Handle resuming from a trigger...

... by disabling all triggers, single stepping, enabling them, and then
resuming as usual. Without this change, you'd just be stuck on an
address trigger and would have to manually disable it.

Change-Id: I5834984671baa6b64f72e533c4aa94555c64617e
This commit is contained in:
Tim Newsome 2018-02-07 12:16:22 -08:00
parent 6e278cded6
commit ace6b7e49a
4 changed files with 52 additions and 22 deletions

View File

@ -248,7 +248,7 @@ static int riscv_gdb_v_packet(struct connection *connection, const char *packet,
if (strcmp(packet_stttrr, "vCont;c") == 0) {
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
target_call_event_callbacks(target, TARGET_EVENT_RESUME_START);
riscv_resume_all_harts(target);
riscv_openocd_resume(target, 1, 0, 0, 0);
target->state = TARGET_RUNNING;
gdb_set_frontend_state_running(connection);
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);

View File

@ -2037,8 +2037,9 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
switch (get_field(dcsr, CSR_DCSR_CAUSE)) {
case CSR_DCSR_CAUSE_SWBP:
case CSR_DCSR_CAUSE_TRIGGER:
return RISCV_HALT_BREAKPOINT;
case CSR_DCSR_CAUSE_TRIGGER:
return RISCV_HALT_TRIGGER;
case CSR_DCSR_CAUSE_STEP:
return RISCV_HALT_SINGLESTEP;
case CSR_DCSR_CAUSE_DEBUGINT:

View File

@ -640,6 +640,7 @@ static int old_or_new_riscv_step(
int handle_breakpoints
){
RISCV_INFO(r);
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
if (r->is_halted == NULL)
return oldriscv_step(target, current, address, handle_breakpoints);
else
@ -728,6 +729,7 @@ static int old_or_new_riscv_resume(
int debug_execution
){
RISCV_INFO(r);
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
if (r->is_halted == NULL)
return oldriscv_resume(target, current, address, handle_breakpoints, debug_execution);
else
@ -1027,6 +1029,9 @@ int riscv_openocd_poll(struct target *target)
case RISCV_HALT_BREAKPOINT:
target->debug_reason = DBG_REASON_BREAKPOINT;
break;
case RISCV_HALT_TRIGGER:
target->debug_reason = DBG_REASON_WATCHPOINT;
break;
case RISCV_HALT_INTERRUPT:
target->debug_reason = DBG_REASON_DBGRQ;
break;
@ -1077,13 +1082,53 @@ int riscv_openocd_resume(
int current,
target_addr_t address,
int handle_breakpoints,
int debug_execution
) {
LOG_DEBUG("resuming all harts");
int debug_execution)
{
LOG_DEBUG("debug_reason=%d", target->debug_reason);
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. */
struct watchpoint *watchpoint = target->watchpoints;
bool trigger_temporarily_cleared[RISCV_MAX_HWBPS] = {0};
int i = 0;
int result = ERROR_OK;
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 = riscv_step_rtos_hart(target);
}
watchpoint = target->watchpoints;
i = 0;
while (watchpoint) {
LOG_DEBUG("watchpoint %d: cleared=%d", 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;
}
int out = riscv_resume_all_harts(target);
if (out != ERROR_OK) {
LOG_ERROR("unable to resume all harts");
@ -1601,18 +1646,6 @@ enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
return r->halt_reason(target);
}
int riscv_count_triggers(struct target *target)
{
return riscv_count_triggers_of_hart(target, riscv_current_hartid(target));
}
int riscv_count_triggers_of_hart(struct target *target, int hartid)
{
RISCV_INFO(r);
assert(hartid < riscv_count_harts(target));
return r->trigger_count[hartid];
}
size_t riscv_debug_buffer_size(struct target *target)
{
RISCV_INFO(r);

View File

@ -30,6 +30,7 @@ enum riscv_halt_reason {
RISCV_HALT_INTERRUPT,
RISCV_HALT_BREAKPOINT,
RISCV_HALT_SINGLESTEP,
RISCV_HALT_TRIGGER,
RISCV_HALT_UNKNOWN
};
@ -216,11 +217,6 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
bool riscv_is_halted(struct target *target);
enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid);
/* Returns the number of triggers availiable to either the current hart or to
* the given hart. */
int riscv_count_triggers(struct target *target);
int riscv_count_triggers_of_hart(struct target *target, int hartid);
/* These helper functions let the generic program interface get target-specific
* information. */
size_t riscv_debug_buffer_size(struct target *target);