qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Sergey Fedorov <serge.fdrv@gmail.com>
To: Peter Maydell <peter.maydell@linaro.org>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PULL 13/13] target-arm: Fix CPU breakpoint handling
Date: Wed, 21 Oct 2015 21:15:26 +0300	[thread overview]
Message-ID: <5627D63E.5080404@gmail.com> (raw)
In-Reply-To: <1445003887-14475-14-git-send-email-peter.maydell@linaro.org>

On 16.10.2015 16:58, Peter Maydell wrote:
> From: Sergey Fedorov <serge.fdrv@gmail.com>
>
> 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 exception handler.
>
> Generate a call to a helper to check CPU breakpoints and raise an
> exception only if any breakpoint matches architecturally.
>
> Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/helper.h        |  2 ++
>  target-arm/op_helper.c     | 29 ++++++++++++++++++-----------
>  target-arm/translate-a64.c | 17 ++++++++++++-----
>  target-arm/translate.c     | 19 ++++++++++++++-----
>  4 files changed, 46 insertions(+), 21 deletions(-)
>
(snip)
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 1273000..9f1d740 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -11342,11 +11342,20 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
>              CPUBreakpoint *bp;
>              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);
> +                        /* End the TB early; it's likely not going to be executed */
> +                        dc->is_jmp = DISAS_UPDATE;
> +                    } else {
> +                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        /* Advance PC so that clearing the breakpoint will
> +                           invalidate this TB.  */
> +                        /* TODO: Advance PC by correct instruction length to
> +                         * avoid disassembler error messages */
> +                        dc->pc += 2;
> +                        goto done_generating;
> +                    }
> +                    break;
>                  }
>              }
>          }

It turns out that this change introduced an issue which can be
illustrated by the following test:

cat >test.s <<EOF
.text
.global _start
_start:
adr r0, bp
mcr p14, 0, r0, c0, c0, 4 // DBGBVR0
mov r0, #1
orr r0, r0, #(0xf << 5)
mcr p14, 0, r0, c0, c0, 5 // DBGBCR0
bp:
nop
wfi
b .
EOF

arm-linux-gnueabi-as -o test.o test.s
arm-linux-gnueabi-ld -Ttext=0x40000000 -o test.elf test.o
./qemu-system-arm -nographic -machine virt -cpu cortex-a15 -kernel \
test.elf -D qemu.log -d in_asm,exec -singlestep

Actually, that is the same test as in
https://lists.gnu.org/archive/html/qemu-devel/2015-08/msg02715.html but
for AArch32.

Running this test QEMU hangs executing code at the address where
breakpoint is set:

----------------
IN:
0x40000000:  e28f000c      add  r0, pc, #12     ; 0xc

Trace 0x7f7c8bdc0028 [40000000]
----------------
IN:
0x40000004:  ee000e90      mcr  14, 0, r0, cr0, cr0, {4}

Trace 0x7f7c8bdc0070 [40000004]
----------------
IN:
0x40000008:  e3a00001      mov  r0, #1  ; 0x1

Trace 0x7f7c8bdc00b0 [40000008]
----------------
IN:
0x4000000c:  e3800e1e      orr  r0, r0, #480    ; 0x1e0

Trace 0x7f7c8bdc00f0 [4000000c]
----------------
IN:
0x40000010:  ee000eb0      mcr  14, 0, r0, cr0, cr0, {5}

Trace 0x7f7c8bdc0140 [40000010]
----------------
IN:
0x40000014:  e1a00000      nop                  (mov r0,r0)

Trace 0x7f7c8bdc0180 [40000014]
Trace 0x7f7c8bdc0180 [40000014]
Trace 0x7f7c8bdc0180 [40000014]
Trace 0x7f7c8bdc0180 [40000014]
...

I can conclude that it is due to 'dc->is_jmp = DISAS_UPDATE'. With the
following patch everything is okay:

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9f1d740..b55c5c2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11345,7 +11345,6 @@ void gen_intermediate_code(CPUARMState *env,
TranslationBlock *tb)
                     if (bp->flags & BP_CPU) {
                         gen_helper_check_breakpoints(cpu_env);
                         /* End the TB early; it's likely not going to
be executed */
-                        dc->is_jmp = DISAS_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* Advance PC so that clearing the breakpoint will


As far as I understand, we can't do this in target-arm/translate.c
before dc->pc is advanced properly because CPU state's PC doesn't get
updated as in target-arm/translate-a64.c. Compare:

target-arm/translate.c:

        case
DISAS_JUMP:                                                                                              

        case
DISAS_UPDATE:                                                                                            

            /* indicate that the hash table must be used to find the
next TB */                                       
           
tcg_gen_exit_tb(0);                                                                                       

           
break;                                                                                                    



target-arm/translate-a64.c:

        case DISAS_UPDATE:
            gen_a64_set_pc_im(dc->pc);
            /* fall through */
        case DISAS_JUMP:
            /* indicate that the hash table must be used to find the
next TB */
            tcg_gen_exit_tb(0);
            break;

I think we could fix this problem by cleaning up DISAS_UPDATE usage in
target-arm/translate.c and implementing PC update as in
target-arm/translate-a64.c. I could prepare a patch for that.

Another problem, I think, is that we should somehow restore the CPU
state before raising an exception from check_breakpoints() helper. But
so far I have no idea how to fix this...

Any suggestions are highly appreciated :)

Best regards,
Sergey

  reply	other threads:[~2015-10-21 18:15 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-16 13:57 [Qemu-devel] [PULL 00/13] target-arm queue Peter Maydell
2015-10-16 13:57 ` [Qemu-devel] [PULL 01/13] target-arm: Add missing 'static' attribute Peter Maydell
2015-10-16 13:57 ` [Qemu-devel] [PULL 02/13] target-arm: Break the TB after ISB to execute self-modified code correctly Peter Maydell
2015-10-16 13:57 ` [Qemu-devel] [PULL 03/13] target-arm: Avoid calling arm_el_is_aa64() function for unimplemented EL Peter Maydell
2015-10-16 13:57 ` [Qemu-devel] [PULL 04/13] hw/arm/virt: smbios: inform guest of kvm Peter Maydell
2015-10-16 13:57 ` [Qemu-devel] [PULL 05/13] target-arm: Implement AArch64 OSLAR/OSLSR_EL1 sysregs Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 06/13] target-arm: Provide model numbers for Sharp PDAs Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 07/13] arm: imx25-pdk: Fix machine name Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 08/13] misc: zynq_slcr: Fix MMIO writes Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 09/13] target-arm: Add MDCR_EL2 Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 10/13] hw/arm/virt: Allow zero address for PCI IO space Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 11/13] target-arm: implement arm_debug_target_el() Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 12/13] target-arm: Fix GDB breakpoint handling Peter Maydell
2015-10-16 13:58 ` [Qemu-devel] [PULL 13/13] target-arm: Fix CPU " Peter Maydell
2015-10-21 18:15   ` Sergey Fedorov [this message]
2015-11-02 11:09     ` Peter Maydell
2015-11-02 13:38       ` Sergey Fedorov
2015-10-17 14:05 ` [Qemu-devel] [PULL 00/13] target-arm queue Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5627D63E.5080404@gmail.com \
    --to=serge.fdrv@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).