qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 02/19] target-arm: Implement handling of breakpoint firing
Date: Mon, 29 Sep 2014 19:26:36 +0100	[thread overview]
Message-ID: <1412015213-22268-3-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1412015213-22268-1-git-send-email-peter.maydell@linaro.org>

Implement handling of breakpoint event firing to correctly
inject the debug exception into the guest.

Since the breakpoint and watchpoint control register format is
very similar we adjust wp_matches() to also handle breakpoints
as well rather than using a separate function.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1410523465-13400-3-git-send-email-peter.maydell@linaro.org
---
 target-arm/internals.h |  6 ++++
 target-arm/op_helper.c | 75 ++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/target-arm/internals.h b/target-arm/internals.h
index b7e4822..986a7b1 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -313,6 +313,12 @@ static inline uint32_t syn_watchpoint(int same_el, int cm, int wnr)
         | (cm << 8) | (wnr << 6) | 0x22;
 }
 
+static inline uint32_t syn_breakpoint(int same_el)
+{
+    return (EC_BREAKPOINT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
+        | ARM_EL_IL | 0x22;
+}
+
 /* Update a QEMU watchpoint based on the information the guest has set in the
  * DBGWCR<n>_EL1 and DBGWVR<n>_EL1 registers.
  */
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index b956216..d0bcd97 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -511,32 +511,43 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
     return false;
 }
 
-static bool wp_matches(ARMCPU *cpu, int n)
+static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
 {
     CPUARMState *env = &cpu->env;
-    uint64_t wcr = env->cp15.dbgwcr[n];
+    uint64_t cr;
     int pac, hmc, ssc, wt, lbn;
     /* TODO: check against CPU security state when we implement TrustZone */
     bool is_secure = false;
 
-    if (!env->cpu_watchpoint[n]
-        || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
-        return false;
-    }
+    if (is_wp) {
+        if (!env->cpu_watchpoint[n]
+            || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
+            return false;
+        }
+        cr = env->cp15.dbgwcr[n];
+    } else {
+        uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
 
+        if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {
+            return false;
+        }
+        cr = env->cp15.dbgbcr[n];
+    }
     /* The WATCHPOINT_HIT flag guarantees us that the watchpoint is
-     * enabled and that the address and access type match; check the
-     * remaining fields, including linked breakpoints.
-     * Note that some combinations of {PAC, HMC SSC} are reserved and
+     * enabled and that the address and access type match; for breakpoints
+     * we know the address matched; check the remaining fields, including
+     * linked breakpoints. We rely on WCR and BCR having the same layout
+     * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.
+     * Note that some combinations of {PAC, HMC, SSC} are reserved and
      * must act either like some valid combination or as if the watchpoint
      * were disabled. We choose the former, and use this together with
      * the fact that EL3 must always be Secure and EL2 must always be
      * Non-Secure to simplify the code slightly compared to the full
      * table in the ARM ARM.
      */
-    pac = extract64(wcr, 1, 2);
-    hmc = extract64(wcr, 13, 1);
-    ssc = extract64(wcr, 14, 2);
+    pac = extract64(cr, 1, 2);
+    hmc = extract64(cr, 13, 1);
+    ssc = extract64(cr, 14, 2);
 
     switch (ssc) {
     case 0:
@@ -560,6 +571,7 @@ static bool wp_matches(ARMCPU *cpu, int n)
      * Implementing this would require reworking the core watchpoint code
      * to plumb the mmu_idx through to this point. Luckily Linux does not
      * rely on this behaviour currently.
+     * For breakpoints we do want to use the current CPU state.
      */
     switch (arm_current_pl(env)) {
     case 3:
@@ -582,8 +594,8 @@ static bool wp_matches(ARMCPU *cpu, int n)
         g_assert_not_reached();
     }
 
-    wt = extract64(wcr, 20, 1);
-    lbn = extract64(wcr, 16, 4);
+    wt = extract64(cr, 20, 1);
+    lbn = extract64(cr, 16, 4);
 
     if (wt && !linked_bp_matches(cpu, lbn)) {
         return false;
@@ -606,7 +618,28 @@ static bool check_watchpoints(ARMCPU *cpu)
     }
 
     for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {
-        if (wp_matches(cpu, n)) {
+        if (bp_wp_matches(cpu, n, true)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool check_breakpoints(ARMCPU *cpu)
+{
+    CPUARMState *env = &cpu->env;
+    int n;
+
+    /* If breakpoints are disabled globally or we can't take debug
+     * exceptions here then breakpoint firings are ignored.
+     */
+    if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
+        || !arm_generate_debug_exceptions(env)) {
+        return false;
+    }
+
+    for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
+        if (bp_wp_matches(cpu, n, false)) {
             return true;
         }
     }
@@ -641,6 +674,18 @@ void arm_debug_excp_handler(CPUState *cs)
                 cpu_resume_from_signal(cs, NULL);
             }
         }
+    } else {
+        if (check_breakpoints(cpu)) {
+            bool same_el = (arm_debug_target_el(env) == arm_current_pl(env));
+            env->exception.syndrome = syn_breakpoint(same_el);
+            if (extended_addresses_enabled(env)) {
+                env->exception.fsr = (1 << 9) | 0x22;
+            } else {
+                env->exception.fsr = 0x2;
+            }
+            /* FAR is UNKNOWN, so doesn't need setting */
+            raise_exception(env, EXCP_PREFETCH_ABORT);
+        }
     }
 }
 
-- 
1.9.1

  parent reply	other threads:[~2014-09-29 18:27 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-29 18:26 [Qemu-devel] [PULL 00/19] target-arm queue Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 01/19] target-arm: Implement setting guest breakpoints Peter Maydell
2014-09-29 18:26 ` Peter Maydell [this message]
2014-09-29 18:26 ` [Qemu-devel] [PULL 03/19] configure: Build GDB XML for 32 bit ARM CPUs into qemu aarch64 binaries Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 04/19] hw/display/blizzard.c: Delete unused function blizzard_rgb2yuv Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 05/19] hw/intc/imx_avic.c: Remove unused function imx_avic_set_prio() Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 06/19] hw/display/pxa2xx_lcd.c: Remove unused function pxa2xx_dma_rdst_set Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 07/19] hw/input/tsc210x.c: Delete unused array tsc2101_rates Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 08/19] target-arm: Don't handle c15_cpar changes via tb_flush() Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 09/19] target-arm: Add HCR_EL2 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 10/19] target-arm: Add SCR_EL3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 11/19] target-arm: A64: Refactor aarch64_cpu_do_interrupt Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 12/19] target-arm: Break out exception masking to a separate func Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 13/19] target-arm: Don't take interrupts targeting lower ELs Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 14/19] target-arm: A64: Correct updates to FAR and ESR on exceptions Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 15/19] target-arm: A64: Emulate the HVC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 16/19] target-arm: Add a Hypervisor Trap exception type Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 17/19] target-arm: A64: Emulate the SMC insn Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 18/19] target-arm: Add IRQ and FIQ routing to EL2 and 3 Peter Maydell
2014-09-29 18:26 ` [Qemu-devel] [PULL 19/19] target-arm: Add support for VIRQ and VFIQ Peter Maydell
2014-09-30 10:52 ` [Qemu-devel] [PULL 00/19] 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=1412015213-22268-3-git-send-email-peter.maydell@linaro.org \
    --to=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).