From b629bbeade8cb430be8d2b899fd521a02419e393 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 22 May 2018 12:32:01 -0700 Subject: 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 --- src/target/riscv/riscv-013.c | 11 ++++++----- src/target/riscv/riscv.c | 11 +++++++++++ src/target/riscv/riscv.h | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index b150b13..5324f1e 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1453,9 +1453,6 @@ static int examine(struct target *target) 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. */ /* TODO: Only do this if the harts were halted to start with. */ riscv_resume_all_harts(target); @@ -1473,8 +1470,8 @@ static int examine(struct target *target) riscv_count_harts(target)); for (int i = 0; i < riscv_count_harts(target); ++i) { if (riscv_hart_enabled(target, i)) { - LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64 ", %d triggers", i, - r->xlen[i], r->misa[i], r->trigger_count[i]); + LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i], + r->misa[i]); } else { 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: return RISCV_HALT_BREAKPOINT; 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; case CSR_DCSR_CAUSE_STEP: return RISCV_HALT_SINGLESTEP; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 88d4b92..b698195 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -407,6 +407,9 @@ static int add_trigger(struct target *target, struct trigger *trigger) { 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 * hart, to keep up the illusion that each hart is a thread running on the * same core. */ @@ -531,6 +534,9 @@ static int remove_trigger(struct target *target, struct trigger *trigger) { RISCV_INFO(r); + if (riscv_enumerate_triggers(target) != ERROR_OK) + return ERROR_FAIL; + int first_hart = -1; for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) @@ -1888,6 +1894,11 @@ int riscv_enumerate_triggers(struct target *target) { 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) { if (!riscv_hart_enabled(target, hartid)) continue; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 63a3b79..1cc32f9 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -87,6 +87,8 @@ typedef struct { /* This hart contains an implicit ebreak at the end of the program buffer. */ bool impebreak; + bool triggers_enumerated; + /* Helper functions that target the various RISC-V debug spec * implementations. */ int (*get_register)(struct target *target, -- cgit v1.1