diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 9f2b9d5fe..9d7d77b83 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1718,7 +1718,7 @@ struct target_type riscv013_target = /*** 0.13-specific implementations of various RISC-V helper functions. ***/ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid) { - LOG_DEBUG("reading register 0x%08x on hart %d", rid, hid); + LOG_DEBUG("reading register %s on hart %d", gdb_regno_name(rid), hid); riscv_set_current_hartid(target, hid); @@ -1750,7 +1750,8 @@ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid static void riscv013_set_register(struct target *target, int hid, int rid, uint64_t value) { - LOG_DEBUG("writing register 0x%08x on hart %d", rid, hid); + LOG_DEBUG("writing 0x%" PRIx64 " to register %s on hart %d", value, + gdb_regno_name(rid), hid); riscv_set_current_hartid(target, hid); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 491996bf1..a8fc4378c 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -394,31 +394,43 @@ static int add_trigger(struct target *target, struct trigger *trigger) { RISCV_INFO(r); + // 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. + + // Otherwise, we just set the trigger on the one hart this target deals + // with. + riscv_reg_t tselect[RISCV_MAX_HARTS]; + int first_hart = -1; for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; + if (first_hart < 0) + first_hart = hartid; tselect[hartid] = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT); } + assert(first_hart >= 0); unsigned int i; - for (i = 0; i < r->trigger_count[0]; i++) { + for (i = 0; i < r->trigger_count[first_hart]; i++) { if (r->trigger_unique_id[i] != -1) { continue; } - riscv_set_register_on_hart(target, 0, GDB_REGNO_TSELECT, i); + riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i); - uint64_t tdata1 = riscv_get_register_on_hart(target, 0, GDB_REGNO_TDATA1); + uint64_t tdata1 = riscv_get_register_on_hart(target, first_hart, GDB_REGNO_TDATA1); int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); int result = ERROR_OK; - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { + LOG_DEBUG(">>> hartid=%d", hartid); if (!riscv_hart_enabled(target, hartid)) continue; - if (hartid > 0) { + if (hartid > first_hart) { riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i); } switch (type) { @@ -448,14 +460,14 @@ static int add_trigger(struct target *target, struct trigger *trigger) break; } - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect[hartid]); } - if (i >= r->trigger_count[0]) { + if (i >= r->trigger_count[first_hart]) { LOG_ERROR("Couldn't find an available hardware trigger."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -507,19 +519,30 @@ static int remove_trigger(struct target *target, struct trigger *trigger) { RISCV_INFO(r); + int first_hart = -1; + for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + if (!riscv_hart_enabled(target, hartid)) + continue; + if (first_hart < 0) { + first_hart = hartid; + break; + } + } + assert(first_hart >= 0); + unsigned int i; - for (i = 0; i < r->trigger_count[0]; i++) { + for (i = 0; i < r->trigger_count[first_hart]; i++) { if (r->trigger_unique_id[i] == trigger->unique_id) { break; } } - if (i >= r->trigger_count[0]) { + if (i >= r->trigger_count[first_hart]) { LOG_ERROR("Couldn't find the hardware resources used by hardware " "trigger."); return ERROR_FAIL; } LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id); - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index d84e51ceb..1197cbfbc 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -67,7 +67,9 @@ typedef struct { unsigned trigger_count[RISCV_MAX_HARTS]; /* For each physical trigger, contains -1 if the hwbp is available, or the - * unique_id of the breakpoint/watchpoint that is using it. */ + * unique_id of the breakpoint/watchpoint that is using it. + * Note that in RTOS mode the triggers are the same across all harts the + * target controls, while otherwise only a single hart is controlled. */ int trigger_unique_id[RISCV_MAX_HWBPS]; /* The address of the debug RAM buffer. */