This is an automated email from Gerrit.

"Antonio Borneo <[email protected]>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9561

-- gerrit

commit 1fed82c01c0e6f19795ea326add92f32bba048f5
Author: Antonio Borneo <[email protected]>
Date:   Fri Apr 3 11:27:05 2026 +0200

    cortex_a: allow single step over synchronous watchpoint
    
    The ARMv7-A/R specification reports that watchpoints hit can be
    handled either synchronous or asynchronously.
    
    Synchronous watchpoints halt at the instruction that accessing the
    memory triggers it, without executing the instruction nor the
    associated memory access.
    A command resume or step will then execute again that instruction
    and will trigger the watchpoint again, which is annoying.
    
    Asynchronous watchpoints halt few instructions after the one that
    triggered the watchpoint, when the memory access is already done.
    A command resume or step will correctly execute the following
    instructions.
    
    Modify the single step code to detect the synchronous watchpoints
    case and disable the watchpoint across the single step.
    If the specific watchpoint cannot be detected, then disable all of
    them across the single step.
    
    Change-Id: I24198938271a43fa2438a4bae40ef78968c8bb96
    Signed-off-by: Antonio Borneo <[email protected]>

diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index b64a3c2c5a..f3589f5811 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -67,6 +67,10 @@ static int cortex_a_set_hybrid_breakpoint(struct target 
*target,
        struct breakpoint *breakpoint);
 static int cortex_a_unset_breakpoint(struct target *target,
        struct breakpoint *breakpoint);
+static int cortex_a_set_watchpoint(struct target *target,
+       struct watchpoint *watchpoint);
+static int cortex_a_unset_watchpoint(struct target *target,
+       struct watchpoint *watchpoint);
 static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
        uint32_t value, uint32_t *dscr);
 static int cortex_a_mmu(struct target *target, bool *enabled);
@@ -1334,6 +1338,32 @@ static int cortex_a_step(struct target *target, bool 
current, target_addr_t addr
                return ERROR_OK;
        }
 
+       /*
+        * if halted on precise watchpoint, we need to disable it otherwise
+        * it will be hit again. If cannot detect the specific watchpoint,
+        * then disable all
+        */
+       bool all_wp_disabled = false;
+       struct watchpoint *hit_watchpoint = NULL;
+       if (current && target->debug_reason == DBG_REASON_WATCHPOINT &&
+                       DSCR_ENTRY(cortex_a->cpudbg_dscr) == 
DSCR_ENTRY_PRECISE_WATCHPT) {
+               retval = target_hit_watchpoint(target, &hit_watchpoint);
+               if (retval == ERROR_OK) {
+                       // wp detected, in hit_watchpoint
+                       retval = cortex_a_unset_watchpoint(target, 
hit_watchpoint);
+                       if (retval != ERROR_OK)
+                               return retval;
+               } else {
+                       // cannot detect wp, unset all
+                       for (struct watchpoint *wp = target->watchpoints; wp; 
wp = wp->next) {
+                               retval = cortex_a_unset_watchpoint(target, wp);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
+                       all_wp_disabled = true;
+               }
+       }
+
        /* Setup single step breakpoint */
        stepbreakpoint.address = address;
        stepbreakpoint.asid = 0;
@@ -1403,6 +1433,13 @@ static int cortex_a_step(struct target *target, bool 
current, target_addr_t addr
 
        target->debug_reason = DBG_REASON_BREAKPOINT;
 
+       if (hit_watchpoint)
+               cortex_a_set_watchpoint(target, hit_watchpoint);
+
+       if (all_wp_disabled)
+               for (struct watchpoint *wp = target->watchpoints; wp; wp = 
wp->next)
+                       cortex_a_set_watchpoint(target, wp);
+
        if (breakpoint)
                cortex_a_set_breakpoint(target, breakpoint, 0);
 

-- 

Reply via email to