Skip to content

Commit c2fdc38

Browse files
tom-vanborneoa
authored andcommitted
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]> Reviewed-on: https://review.openocd.org/c/openocd/+/9246 Reviewed-by: Antonio Borneo <[email protected]> Tested-by: jenkins
1 parent 1ca34e2 commit c2fdc38

File tree

1 file changed

+46
-21
lines changed

1 file changed

+46
-21
lines changed

src/target/aarch64.c

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ struct aarch64_private_config {
3939
struct arm_cti *cti;
4040
};
4141

42-
static int aarch64_poll_smp(struct target *target, bool smp);
42+
static int aarch64_poll_smp(struct target *target, bool smp,
43+
bool postpone_event);
4344
static int aarch64_debug_entry(struct target *target);
4445
static int aarch64_restore_context(struct target *target, bool bpwp);
4546
static int aarch64_set_breakpoint(struct target *target,
@@ -471,7 +472,6 @@ static int aarch64_halt_smp(struct target *target, bool exc_target)
471472

472473
static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reason debug_reason)
473474
{
474-
struct target *gdb_target = NULL;
475475
struct target_list *head;
476476
struct target *curr;
477477

@@ -480,7 +480,7 @@ static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reas
480480
aarch64_halt_smp(target, true);
481481
}
482482

483-
/* poll all targets in the group, but skip the target that serves GDB */
483+
/* poll all targets in the group */
484484
foreach_smp_target(head, target->smp_targets) {
485485
curr = head->target;
486486
/* skip calling context */
@@ -491,31 +491,43 @@ static int aarch64_update_halt_gdb(struct target *target, enum target_debug_reas
491491
/* skip targets that were already halted */
492492
if (curr->state == TARGET_HALTED)
493493
continue;
494-
/* remember the gdb_service->target */
495-
if (curr->gdb_service)
496-
gdb_target = curr->gdb_service->target;
497-
/* skip it */
498-
if (curr == gdb_target)
499-
continue;
500494

501495
const bool smp = false;
502-
aarch64_poll_smp(curr, smp);
503-
}
504-
505-
/* after all targets were updated, poll the gdb serving target */
506-
if (gdb_target && gdb_target != target) {
507-
const bool smp = false;
508-
aarch64_poll_smp(gdb_target, smp);
496+
const bool postpone_event = true;
497+
aarch64_poll_smp(curr, smp, postpone_event);
509498
}
510499

511500
return ERROR_OK;
512501
}
513502

503+
enum postponed_halt_events_op {
504+
POSTPONED_HALT_EVENT_CLEAR,
505+
POSTPONED_HALT_EVENT_EMIT
506+
};
507+
508+
static void aarch64_smp_postponed_halt_events(struct list_head *smp_targets,
509+
enum postponed_halt_events_op op)
510+
{
511+
struct target_list *head;
512+
foreach_smp_target(head, smp_targets) {
513+
struct target *t = head->target;
514+
if (!t->smp_halt_event_postponed)
515+
continue;
516+
517+
if (op == POSTPONED_HALT_EVENT_EMIT) {
518+
LOG_TARGET_DEBUG(t, "sending postponed target event 'halted'");
519+
target_call_event_callbacks(t, TARGET_EVENT_HALTED);
520+
}
521+
t->smp_halt_event_postponed = false;
522+
}
523+
}
524+
514525
/*
515526
* Aarch64 Run control
516527
*/
517528

518-
static int aarch64_poll_smp(struct target *target, bool smp)
529+
static int aarch64_poll_smp(struct target *target, bool smp,
530+
bool postpone_event)
519531
{
520532
struct armv8_common *armv8 = target_to_armv8(target);
521533
enum target_state prev_target_state;
@@ -553,21 +565,33 @@ static int aarch64_poll_smp(struct target *target, bool smp)
553565
if (smp)
554566
aarch64_update_halt_gdb(target, debug_reason);
555567

556-
if (arm_semihosting(target, &retval) != 0)
568+
if (arm_semihosting(target, &retval) != 0) {
569+
if (smp)
570+
aarch64_smp_postponed_halt_events(target->smp_targets,
571+
POSTPONED_HALT_EVENT_CLEAR);
572+
557573
return retval;
574+
}
558575

559576
switch (prev_target_state) {
560577
case TARGET_RUNNING:
561578
case TARGET_UNKNOWN:
562579
case TARGET_RESET:
563-
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
580+
if (postpone_event)
581+
target->smp_halt_event_postponed = true;
582+
else
583+
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
564584
break;
565585
case TARGET_DEBUG_RUNNING:
566586
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
567587
break;
568588
default:
569589
break;
570590
}
591+
592+
if (smp)
593+
aarch64_smp_postponed_halt_events(target->smp_targets,
594+
POSTPONED_HALT_EVENT_EMIT);
571595
}
572596
} else if (prsr & PRSR_RESET) {
573597
target->state = TARGET_RESET;
@@ -580,7 +604,8 @@ static int aarch64_poll_smp(struct target *target, bool smp)
580604

581605
static int aarch64_poll(struct target *target)
582606
{
583-
return aarch64_poll_smp(target, target->smp != 0);
607+
const bool postpone_event = false;
608+
return aarch64_poll_smp(target, target->smp != 0, postpone_event);
584609
}
585610

586611
static int aarch64_halt(struct target *target)
@@ -866,7 +891,7 @@ static int aarch64_step_restart_smp(struct target *target)
866891
retval = aarch64_do_restart_one(curr, RESTART_LAZY);
867892
if (retval != ERROR_OK)
868893
break;
869-
}
894+
}
870895

871896
return retval;
872897
}

0 commit comments

Comments
 (0)