diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index bd6482121..39209610e 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1213,6 +1213,97 @@ int riscv_resume_prep_all_harts(struct target *target) 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. */ @@ -1228,87 +1319,16 @@ static int resume_prep(struct target *target, int current, 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) + riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0}; + + if (disable_triggers(target, trigger_state) != ERROR_OK) 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; - 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))) { - 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 (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;