This is an automated email from Gerrit.

"Daniel Goehring <dgoeh...@os.amperecomputing.com>" just uploaded a new patch 
set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8958

-- gerrit

commit fa7f15dc829077f2541c9017055cec2044657abd
Author: Daniel Goehring <dgoeh...@os.amperecomputing.com>
Date:   Thu Jun 12 18:32:30 2025 -0400

    breakpoint: SMP updates wrt arp_examine support
    
    Modify SMP breakpoint logic to support a per-core granularity.
    
    Before setting and removing breakpoints/watchpoints for a
    processor core contained in a SMP group, verify the core
    is halted and examined.
    
    For software breakpoints, assign the breakpoint to the current
    selected processor target, not the first target in the SMP group.
    
    Also verify at least one target in a SMP group is examined
    before setting the breakpoint/watchpoint.
    
    Change-Id: I9923ed20ea02ad92cce5ea12558f95e0ae1b161a
    Signed-off-by: Daniel Goehring <dgoeh...@os.amperecomputing.com>

diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index a080416291..7f79daf538 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -211,18 +211,25 @@ int breakpoint_add(struct target *target,
        enum breakpoint_type type)
 {
        if (target->smp) {
+               bool breakpoint_set = false;
                struct target_list *head;
 
-               if (type == BKPT_SOFT) {
-                       head = list_first_entry(target->smp_targets, struct 
target_list, lh);
-                       return breakpoint_add_internal(head->target, address, 
length, type);
-               }
+               if (type == BKPT_SOFT)
+                       return breakpoint_add_internal(target, address, length, 
type);
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int retval = breakpoint_add_internal(curr, address, 
length, type);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int retval = breakpoint_add_internal(curr, 
address, length, type);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               breakpoint_set = true;
+                       }
+               }
+
+               if (!breakpoint_set) {
+                       LOG_ERROR("Unable to set breakpoint. All SMP targets 
are in the examine deferred state.");
+                       return ERROR_FAIL;
                }
 
                return ERROR_OK;
@@ -237,13 +244,22 @@ int context_breakpoint_add(struct target *target,
        enum breakpoint_type type)
 {
        if (target->smp) {
+               bool breakpoint_set = false;
                struct target_list *head;
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int retval = context_breakpoint_add_internal(curr, 
asid, length, type);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int retval = 
context_breakpoint_add_internal(curr, asid, length, type);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               breakpoint_set = true;
+                       }
+               }
+
+               if (!breakpoint_set) {
+                       LOG_ERROR("Unable to set context breakpoint. All SMP 
targets are in the examine deferred state.");
+                       return ERROR_FAIL;
                }
 
                return ERROR_OK;
@@ -259,13 +275,22 @@ int hybrid_breakpoint_add(struct target *target,
        enum breakpoint_type type)
 {
        if (target->smp) {
+               bool breakpoint_set = false;
                struct target_list *head;
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int retval = hybrid_breakpoint_add_internal(curr, 
address, asid, length, type);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int retval = 
hybrid_breakpoint_add_internal(curr, address, asid, length, type);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               breakpoint_set = true;
+                       }
+               }
+
+               if (!breakpoint_set) {
+                       LOG_ERROR("Unable to set hybrid breakpoint. All SMP 
targets are in the examine deferred state.");
+                       return ERROR_FAIL;
                }
 
                return ERROR_OK;
@@ -350,18 +375,19 @@ int breakpoint_remove(struct target *target, 
target_addr_t address)
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int status = breakpoint_remove_internal(curr, address);
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int status = breakpoint_remove_internal(curr, 
address);
 
-                       if (status != ERROR_BREAKPOINT_NOT_FOUND) {
-                               num_found_breakpoints++;
+                               if (status != ERROR_BREAKPOINT_NOT_FOUND) {
+                                       num_found_breakpoints++;
 
-                               if (status != ERROR_OK) {
-                                       LOG_TARGET_ERROR(curr, "failed to 
remove breakpoint at address " TARGET_ADDR_FMT, address);
-                                       retval = status;
+                                       if (status != ERROR_OK) {
+                                               LOG_TARGET_ERROR(curr, "failed 
to remove breakpoint at address " TARGET_ADDR_FMT, address);
+                                               retval = status;
+                                       }
                                }
                        }
                }
-
        } else {
                retval = breakpoint_remove_internal(target, address);
 
@@ -396,6 +422,7 @@ static int watchpoint_free(struct target *target, struct 
watchpoint *watchpoint_
 
        if (!watchpoint)
                return ERROR_OK;
+
        retval = target_remove_watchpoint(target, watchpoint);
        if (retval != ERROR_OK) {
                LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on 
this target",
@@ -436,14 +463,16 @@ static int breakpoint_watchpoint_remove_all(struct target 
*target, enum breakpoi
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
 
-                       int status = ERROR_OK;
-                       if (bp_wp == BREAKPOINT)
-                               status = breakpoint_remove_all_internal(curr);
-                       else
-                               status = watchpoint_remove_all_internal(curr);
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int status = ERROR_OK;
+                               if (bp_wp == BREAKPOINT)
+                                       status = 
breakpoint_remove_all_internal(curr);
+                               else
+                                       status = 
watchpoint_remove_all_internal(curr);
 
-                       if (status != ERROR_OK)
-                               retval = status;
+                               if (status != ERROR_OK)
+                                       retval = status;
+                       }
                }
        } else {
                if (bp_wp == BREAKPOINT)
@@ -468,16 +497,18 @@ int watchpoint_remove_all(struct target *target)
 int breakpoint_clear_target(struct target *target)
 {
        int retval = ERROR_OK;
-
        if (target->smp) {
                struct target_list *head;
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int status = breakpoint_remove_all_internal(curr);
 
-                       if (status != ERROR_OK)
-                               retval = status;
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int status = 
breakpoint_remove_all_internal(curr);
+
+                               if (status != ERROR_OK)
+                                       retval = status;
+                       }
                }
        } else {
                retval = breakpoint_remove_all_internal(target);
@@ -569,13 +600,22 @@ int watchpoint_add(struct target *target, target_addr_t 
address,
                unsigned int length, enum watchpoint_rw rw, uint64_t value, 
uint64_t mask)
 {
        if (target->smp) {
+               bool watchpoint_set = false;
                struct target_list *head;
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int retval = watchpoint_add_internal(curr, address, 
length, rw, value, mask);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int retval = watchpoint_add_internal(curr, 
address, length, rw, value, mask);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               watchpoint_set = true;
+                       }
+               }
+
+               if (!watchpoint_set) {
+                       LOG_ERROR("Unable to set watchpoint. All SMP targets 
are in the examine deferred state.");
+                       return ERROR_FAIL;
                }
 
                return ERROR_OK;
@@ -611,14 +651,16 @@ int watchpoint_remove(struct target *target, 
target_addr_t address)
 
                foreach_smp_target(head, target->smp_targets) {
                        struct target *curr = head->target;
-                       int status = watchpoint_remove_internal(curr, address);
+                       if (target_was_examined(curr) && curr->state == 
TARGET_HALTED) {
+                               int status = watchpoint_remove_internal(curr, 
address);
 
-                       if (status != ERROR_WATCHPOINT_NOT_FOUND) {
-                               num_found_watchpoints++;
+                               if (status != ERROR_WATCHPOINT_NOT_FOUND) {
+                                       num_found_watchpoints++;
 
-                               if (status != ERROR_OK) {
-                                       LOG_TARGET_ERROR(curr, "failed to 
remove watchpoint at address " TARGET_ADDR_FMT, address);
-                                       retval = status;
+                                       if (status != ERROR_OK) {
+                                               LOG_TARGET_ERROR(curr, "failed 
to remove watchpoint at address " TARGET_ADDR_FMT, address);
+                                               retval = status;
+                                       }
                                }
                        }
                }

-- 

Reply via email to