This is an automated email from Gerrit. "Tomas Vanek <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9246
-- gerrit commit 591687564c0c466cee1c900748aa8abe335e930b Author: Tomas Vanek <[email protected]> Date: Fri Nov 21 12:21:16 2025 +0100 target/aarch64: fix semihosting on SMP Semihosting worked only on the first/gdb assigned core of a SMP group. If a semihosting call was issued on another core, aarch64_update_halt_gdb() emitted 'halted' event on core0 before semihosting decoding started. Use target's smp_halt_event_postponed flag to keep events from emitting until semihosting is decoded. If a semihosting call is confirmed, clear flags and do not send 'halted' event for any core of SMP group. Change-Id: Ie7eff7e493c2a4df3039f49fce1744d996050a59 Signed-off-by: Tomas Vanek <[email protected]> diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 4910714ba9..74df97c274 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -39,7 +39,8 @@ struct aarch64_private_config { struct arm_cti *cti; }; -static int aarch64_poll_smp(struct target *target, bool smp); +static int aarch64_poll_smp(struct target *target, bool smp, + bool postpone_event); static int aarch64_debug_entry(struct target *target); static int aarch64_restore_context(struct target *target, bool bpwp); static int aarch64_set_breakpoint(struct target *target, @@ -471,7 +472,6 @@ static int aarch64_halt_smp(struct target *target, bool exc_target) static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reason debug_reason) { - struct target *gdb_target = NULL; struct target_list *head; struct target *curr; @@ -480,7 +480,7 @@ static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reas aarch64_halt_smp(target, true); } - /* poll all targets in the group, but skip the target that serves GDB */ + /* poll all targets in the group */ foreach_smp_target(head, target->smp_targets) { curr = head->target; /* skip calling context */ @@ -491,31 +491,43 @@ static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reas /* skip targets that were already halted */ if (curr->state == TARGET_HALTED) continue; - /* remember the gdb_service->target */ - if (curr->gdb_service) - gdb_target = curr->gdb_service->target; - /* skip it */ - if (curr == gdb_target) - continue; const bool smp = false; - aarch64_poll_smp(curr, smp); - } - - /* after all targets were updated, poll the gdb serving target */ - if (gdb_target && gdb_target != target) { - const bool smp = false; - aarch64_poll_smp(gdb_target, smp); + const bool postpone_event = true; + aarch64_poll_smp(curr, smp, postpone_event); } return ERROR_OK; } +enum postponed_halt_events_op { + POSTPONED_HALT_EVENT_CLEAR, + POSTPONED_HALT_EVENT_EMIT +}; + +static void aarch64_smp_postponed_halt_events(struct list_head *smp_targets, + enum postponed_halt_events_op op) +{ + struct target_list *head; + foreach_smp_target(head, smp_targets) { + struct target *t = head->target; + if (!t->smp_halt_event_postponed) + continue; + + if (op == POSTPONED_HALT_EVENT_EMIT) { + LOG_TARGET_DEBUG(t, "sending postponed target event 'halted'"); + target_call_event_callbacks(t, TARGET_EVENT_HALTED); + } + t->smp_halt_event_postponed = false; + } +} + /* * Aarch64 Run control */ -static int aarch64_poll_smp(struct target *target, bool smp) +static int aarch64_poll_smp(struct target *target, bool smp, + bool postpone_event) { struct armv8_common *armv8 = target_to_armv8(target); enum target_state prev_target_state; @@ -553,14 +565,22 @@ static int aarch64_poll_smp(struct target *target, bool smp) if (smp) aarch64_update_halt_gdb(target, debug_reason); - if (arm_semihosting(target, &retval) != 0) + if (arm_semihosting(target, &retval) != 0) { + if (smp) + aarch64_smp_postponed_halt_events(target->smp_targets, + POSTPONED_HALT_EVENT_CLEAR); + return retval; + } switch (prev_target_state) { case TARGET_RUNNING: case TARGET_UNKNOWN: case TARGET_RESET: - target_call_event_callbacks(target, TARGET_EVENT_HALTED); + if (postpone_event) + target->smp_halt_event_postponed = true; + else + target_call_event_callbacks(target, TARGET_EVENT_HALTED); break; case TARGET_DEBUG_RUNNING: target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); @@ -568,6 +588,10 @@ static int aarch64_poll_smp(struct target *target, bool smp) default: break; } + + if (smp) + aarch64_smp_postponed_halt_events(target->smp_targets, + POSTPONED_HALT_EVENT_EMIT); } } else if (prsr & PRSR_RESET) { target->state = TARGET_RESET; @@ -580,7 +604,8 @@ static int aarch64_poll_smp(struct target *target, bool smp) static int aarch64_poll(struct target *target) { - return aarch64_poll_smp(target, target->smp != 0); + const bool postpone_event = false; + return aarch64_poll_smp(target, target->smp != 0, postpone_event); } static int aarch64_halt(struct target *target) @@ -866,7 +891,7 @@ static int aarch64_step_restart_smp(struct target *target) retval = aarch64_do_restart_one(curr, RESTART_LAZY); if (retval != ERROR_OK) break; -} + } return retval; } --
