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: I3396f713f16980a8b74745a1672fe8b8a2d4abaeriscv-compliance-dev^2
parent
6875379089
commit
b629bbeade
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue