Do not resume harts that was meant to be halted
This commit is contained in:
parent
ea57d2ae27
commit
a4a158dc54
|
@ -2217,19 +2217,19 @@ static int examine(struct target *target)
|
||||||
/* Don't call any riscv_* functions until after we've counted the number of
|
/* Don't call any riscv_* functions until after we've counted the number of
|
||||||
* cores and initialized registers. */
|
* cores and initialized registers. */
|
||||||
|
|
||||||
enum riscv_hart_state state_at_examine_start;
|
enum riscv_hart_state riscv_state_at_examine_start;
|
||||||
if (riscv_get_hart_state(target, &state_at_examine_start) != ERROR_OK)
|
if (riscv_get_hart_state(target, &riscv_state_at_examine_start) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
/* Skip full examination and reporting of hart if it is currently unavailable */
|
/* Skip full examination and reporting of hart if it is currently unavailable */
|
||||||
const bool hart_unavailable_at_examine_start = state_at_examine_start == RISCV_STATE_UNAVAILABLE;
|
const bool hart_unavailable_at_examine_start = riscv_state_at_examine_start == RISCV_STATE_UNAVAILABLE;
|
||||||
if (hart_unavailable_at_examine_start) {
|
if (hart_unavailable_at_examine_start) {
|
||||||
LOG_TARGET_DEBUG(target, "Did not fully examine hart %d as it was currently unavailable, deferring examine.", info->index);
|
LOG_TARGET_DEBUG(target, "Did not fully examine hart %d as it was currently unavailable, deferring examine.", info->index);
|
||||||
target->state = TARGET_UNAVAILABLE;
|
target->state = TARGET_UNAVAILABLE;
|
||||||
target->defer_examine = true;
|
target->defer_examine = true;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
const bool hart_halted_at_examine_start = state_at_examine_start == RISCV_STATE_HALTED;
|
const bool hart_halted_at_examine_start = riscv_state_at_examine_start == RISCV_STATE_HALTED;
|
||||||
if (!hart_halted_at_examine_start) {
|
if (!hart_halted_at_examine_start) {
|
||||||
if (riscv013_halt_target(target) != ERROR_OK) {
|
if (riscv013_halt_target(target) != ERROR_OK) {
|
||||||
LOG_TARGET_ERROR(target, "Fatal: Hart %d failed to halt during %s",
|
LOG_TARGET_ERROR(target, "Fatal: Hart %d failed to halt during %s",
|
||||||
|
@ -2330,11 +2330,11 @@ static int examine(struct target *target)
|
||||||
if (set_dcsr_ebreak(target, false) != ERROR_OK)
|
if (set_dcsr_ebreak(target, false) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (state_at_examine_start == RISCV_STATE_RUNNING) {
|
if (riscv_state_at_examine_start == RISCV_STATE_RUNNING) {
|
||||||
riscv013_step_or_resume_current_hart(target, false);
|
riscv013_step_or_resume_current_hart(target, false);
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||||
} else if (state_at_examine_start == RISCV_STATE_HALTED) {
|
} else if (riscv_state_at_examine_start == RISCV_STATE_HALTED) {
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
target->debug_reason = DBG_REASON_UNDEFINED;
|
target->debug_reason = DBG_REASON_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
@ -2868,7 +2868,7 @@ static int sample_memory(struct target *target,
|
||||||
return sample_memory_bus_v1(target, buf, config, until_ms);
|
return sample_memory_bus_v1(target, buf, config, until_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state *state)
|
static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state *riscv_state)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
if (dm013_select_target(target) != ERROR_OK)
|
if (dm013_select_target(target) != ERROR_OK)
|
||||||
|
@ -2900,19 +2900,19 @@ static int riscv013_get_hart_state(struct target *target, enum riscv_hart_state
|
||||||
dm_write(target, DM_DMCONTROL, dmcontrol);
|
dm_write(target, DM_DMCONTROL, dmcontrol);
|
||||||
}
|
}
|
||||||
if (get_field(dmstatus, DM_DMSTATUS_ALLNONEXISTENT)) {
|
if (get_field(dmstatus, DM_DMSTATUS_ALLNONEXISTENT)) {
|
||||||
*state = RISCV_STATE_NON_EXISTENT;
|
*riscv_state = RISCV_STATE_NON_EXISTENT;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if (get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL)) {
|
if (get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL)) {
|
||||||
*state = RISCV_STATE_UNAVAILABLE;
|
*riscv_state = RISCV_STATE_UNAVAILABLE;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if (get_field(dmstatus, DM_DMSTATUS_ALLHALTED)) {
|
if (get_field(dmstatus, DM_DMSTATUS_ALLHALTED)) {
|
||||||
*state = RISCV_STATE_HALTED;
|
*riscv_state = RISCV_STATE_HALTED;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
if (get_field(dmstatus, DM_DMSTATUS_ALLRUNNING)) {
|
if (get_field(dmstatus, DM_DMSTATUS_ALLRUNNING)) {
|
||||||
*state = RISCV_STATE_RUNNING;
|
*riscv_state = RISCV_STATE_RUNNING;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
LOG_TARGET_ERROR(target, "Couldn't determine state. dmstatus=0x%x", dmstatus);
|
LOG_TARGET_ERROR(target, "Couldn't determine state. dmstatus=0x%x", dmstatus);
|
||||||
|
|
|
@ -1897,10 +1897,10 @@ static int riscv_halt_go_all_harts(struct target *target)
|
||||||
{
|
{
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
|
|
||||||
enum riscv_hart_state state;
|
enum riscv_hart_state riscv_state;
|
||||||
if (riscv_get_hart_state(target, &state) != ERROR_OK)
|
if (riscv_get_hart_state(target, &riscv_state) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
if (state == RISCV_STATE_HALTED) {
|
if (riscv_state == RISCV_STATE_HALTED) {
|
||||||
LOG_TARGET_DEBUG(target, "Hart is already halted.");
|
LOG_TARGET_DEBUG(target, "Hart is already halted.");
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
target->state = TARGET_HALTED;
|
target->state = TARGET_HALTED;
|
||||||
|
@ -3061,16 +3061,16 @@ static int riscv_poll_hart(struct target *target, enum riscv_next_action *next_a
|
||||||
|
|
||||||
/* 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. */
|
||||||
enum riscv_hart_state state;
|
enum riscv_hart_state riscv_state;
|
||||||
if (riscv_get_hart_state(target, &state) != ERROR_OK)
|
if (riscv_get_hart_state(target, &riscv_state) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (state == RISCV_STATE_NON_EXISTENT) {
|
if (riscv_state == RISCV_STATE_NON_EXISTENT) {
|
||||||
LOG_TARGET_ERROR(target, "Hart is non-existent!");
|
LOG_TARGET_ERROR(target, "Hart is non-existent!");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == RISCV_STATE_HALTED && timeval_ms() - r->last_activity > 100) {
|
if (riscv_state == RISCV_STATE_HALTED && timeval_ms() - r->last_activity > 100) {
|
||||||
/* If we've been idle for a while, flush the register cache. Just in case
|
/* If we've been idle for a while, flush the register cache. Just in case
|
||||||
* OpenOCD is going to be disconnected without shutting down cleanly. */
|
* OpenOCD is going to be disconnected without shutting down cleanly. */
|
||||||
if (riscv_flush_registers(target) != ERROR_OK)
|
if (riscv_flush_registers(target) != ERROR_OK)
|
||||||
|
@ -3078,16 +3078,16 @@ static int riscv_poll_hart(struct target *target, enum riscv_next_action *next_a
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The hart apparently became unavailable while halted, so we want to resume it */
|
/* The hart apparently became unavailable while halted, so we want to resume it */
|
||||||
if (state == RISCV_STATE_HALTED && previous_riscv_state == RISCV_STATE_UNAVAILABLE) {
|
// if (riscv_state == RISCV_STATE_HALTED && previous_riscv_state == RISCV_STATE_UNAVAILABLE) {
|
||||||
if (r->handle_became_available &&
|
// if (r->handle_became_available &&
|
||||||
r->handle_became_available(target, previous_riscv_state) != ERROR_OK)
|
// r->handle_became_available(target, previous_riscv_state) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
// return ERROR_FAIL;
|
||||||
if (riscv_get_hart_state(target, &state) != ERROR_OK)
|
// if (riscv_get_hart_state(target, &riscv_state) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
// return ERROR_FAIL;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (target->state == TARGET_UNKNOWN || state != previous_riscv_state) {
|
if (target->state == TARGET_UNKNOWN || riscv_state != previous_riscv_state) {
|
||||||
switch (state) {
|
switch (riscv_state) {
|
||||||
case RISCV_STATE_HALTED:
|
case RISCV_STATE_HALTED:
|
||||||
if (previous_riscv_state == RISCV_STATE_UNAVAILABLE)
|
if (previous_riscv_state == RISCV_STATE_UNAVAILABLE)
|
||||||
LOG_TARGET_INFO(target, "became available (halted)");
|
LOG_TARGET_INFO(target, "became available (halted)");
|
||||||
|
@ -5361,11 +5361,11 @@ int riscv_save_register(struct target *target, enum gdb_regno regid)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv_get_hart_state(struct target *target, enum riscv_hart_state *state)
|
int riscv_get_hart_state(struct target *target, enum riscv_hart_state *riscv_state)
|
||||||
{
|
{
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
assert(r->get_hart_state);
|
assert(r->get_hart_state);
|
||||||
return r->get_hart_state(target, state);
|
return r->get_hart_state(target, riscv_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum riscv_halt_reason riscv_halt_reason(struct target *target)
|
static enum riscv_halt_reason riscv_halt_reason(struct target *target)
|
||||||
|
|
|
@ -199,7 +199,7 @@ struct riscv_info {
|
||||||
int (*set_register_buf)(struct target *target, enum gdb_regno regno,
|
int (*set_register_buf)(struct target *target, enum gdb_regno regno,
|
||||||
const uint8_t *buf);
|
const uint8_t *buf);
|
||||||
int (*select_target)(struct target *target);
|
int (*select_target)(struct target *target);
|
||||||
int (*get_hart_state)(struct target *target, enum riscv_hart_state *state);
|
int (*get_hart_state)(struct target *target, enum riscv_hart_state *riscv_state);
|
||||||
/* Resume this target, as well as every other prepped target that can be
|
/* Resume this target, as well as every other prepped target that can be
|
||||||
* resumed near-simultaneously. Clear the prepped flag on any target that
|
* resumed near-simultaneously. Clear the prepped flag on any target that
|
||||||
* was resumed. */
|
* was resumed. */
|
||||||
|
@ -427,7 +427,7 @@ int riscv_flush_registers(struct target *target);
|
||||||
|
|
||||||
/* Checks the state of the current hart -- "is_halted" checks the actual
|
/* Checks the state of the current hart -- "is_halted" checks the actual
|
||||||
* on-device register. */
|
* on-device register. */
|
||||||
int riscv_get_hart_state(struct target *target, enum riscv_hart_state *state);
|
int riscv_get_hart_state(struct target *target, enum riscv_hart_state *riscv_state);
|
||||||
|
|
||||||
/* These helper functions let the generic program interface get target-specific
|
/* These helper functions let the generic program interface get target-specific
|
||||||
* information. */
|
* information. */
|
||||||
|
|
|
@ -687,7 +687,7 @@ int target_examine_one(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->defer_examine) {
|
if (target->defer_examine) {
|
||||||
LOG_USER("[%s] Target currently unavailable for full examination.", target_name(target));
|
LOG_TARGET_DEBUG(target, "Currently unavailable for full examination");
|
||||||
target->defer_examine = defer_state;
|
target->defer_examine = defer_state;
|
||||||
target_reset_examined(target);
|
target_reset_examined(target);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue