Merge pull request #851 from riscv/power_dance
target/riscv: Handle harts powering down and coming back up.
This commit is contained in:
commit
58b6a5eabf
|
@ -589,15 +589,15 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
|
||||||
} else if (status == DMI_STATUS_SUCCESS) {
|
} else if (status == DMI_STATUS_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("failed %s at 0x%x, status=%d", op_name, address, status);
|
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
|
||||||
return ERROR_FAIL;
|
break;
|
||||||
}
|
}
|
||||||
if (time(NULL) - start > timeout_sec)
|
if (time(NULL) - start > timeout_sec)
|
||||||
return ERROR_TIMEOUT_REACHED;
|
return ERROR_TIMEOUT_REACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != DMI_STATUS_SUCCESS) {
|
if (status != DMI_STATUS_SUCCESS) {
|
||||||
LOG_ERROR("Failed %s at 0x%x; status=%d", op_name, address, status);
|
LOG_TARGET_ERROR(target, "Failed DMI %s at 0x%x; status=%d", op_name, address, status);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,12 +616,15 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in,
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (data_in) {
|
if (data_in) {
|
||||||
LOG_ERROR("Failed %s (NOP) at 0x%x; value=0x%x, status=%d",
|
LOG_TARGET_ERROR(target,
|
||||||
|
"Failed DMI %s (NOP) at 0x%x; value=0x%x, status=%d",
|
||||||
op_name, address, *data_in, status);
|
op_name, address, *data_in, status);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Failed %s (NOP) at 0x%x; status=%d", op_name, address,
|
LOG_TARGET_ERROR(target,
|
||||||
|
"Failed DMI %s (NOP) at 0x%x; status=%d", op_name, address,
|
||||||
status);
|
status);
|
||||||
}
|
}
|
||||||
|
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (time(NULL) - start > timeout_sec)
|
if (time(NULL) - start > timeout_sec)
|
||||||
|
@ -1552,6 +1555,24 @@ static int wait_for_authbusy(struct target *target, uint32_t *dmstatus)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int update_dcsr(struct target *target, bool step)
|
||||||
|
{
|
||||||
|
riscv_reg_t dcsr;
|
||||||
|
/* We want to twiddle some bits in the debug CSR so debugging works. */
|
||||||
|
int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR);
|
||||||
|
if (result != ERROR_OK)
|
||||||
|
return result;
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm);
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, riscv_ebreaks);
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, riscv_ebreaku);
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, riscv_ebreaku);
|
||||||
|
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, riscv_ebreaku);
|
||||||
|
if (riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*** OpenOCD target functions. ***/
|
/*** OpenOCD target functions. ***/
|
||||||
|
|
||||||
static void deinit_target(struct target *target)
|
static void deinit_target(struct target *target)
|
||||||
|
@ -1620,10 +1641,10 @@ static int examine(struct target *target)
|
||||||
dmi_write(target, DM_DMCONTROL, 0);
|
dmi_write(target, DM_DMCONTROL, 0);
|
||||||
dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
|
dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
|
||||||
dm->was_reset = true;
|
dm->was_reset = true;
|
||||||
|
|
||||||
/* The DM gets reset, so forget any cached progbuf entries. */
|
|
||||||
riscv013_invalidate_cached_debug_buffer(target);
|
|
||||||
}
|
}
|
||||||
|
/* We're here because we're uncertain about the state of the target. That
|
||||||
|
* includes our progbuf cache. */
|
||||||
|
riscv013_invalidate_cached_debug_buffer(target);
|
||||||
|
|
||||||
dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO |
|
dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO |
|
||||||
DM_DMCONTROL_HARTSELHI | DM_DMCONTROL_DMACTIVE |
|
DM_DMCONTROL_HARTSELHI | DM_DMCONTROL_DMACTIVE |
|
||||||
|
@ -1823,10 +1844,6 @@ static int examine(struct target *target)
|
||||||
r->mtopi_readable = false;
|
r->mtopi_readable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now init registers based on what we discovered. */
|
|
||||||
if (riscv_init_registers(target) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
|
||||||
|
|
||||||
/* Display this as early as possible to help people who are using
|
/* Display this as early as possible to help people who are using
|
||||||
* really slow simulators. */
|
* really slow simulators. */
|
||||||
LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa);
|
LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa);
|
||||||
|
@ -1844,6 +1861,13 @@ static int examine(struct target *target)
|
||||||
target->state = saved_tgt_state;
|
target->state = saved_tgt_state;
|
||||||
target->debug_reason = saved_dbg_reason;
|
target->debug_reason = saved_dbg_reason;
|
||||||
|
|
||||||
|
/* Now init registers based on what we discovered. */
|
||||||
|
if (riscv_init_registers(target) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
if (update_dcsr(target, false) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (!halted) {
|
if (!halted) {
|
||||||
riscv013_step_or_resume_current_hart(target, false);
|
riscv013_step_or_resume_current_hart(target, false);
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
|
@ -4602,19 +4626,9 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
|
||||||
if (maybe_execute_fence_i(target) != ERROR_OK)
|
if (maybe_execute_fence_i(target) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
/* We want to twiddle some bits in the debug CSR so debugging works. */
|
if (update_dcsr(target, step) != ERROR_OK)
|
||||||
riscv_reg_t dcsr;
|
|
||||||
int result = riscv_get_register(target, &dcsr, GDB_REGNO_DCSR);
|
|
||||||
if (result != ERROR_OK)
|
|
||||||
return result;
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm);
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, riscv_ebreaks);
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, riscv_ebreaku);
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, riscv_ebreaku);
|
|
||||||
dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, riscv_ebreaku);
|
|
||||||
if (riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (riscv_flush_registers(target) != ERROR_OK)
|
if (riscv_flush_registers(target) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -3055,9 +3055,12 @@ static int handle_target(void *priv)
|
||||||
/* Increase interval between polling up to 5000ms */
|
/* Increase interval between polling up to 5000ms */
|
||||||
target->backoff.interval = MAX(polling_interval,
|
target->backoff.interval = MAX(polling_interval,
|
||||||
MIN(target->backoff.interval * 2 + 1, 5000));
|
MIN(target->backoff.interval * 2 + 1, 5000));
|
||||||
/* Tell GDB to halt the debugger. This allows the user to run
|
/* Do *not* tell gdb the target halted. This might just
|
||||||
* monitor commands to handle the situation. */
|
* be a hiccup. We have no reason to believe the target
|
||||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
|
* is halted, and if it is running while gdb thinks it's
|
||||||
|
* halted things just get unnecessarily confused. gdb
|
||||||
|
* users can hit ^C if the need to interact with the
|
||||||
|
* target. */
|
||||||
}
|
}
|
||||||
target->backoff.next_attempt = timeval_ms() + target->backoff.interval;
|
target->backoff.next_attempt = timeval_ms() + target->backoff.interval;
|
||||||
LOG_TARGET_DEBUG(target, "target_poll() -> %d, next attempt in %dms",
|
LOG_TARGET_DEBUG(target, "target_poll() -> %d, next attempt in %dms",
|
||||||
|
@ -3067,8 +3070,7 @@ static int handle_target(void *priv)
|
||||||
target_reset_examined(target);
|
target_reset_examined(target);
|
||||||
retval = target_examine_one(target);
|
retval = target_examine_one(target);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_TARGET_DEBUG(target, "Examination failed, GDB will be halted. "
|
LOG_TARGET_DEBUG(target, "Examination failed. Polling again in %dms",
|
||||||
"Polling again in %dms",
|
|
||||||
target->backoff.interval);
|
target->backoff.interval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue