Delay trigger enumeration until it's required.

This improves startup time, which is important when connecting to
simulators. One problem is that triggers that are set when the debugger
connects are not cleared until enumeration happens. Execution may halt
due to a trigger set by a previous debug session, which could confuse
the user. If this happens, triggers will be instantly enumerated, so it
will only happen once per session.

Change-Id: I3396f713f16980a8b74745a1672fe8b8a2d4abae
riscv-compliance-dev^2
Tim Newsome 2018-05-22 12:32:01 -07:00
parent 6875379089
commit b629bbeade
3 changed files with 19 additions and 5 deletions

View File

@ -1453,9 +1453,6 @@ static int examine(struct target *target)
return ERROR_FAIL; return ERROR_FAIL;
} }
/* Then we check the number of triggers availiable to each hart. */
riscv_enumerate_triggers(target);
/* Resumes all the harts, so the debugger can later pause them. */ /* Resumes all the harts, so the debugger can later pause them. */
/* TODO: Only do this if the harts were halted to start with. */ /* TODO: Only do this if the harts were halted to start with. */
riscv_resume_all_harts(target); riscv_resume_all_harts(target);
@ -1473,8 +1470,8 @@ static int examine(struct target *target)
riscv_count_harts(target)); riscv_count_harts(target));
for (int i = 0; i < riscv_count_harts(target); ++i) { for (int i = 0; i < riscv_count_harts(target); ++i) {
if (riscv_hart_enabled(target, i)) { if (riscv_hart_enabled(target, i)) {
LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64 ", %d triggers", i, LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i],
r->xlen[i], r->misa[i], r->trigger_count[i]); r->misa[i]);
} else { } else {
LOG_INFO(" hart %d: currently disabled", i); LOG_INFO(" hart %d: currently disabled", i);
} }
@ -2826,6 +2823,10 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
case CSR_DCSR_CAUSE_SWBP: case CSR_DCSR_CAUSE_SWBP:
return RISCV_HALT_BREAKPOINT; return RISCV_HALT_BREAKPOINT;
case CSR_DCSR_CAUSE_TRIGGER: case CSR_DCSR_CAUSE_TRIGGER:
/* We could get here before triggers are enumerated if a trigger was
* already set when we connected. Force enumeration now, which has the
* side effect of clearing any triggers we did not set. */
riscv_enumerate_triggers(target);
return RISCV_HALT_TRIGGER; return RISCV_HALT_TRIGGER;
case CSR_DCSR_CAUSE_STEP: case CSR_DCSR_CAUSE_STEP:
return RISCV_HALT_SINGLESTEP; return RISCV_HALT_SINGLESTEP;

View File

@ -407,6 +407,9 @@ static int add_trigger(struct target *target, struct trigger *trigger)
{ {
RISCV_INFO(r); RISCV_INFO(r);
if (riscv_enumerate_triggers(target) != ERROR_OK)
return ERROR_FAIL;
/* In RTOS mode, we need to set the same trigger in the same slot on every /* In RTOS mode, we need to set the same trigger in the same slot on every
* hart, to keep up the illusion that each hart is a thread running on the * hart, to keep up the illusion that each hart is a thread running on the
* same core. */ * same core. */
@ -531,6 +534,9 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
{ {
RISCV_INFO(r); RISCV_INFO(r);
if (riscv_enumerate_triggers(target) != ERROR_OK)
return ERROR_FAIL;
int first_hart = -1; int first_hart = -1;
for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) {
if (!riscv_hart_enabled(target, hartid)) if (!riscv_hart_enabled(target, hartid))
@ -1888,6 +1894,11 @@ int riscv_enumerate_triggers(struct target *target)
{ {
RISCV_INFO(r); RISCV_INFO(r);
if (r->triggers_enumerated)
return ERROR_OK;
r->triggers_enumerated = true; /* At the very least we tried. */
for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) {
if (!riscv_hart_enabled(target, hartid)) if (!riscv_hart_enabled(target, hartid))
continue; continue;

View File

@ -87,6 +87,8 @@ typedef struct {
/* This hart contains an implicit ebreak at the end of the program buffer. */ /* This hart contains an implicit ebreak at the end of the program buffer. */
bool impebreak; bool impebreak;
bool triggers_enumerated;
/* Helper functions that target the various RISC-V debug spec /* Helper functions that target the various RISC-V debug spec
* implementations. */ * implementations. */
int (*get_register)(struct target *target, int (*get_register)(struct target *target,