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; + } } } } --