Also disable/reenable triggers around single step.
Gdb is smart enough to disable/step/resume if it set the triggers, but if a user set them manually it also needs to happen. Change-Id: I1251bd47199b6f15f61a93e3a521a53f2b677c5f
This commit is contained in:
parent
4411d1f4c2
commit
56d1c6ae6c
|
@ -1213,6 +1213,97 @@ int riscv_resume_prep_all_harts(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* state must be riscv_reg_t state[RISCV_MAX_HWBPS] = {0}; */
|
||||||
|
static int disable_triggers(struct target *target, riscv_reg_t *state)
|
||||||
|
{
|
||||||
|
RISCV_INFO(r);
|
||||||
|
|
||||||
|
LOG_DEBUG("deal with triggers");
|
||||||
|
|
||||||
|
if (riscv_enumerate_triggers(target) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int hartid = riscv_current_hartid(target);
|
||||||
|
if (r->manual_hwbp_set) {
|
||||||
|
/* Look at every trigger that may have been set. */
|
||||||
|
riscv_reg_t tselect;
|
||||||
|
if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
for (unsigned t = 0; t < r->trigger_count[hartid]; t++) {
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
riscv_reg_t tdata1;
|
||||||
|
if (riscv_get_register(target, &tdata1, GDB_REGNO_TDATA1) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
if (tdata1 & MCONTROL_DMODE(riscv_xlen(target))) {
|
||||||
|
state[t] = tdata1;
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TDATA1, 0) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Just go through the triggers we manage. */
|
||||||
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
int i = 0;
|
||||||
|
while (watchpoint) {
|
||||||
|
LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set);
|
||||||
|
state[i] = watchpoint->set;
|
||||||
|
if (watchpoint->set) {
|
||||||
|
if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
watchpoint = watchpoint->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int enable_triggers(struct target *target, riscv_reg_t *state)
|
||||||
|
{
|
||||||
|
RISCV_INFO(r);
|
||||||
|
|
||||||
|
int hartid = riscv_current_hartid(target);
|
||||||
|
|
||||||
|
if (r->manual_hwbp_set) {
|
||||||
|
/* Look at every trigger that may have been set. */
|
||||||
|
riscv_reg_t tselect;
|
||||||
|
if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
for (unsigned t = 0; t < r->trigger_count[hartid]; t++) {
|
||||||
|
if (state[t] != 0) {
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TDATA1, state[t]) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
int i = 0;
|
||||||
|
while (watchpoint)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("watchpoint %d: cleared=%" PRId64, i, state[i]);
|
||||||
|
if (state[i])
|
||||||
|
{
|
||||||
|
if (riscv_add_watchpoint(target, watchpoint) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
watchpoint = watchpoint->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get everything ready to resume.
|
* Get everything ready to resume.
|
||||||
*/
|
*/
|
||||||
|
@ -1228,87 +1319,16 @@ static int resume_prep(struct target *target, int current,
|
||||||
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
|
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
|
||||||
/* To be able to run off a trigger, disable all the triggers, step, and
|
/* To be able to run off a trigger, disable all the triggers, step, and
|
||||||
* then resume as usual. */
|
* then resume as usual. */
|
||||||
LOG_DEBUG("deal with triggers");
|
riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0};
|
||||||
if (riscv_enumerate_triggers(target) != ERROR_OK)
|
|
||||||
|
if (disable_triggers(target, trigger_state) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
riscv_reg_t trigger_temporarily_cleared[RISCV_MAX_HWBPS] = {0};
|
if (old_or_new_riscv_step(target, true, 0, false) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
int result = ERROR_OK;
|
if (enable_triggers(target, trigger_state) != ERROR_OK)
|
||||||
int hartid = riscv_current_hartid(target);
|
return ERROR_FAIL;
|
||||||
if (r->manual_hwbp_set) {
|
|
||||||
/* Look at every trigger that may have been set. */
|
|
||||||
riscv_reg_t tselect;
|
|
||||||
if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
for (unsigned t = 0; t < r->trigger_count[hartid]; t++) {
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
riscv_reg_t tdata1;
|
|
||||||
if (riscv_get_register(target, &tdata1, GDB_REGNO_TDATA1) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
if (tdata1 & MCONTROL_DMODE(riscv_xlen(target))) {
|
|
||||||
trigger_temporarily_cleared[t] = tdata1;
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TDATA1, 0) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Just go through the triggers we manage. */
|
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
|
||||||
int i = 0;
|
|
||||||
while (watchpoint && result == ERROR_OK) {
|
|
||||||
LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set);
|
|
||||||
trigger_temporarily_cleared[i] = watchpoint->set;
|
|
||||||
if (watchpoint->set)
|
|
||||||
result = riscv_remove_watchpoint(target, watchpoint);
|
|
||||||
watchpoint = watchpoint->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == ERROR_OK)
|
|
||||||
result = old_or_new_riscv_step(target, true, 0, false);
|
|
||||||
|
|
||||||
if (r->manual_hwbp_set) {
|
|
||||||
/* Look at every trigger that may have been set. */
|
|
||||||
riscv_reg_t tselect;
|
|
||||||
if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
for (unsigned t = 0; t < r->trigger_count[hartid]; t++) {
|
|
||||||
if (trigger_temporarily_cleared[t] != 0) {
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TDATA1, trigger_temporarily_cleared[t]) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
|
||||||
int i = 0;
|
|
||||||
while (watchpoint)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("watchpoint %d: cleared=%" PRId64, i, trigger_temporarily_cleared[i]);
|
|
||||||
if (trigger_temporarily_cleared[i])
|
|
||||||
{
|
|
||||||
if (result == ERROR_OK)
|
|
||||||
result = riscv_add_watchpoint(target, watchpoint);
|
|
||||||
else
|
|
||||||
riscv_add_watchpoint(target, watchpoint);
|
|
||||||
}
|
|
||||||
watchpoint = watchpoint->next;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != ERROR_OK)
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->is_halted) {
|
if (r->is_halted) {
|
||||||
|
@ -2181,6 +2201,10 @@ int riscv_openocd_step(
|
||||||
if (!current)
|
if (!current)
|
||||||
riscv_set_register(target, GDB_REGNO_PC, address);
|
riscv_set_register(target, GDB_REGNO_PC, address);
|
||||||
|
|
||||||
|
riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0};
|
||||||
|
if (disable_triggers(target, trigger_state) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
int out = riscv_step_rtos_hart(target);
|
int out = riscv_step_rtos_hart(target);
|
||||||
if (out != ERROR_OK) {
|
if (out != ERROR_OK) {
|
||||||
LOG_ERROR("unable to step rtos hart");
|
LOG_ERROR("unable to step rtos hart");
|
||||||
|
@ -2188,6 +2212,10 @@ int riscv_openocd_step(
|
||||||
}
|
}
|
||||||
|
|
||||||
register_cache_invalidate(target->reg_cache);
|
register_cache_invalidate(target->reg_cache);
|
||||||
|
|
||||||
|
if (enable_triggers(target, trigger_state) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
|
Loading…
Reference in New Issue