aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2020-06-17 13:47:58 -0700
committerTim Newsome <tim@sifive.com>2020-06-17 13:47:58 -0700
commit56d1c6ae6c93a11bb807b6399c7fb84146937dd0 (patch)
tree5e01cb4fd75cdf606759a25e8d51bd4a18649e36
parent4411d1f4c2d36ece06421b02e986abe0d9f19714 (diff)
downloadriscv-openocd-56d1c6ae6c93a11bb807b6399c7fb84146937dd0.zip
riscv-openocd-56d1c6ae6c93a11bb807b6399c7fb84146937dd0.tar.gz
riscv-openocd-56d1c6ae6c93a11bb807b6399c7fb84146937dd0.tar.bz2
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
-rw-r--r--src/target/riscv/riscv.c182
1 files changed, 105 insertions, 77 deletions
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index bd64821..3920961 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -1213,102 +1213,122 @@ int riscv_resume_prep_all_harts(struct target *target)
return ERROR_OK;
}
-/**
- * Get everything ready to resume.
- */
-static int resume_prep(struct target *target, int current,
- target_addr_t address, int handle_breakpoints, int debug_execution)
+/* 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("[%d]", target->coreid);
- if (!current)
- riscv_set_register(target, GDB_REGNO_PC, address);
+ LOG_DEBUG("deal with triggers");
- if (target->debug_reason == DBG_REASON_WATCHPOINT) {
- /* To be able to run off a trigger, disable all the triggers, step, and
- * then resume as usual. */
- LOG_DEBUG("deal with triggers");
- if (riscv_enumerate_triggers(target) != ERROR_OK)
- return ERROR_FAIL;
-
- riscv_reg_t trigger_temporarily_cleared[RISCV_MAX_HWBPS] = {0};
+ if (riscv_enumerate_triggers(target) != ERROR_OK)
+ return ERROR_FAIL;
- int result = ERROR_OK;
- 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)
+ 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;
- 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)
+ 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 (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;
+ }
+ 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++;
+ } 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++;
}
+ }
- if (result == ERROR_OK)
- result = old_or_new_riscv_step(target, true, 0, false);
+ return ERROR_OK;
+}
- 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;
- }
+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;
+ }
+ 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)
+ } else {
+ struct watchpoint *watchpoint = target->watchpoints;
+ int i = 0;
+ while (watchpoint)
+ {
+ LOG_DEBUG("watchpoint %d: cleared=%" PRId64, i, state[i]);
+ if (state[i])
{
- 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 (riscv_add_watchpoint(target, watchpoint) != ERROR_OK)
+ return ERROR_FAIL;
}
+ watchpoint = watchpoint->next;
+ i++;
}
+ }
- if (result != ERROR_OK)
- return result;
+ return ERROR_OK;
+}
+
+/**
+ * Get everything ready to resume.
+ */
+static int resume_prep(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints, int debug_execution)
+{
+ RISCV_INFO(r);
+ LOG_DEBUG("[%d]", target->coreid);
+
+ if (!current)
+ riscv_set_register(target, GDB_REGNO_PC, address);
+
+ if (target->debug_reason == DBG_REASON_WATCHPOINT) {
+ /* To be able to run off a trigger, disable all the triggers, step, and
+ * then resume as usual. */
+ riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0};
+
+ if (disable_triggers(target, trigger_state) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (old_or_new_riscv_step(target, true, 0, false) != ERROR_OK)
+ return ERROR_FAIL;
+
+ if (enable_triggers(target, trigger_state) != ERROR_OK)
+ return ERROR_FAIL;
}
if (r->is_halted) {
@@ -2181,6 +2201,10 @@ int riscv_openocd_step(
if (!current)
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);
if (out != ERROR_OK) {
LOG_ERROR("unable to step rtos hart");
@@ -2188,6 +2212,10 @@ int riscv_openocd_step(
}
register_cache_invalidate(target->reg_cache);
+
+ if (enable_triggers(target, trigger_state) != ERROR_OK)
+ return ERROR_FAIL;
+
target->state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
target->state = TARGET_HALTED;