Notice when a hart has reset.

Attempt to notify the user.
Deal correctly with a halted target that is suddenly running.

Change-Id: Ib0e0aa843d1da22df673713687ec884f6af14949
This commit is contained in:
Tim Newsome 2018-03-16 15:02:47 -07:00
parent fd2759a63d
commit 4d2d1f7324
2 changed files with 33 additions and 20 deletions

View File

@ -1107,10 +1107,9 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
int result = register_read_abstract(target, value, number, int result = register_read_abstract(target, value, number,
register_size(target, number)); register_size(target, number));
if (result != ERROR_OK && info->progbufsize + r->impebreak >= 2 && if (result != ERROR_OK &&
riscv_is_halted(target)) { info->progbufsize + r->impebreak >= 2 &&
assert(number != GDB_REGNO_S0); number > GDB_REGNO_XPR31) {
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
@ -2567,6 +2566,14 @@ static bool riscv013_is_halted(struct target *target)
LOG_ERROR("hart %d is unavailable", riscv_current_hartid(target)); LOG_ERROR("hart %d is unavailable", riscv_current_hartid(target));
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT)) if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT))
LOG_ERROR("hart %d doesn't exist", riscv_current_hartid(target)); LOG_ERROR("hart %d doesn't exist", riscv_current_hartid(target));
if (get_field(dmstatus, DMI_DMSTATUS_ANYHAVERESET)) {
int hartid = riscv_current_hartid(target);
LOG_INFO("hart %d unexpectedly reset!", hartid);
/* TODO: Can we make this more obvious to eg. a gdb user? */
dmi_write(target, DMI_DMCONTROL,
set_field(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET,
hartsel_mask(target), hartid));
}
return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED); return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED);
} }

View File

@ -969,7 +969,8 @@ int riscv_blank_check_memory(struct target *target,
enum riscv_poll_hart { enum riscv_poll_hart {
RPH_NO_CHANGE, RPH_NO_CHANGE,
RPH_CHANGE, RPH_DISCOVERED_HALTED,
RPH_DISCOVERED_RUNNING,
RPH_ERROR RPH_ERROR
}; };
static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid) static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
@ -978,15 +979,19 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
if (riscv_set_current_hartid(target, hartid) != ERROR_OK) if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
return RPH_ERROR; return RPH_ERROR;
LOG_DEBUG("polling hart %d, target->state=%d (TARGET_HALTED=%d)", hartid, LOG_DEBUG("polling hart %d, target->state=%d", hartid, target->state);
target->state, TARGET_HALTED);
/* If OpenOCD thinks we're running but this hart is halted then it's time /* If OpenOCD thinks we're running but this hart is halted then it's time
* to raise an event. */ * to raise an event. */
if (target->state != TARGET_HALTED && riscv_is_halted(target)) { bool halted = riscv_is_halted(target);
if (target->state != TARGET_HALTED && halted) {
LOG_DEBUG(" triggered a halt"); LOG_DEBUG(" triggered a halt");
r->on_halt(target); r->on_halt(target);
return RPH_CHANGE; return RPH_DISCOVERED_HALTED;
} else if (target->state != TARGET_RUNNING && !halted) {
LOG_DEBUG(" triggered running");
target->state = TARGET_RUNNING;
return RPH_DISCOVERED_RUNNING;
} }
return RPH_NO_CHANGE; return RPH_NO_CHANGE;
@ -996,26 +1001,27 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
int riscv_openocd_poll(struct target *target) int riscv_openocd_poll(struct target *target)
{ {
LOG_DEBUG("polling all harts"); LOG_DEBUG("polling all harts");
int triggered_hart = -1; int halted_hart = -1;
if (riscv_rtos_enabled(target)) { if (riscv_rtos_enabled(target)) {
/* Check every hart for an event. */ /* Check every hart for an event. */
for (int i = 0; i < riscv_count_harts(target); ++i) { for (int i = 0; i < riscv_count_harts(target); ++i) {
enum riscv_poll_hart out = riscv_poll_hart(target, i); enum riscv_poll_hart out = riscv_poll_hart(target, i);
switch (out) { switch (out) {
case RPH_NO_CHANGE: case RPH_NO_CHANGE:
case RPH_DISCOVERED_RUNNING:
continue; continue;
case RPH_CHANGE: case RPH_DISCOVERED_HALTED:
triggered_hart = i; halted_hart = i;
break; break;
case RPH_ERROR: case RPH_ERROR:
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
if (triggered_hart == -1) { if (halted_hart == -1) {
LOG_DEBUG(" no harts just halted, target->state=%d", target->state); LOG_DEBUG(" no harts just halted, target->state=%d", target->state);
return ERROR_OK; return ERROR_OK;
} }
LOG_DEBUG(" hart %d halted", triggered_hart); LOG_DEBUG(" hart %d halted", halted_hart);
/* If we're here then at least one hart triggered. That means /* If we're here then at least one hart triggered. That means
* we want to go and halt _every_ hart in the system, as that's * we want to go and halt _every_ hart in the system, as that's
@ -1028,17 +1034,17 @@ int riscv_openocd_poll(struct target *target)
} else { } else {
enum riscv_poll_hart out = riscv_poll_hart(target, enum riscv_poll_hart out = riscv_poll_hart(target,
riscv_current_hartid(target)); riscv_current_hartid(target));
if (out == RPH_NO_CHANGE) if (out == RPH_NO_CHANGE || out == RPH_DISCOVERED_RUNNING)
return ERROR_OK; return ERROR_OK;
else if (out == RPH_ERROR) else if (out == RPH_ERROR)
return ERROR_FAIL; return ERROR_FAIL;
triggered_hart = riscv_current_hartid(target); halted_hart = riscv_current_hartid(target);
LOG_DEBUG(" hart %d halted", triggered_hart); LOG_DEBUG(" hart %d halted", halted_hart);
} }
target->state = TARGET_HALTED; target->state = TARGET_HALTED;
switch (riscv_halt_reason(target, triggered_hart)) { switch (riscv_halt_reason(target, halted_hart)) {
case RISCV_HALT_BREAKPOINT: case RISCV_HALT_BREAKPOINT:
target->debug_reason = DBG_REASON_BREAKPOINT; target->debug_reason = DBG_REASON_BREAKPOINT;
break; break;
@ -1059,8 +1065,8 @@ int riscv_openocd_poll(struct target *target)
} }
if (riscv_rtos_enabled(target)) { if (riscv_rtos_enabled(target)) {
target->rtos->current_threadid = triggered_hart + 1; target->rtos->current_threadid = halted_hart + 1;
target->rtos->current_thread = triggered_hart + 1; target->rtos->current_thread = halted_hart + 1;
} }
target->state = TARGET_HALTED; target->state = TARGET_HALTED;