qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] target-arm: fix CPU breakpoint handling


From: Peter Maydell
Subject: Re: [Qemu-devel] [PATCH] target-arm: fix CPU breakpoint handling
Date: Fri, 18 Sep 2015 14:50:01 +0100

On 14 September 2015 at 11:51, Sergey Fedorov <address@hidden> wrote:
> A QEMU breakpoint match is not definitely an architectural breakpoint
> match. If an exception is generated unconditionally during translation,
> it is hardly possible to ignore it in the debug exceptoin hanlder.

"exception".

>
> Generate a call to helper to check CPU breakpoints and raise an
> exception only if any breakpoint architecturally matches.
>
> Signed-off-by: Sergey Fedorov <address@hidden>
> ---
>  target-arm/helper.h        |  2 ++
>  target-arm/op_helper.c     | 20 +++++++++++++++++++-
>  target-arm/translate-a64.c | 12 +++++++-----
>  target-arm/translate.c     | 12 +++++++-----
>  4 files changed, 35 insertions(+), 11 deletions(-)
>
> diff --git a/target-arm/helper.h b/target-arm/helper.h
> index 827b33d..c2a85c7 100644
> --- a/target-arm/helper.h
> +++ b/target-arm/helper.h
> @@ -54,6 +54,8 @@ DEF_HELPER_1(yield, void, env)
>  DEF_HELPER_1(pre_hvc, void, env)
>  DEF_HELPER_2(pre_smc, void, env, i32)
>
> +DEF_HELPER_1(check_breakpoints, void, env)
> +
>  DEF_HELPER_3(cpsr_write, void, env, i32, i32)
>  DEF_HELPER_1(cpsr_read, i32, env)
>
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index b298e57..24dcefd 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -877,6 +877,15 @@ bool arm_debug_check_watchpoint(CPUState *cs)
>      return check_watchpoints(cpu);
>  }
>
> +void HELPER(check_breakpoints)(CPUARMState *env)
> +{
> +    ARMCPU *cpu = arm_env_get_cpu(env);
> +
> +    if (check_breakpoints(cpu)) {
> +        HELPER(exception_internal(env, EXCP_DEBUG));
> +    }
> +}
> +
>  void arm_debug_excp_handler(CPUState *cs)
>  {
>      /* Called by core code when a watchpoint or breakpoint fires;
> @@ -904,7 +913,16 @@ void arm_debug_excp_handler(CPUState *cs)
>                      arm_debug_target_el(env));
>          }
>      } else {
> -        if (check_breakpoints(cpu)) {
> +        CPUBreakpoint *bp;
> +        uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
> +
> +        QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
> +            if (bp->pc == pc && !(bp->flags & BP_CPU)) {
> +                return;
> +            }
> +        }

This extra code looks right, but isn't it fixing a different bug?

> +
> +        {

Rather than adding the extra block I would just de-indent the code
that used to live inside the if() and move the variable declaration
to the top of the new block.

>              bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
>              if (extended_addresses_enabled(env)) {
>                  env->exception.fsr = (1 << 9) | 0x22;
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 5c13e15..a5927fd 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -11000,11 +11000,13 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
>          if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
>              QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
>                  if (bp->pc == dc->pc) {
> -                    gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> -                    /* Advance PC so that clearing the breakpoint will
> -                       invalidate this TB.  */
> -                    dc->pc += 2;
> -                    goto done_generating;
> +                    if (bp->flags & BP_CPU) {
> +                        gen_helper_check_breakpoints(cpu_env);
> +                        break;
> +                    } else {
> +                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        goto done_generating;
> +                    }

You seem to have dropped the "advance the PC" code -- why is that ok?

thanks
-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]