Merge pull request #116 from riscv/multigdb
Fix trigger code to work with multi-gdb mode instead of RTOS mode
This commit is contained in:
commit
a3c26250bf
|
@ -1718,7 +1718,7 @@ struct target_type riscv013_target =
|
||||||
/*** 0.13-specific implementations of various RISC-V helper functions. ***/
|
/*** 0.13-specific implementations of various RISC-V helper functions. ***/
|
||||||
static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid)
|
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);
|
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)
|
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);
|
riscv_set_current_hartid(target, hid);
|
||||||
|
|
||||||
|
|
|
@ -394,31 +394,43 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
||||||
{
|
{
|
||||||
RISCV_INFO(r);
|
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];
|
riscv_reg_t tselect[RISCV_MAX_HARTS];
|
||||||
|
|
||||||
|
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))
|
||||||
continue;
|
continue;
|
||||||
|
if (first_hart < 0)
|
||||||
|
first_hart = hartid;
|
||||||
tselect[hartid] = riscv_get_register_on_hart(target, hartid,
|
tselect[hartid] = riscv_get_register_on_hart(target, hartid,
|
||||||
GDB_REGNO_TSELECT);
|
GDB_REGNO_TSELECT);
|
||||||
}
|
}
|
||||||
|
assert(first_hart >= 0);
|
||||||
|
|
||||||
unsigned int i;
|
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) {
|
if (r->trigger_unique_id[i] != -1) {
|
||||||
continue;
|
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 type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
|
||||||
|
|
||||||
int result = ERROR_OK;
|
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))
|
if (!riscv_hart_enabled(target, hartid))
|
||||||
continue;
|
continue;
|
||||||
if (hartid > 0) {
|
if (hartid > first_hart) {
|
||||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
|
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -448,14 +460,14 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
||||||
break;
|
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))
|
if (!riscv_hart_enabled(target, hartid))
|
||||||
continue;
|
continue;
|
||||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT,
|
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT,
|
||||||
tselect[hartid]);
|
tselect[hartid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= r->trigger_count[0]) {
|
if (i >= r->trigger_count[first_hart]) {
|
||||||
LOG_ERROR("Couldn't find an available hardware trigger.");
|
LOG_ERROR("Couldn't find an available hardware trigger.");
|
||||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
@ -507,19 +519,30 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
|
||||||
{
|
{
|
||||||
RISCV_INFO(r);
|
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;
|
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) {
|
if (r->trigger_unique_id[i] == trigger->unique_id) {
|
||||||
break;
|
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 "
|
LOG_ERROR("Couldn't find the hardware resources used by hardware "
|
||||||
"trigger.");
|
"trigger.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id);
|
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))
|
if (!riscv_hart_enabled(target, hartid))
|
||||||
continue;
|
continue;
|
||||||
riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT);
|
riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT);
|
||||||
|
|
|
@ -67,7 +67,9 @@ typedef struct {
|
||||||
unsigned trigger_count[RISCV_MAX_HARTS];
|
unsigned trigger_count[RISCV_MAX_HARTS];
|
||||||
|
|
||||||
/* For each physical trigger, contains -1 if the hwbp is available, or the
|
/* 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];
|
int trigger_unique_id[RISCV_MAX_HWBPS];
|
||||||
|
|
||||||
/* The address of the debug RAM buffer. */
|
/* The address of the debug RAM buffer. */
|
||||||
|
|
Loading…
Reference in New Issue