Simultaneous halt (#372)
* WIP Change-Id: I4f50dced77e9ded4a58ab152824a841a73bc0dc1 * riscv_halt() only halt harts that are running. Progress towards simultaneous halt. Change-Id: I749b6d9ba5e77aa7aca4342c7af841312b78be0e * -rtos riscv passes. But dual gdb is failing again. Change-Id: I1747ba42ce3f3062f6e8c28a75ac40e17f80e980 * Dual gdb works again. -rtos riscv still works. Change-Id: Idddddda79e5918b26e181384def1a305ecceced2 * -rtos hwthread almost completely works. Change-Id: I845feb0bd93484e28ca8620f4760c234d4ce5310 * Maybe better? Change-Id: I669c67e83acf1b749bfb534d3b3c0915c129d686 * All three methods work. Change-Id: If77074fa43f6420d1ec9b594fe366415f5a41f2c * Fix hitting hardware triggers with `-rtos riscv`. Change-Id: I8d4600e1c66fa0e3b9d986b96a5973d09f40735c * Fix halting dual core E31. Change-Id: Ic2d885e027312b68e2f3c6854957fbfee09f814b * Not addressing this TODO right now. Change-Id: Ic7c0d32424068ae1de04d37d15a411c1957207c4 * Remove duplicate line. Change-Id: I14fe8d422f23c97afdaa20a02c0e3ab568219467
This commit is contained in:
parent
44a4deb373
commit
5cb2f200f8
|
@ -41,7 +41,8 @@ static int riscv013_get_register(struct target *target,
|
|||
riscv_reg_t *value, int hid, int rid);
|
||||
static int riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value);
|
||||
static int riscv013_select_current_hart(struct target *target);
|
||||
static int riscv013_halt_current_hart(struct target *target);
|
||||
static int riscv013_halt_prep(struct target *target);
|
||||
static int riscv013_halt_go(struct target *target);
|
||||
static int riscv013_resume_go(struct target *target);
|
||||
static int riscv013_step_current_hart(struct target *target);
|
||||
static int riscv013_on_halt(struct target *target);
|
||||
|
@ -1586,7 +1587,7 @@ static int examine(struct target *target)
|
|||
|
||||
bool halted = riscv_is_halted(target);
|
||||
if (!halted) {
|
||||
if (riscv013_halt_current_hart(target) != ERROR_OK) {
|
||||
if (riscv013_halt_go(target) != ERROR_OK) {
|
||||
LOG_ERROR("Fatal: Hart %d failed to halt during examine()", i);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1701,11 +1702,12 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
generic_info->set_register = &riscv013_set_register;
|
||||
generic_info->select_current_hart = &riscv013_select_current_hart;
|
||||
generic_info->is_halted = &riscv013_is_halted;
|
||||
generic_info->halt_current_hart = &riscv013_halt_current_hart;
|
||||
generic_info->resume_go = &riscv013_resume_go;
|
||||
generic_info->step_current_hart = &riscv013_step_current_hart;
|
||||
generic_info->on_halt = &riscv013_on_halt;
|
||||
generic_info->resume_prep = &riscv013_resume_prep;
|
||||
generic_info->halt_prep = &riscv013_halt_prep;
|
||||
generic_info->halt_go = &riscv013_halt_go;
|
||||
generic_info->on_step = &riscv013_on_step;
|
||||
generic_info->halt_reason = &riscv013_halt_reason;
|
||||
generic_info->read_debug_buffer = &riscv013_read_debug_buffer;
|
||||
|
@ -2897,7 +2899,7 @@ struct target_type riscv013_target = {
|
|||
.examine = examine,
|
||||
|
||||
.poll = &riscv_openocd_poll,
|
||||
.halt = &riscv_openocd_halt,
|
||||
.halt = &riscv_halt,
|
||||
.resume = &riscv_resume,
|
||||
.step = &riscv_openocd_step,
|
||||
|
||||
|
@ -2985,42 +2987,6 @@ static int riscv013_select_current_hart(struct target *target)
|
|||
return result;
|
||||
}
|
||||
|
||||
static int riscv013_halt_current_hart(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("halting hart %d", r->current_hartid);
|
||||
if (riscv_is_halted(target))
|
||||
LOG_ERROR("Hart %d is already halted!", r->current_hartid);
|
||||
|
||||
/* Issue the halt command, and then wait for the current hart to halt. */
|
||||
uint32_t dmcontrol;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
if (riscv_is_halted(target))
|
||||
break;
|
||||
|
||||
if (!riscv_is_halted(target)) {
|
||||
uint32_t dmstatus;
|
||||
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
LOG_ERROR("unable to halt hart %d", r->current_hartid);
|
||||
LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
|
||||
LOG_ERROR(" dmstatus =0x%08x", dmstatus);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Select all harts that were prepped and that are selectable, clearing the
|
||||
* prepped flag on the harts that actually were selected. */
|
||||
static int select_prepped_harts(struct target *target, bool *use_hasel)
|
||||
|
@ -3047,6 +3013,7 @@ static int select_prepped_harts(struct target *target, bool *use_hasel)
|
|||
riscv013_info_t *info = get_info(t);
|
||||
unsigned index = info->index;
|
||||
LOG_DEBUG("index=%d, coreid=%d, prepped=%d", index, t->coreid, r->prepped);
|
||||
r->selected = r->prepped;
|
||||
if (r->prepped) {
|
||||
hawindow[index / 32] |= 1 << (index % 32);
|
||||
r->prepped = false;
|
||||
|
@ -3072,6 +3039,63 @@ static int select_prepped_harts(struct target *target, bool *use_hasel)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv013_halt_prep(struct target *target)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv013_halt_go(struct target *target)
|
||||
{
|
||||
bool use_hasel = false;
|
||||
if (!riscv_rtos_enabled(target)) {
|
||||
if (select_prepped_harts(target, &use_hasel) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("halting hart %d", r->current_hartid);
|
||||
|
||||
/* Issue the halt command, and then wait for the current hart to halt. */
|
||||
uint32_t dmcontrol = DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_HALTREQ;
|
||||
if (use_hasel)
|
||||
dmcontrol |= DMI_DMCONTROL_HASEL;
|
||||
dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
if (riscv_is_halted(target))
|
||||
break;
|
||||
|
||||
if (!riscv_is_halted(target)) {
|
||||
uint32_t dmstatus;
|
||||
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
LOG_ERROR("unable to halt hart %d", r->current_hartid);
|
||||
LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
|
||||
LOG_ERROR(" dmstatus =0x%08x", dmstatus);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
|
||||
if (use_hasel) {
|
||||
target_list_t *entry;
|
||||
dm013_info_t *dm = get_dm(target);
|
||||
list_for_each_entry(entry, &dm->target_list, list) {
|
||||
struct target *t = entry->target;
|
||||
t->state = TARGET_HALTED;
|
||||
if (t->debug_reason == DBG_REASON_NOTHALTED)
|
||||
t->debug_reason = DBG_REASON_DBGRQ;
|
||||
}
|
||||
}
|
||||
/* The "else" case is handled in halt_go(). */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv013_resume_go(struct target *target)
|
||||
{
|
||||
bool use_hasel = false;
|
||||
|
@ -3634,7 +3658,7 @@ static int riscv013_step_or_resume_current_hart(struct target *target,
|
|||
|
||||
if (step) {
|
||||
LOG_ERROR(" was stepping, halting");
|
||||
riscv013_halt_current_hart(target);
|
||||
riscv_halt(target);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -3731,7 +3755,7 @@ int riscv013_test_compliance(struct target *target)
|
|||
/* TODO: test that hamask registers exist if hasel does. */
|
||||
|
||||
/* haltreq */
|
||||
COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target));
|
||||
COMPLIANCE_MUST_PASS(riscv_halt(target));
|
||||
/* This bit is not actually readable according to the spec, so nothing to check.*/
|
||||
|
||||
/* DMSTATUS */
|
||||
|
@ -3742,7 +3766,7 @@ int riscv013_test_compliance(struct target *target)
|
|||
COMPLIANCE_MUST_PASS(riscv_resume(target, true, 0, false, false));
|
||||
|
||||
/* Halt all harts again so the test can continue.*/
|
||||
COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target));
|
||||
COMPLIANCE_MUST_PASS(riscv_halt(target));
|
||||
|
||||
/* HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel. */
|
||||
uint32_t hartinfo;
|
||||
|
@ -4107,7 +4131,7 @@ int riscv013_test_compliance(struct target *target)
|
|||
*/
|
||||
|
||||
/* Halt every hart for any follow-up tests*/
|
||||
COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target));
|
||||
COMPLIANCE_MUST_PASS(riscv_halt(target));
|
||||
|
||||
uint32_t failed_tests = total_tests - passed_tests;
|
||||
if (total_tests == passed_tests) {
|
||||
|
|
|
@ -431,12 +431,6 @@ static void riscv_deinit_target(struct target *target)
|
|||
target->arch_info = NULL;
|
||||
}
|
||||
|
||||
static int oldriscv_halt(struct target *target)
|
||||
{
|
||||
struct target_type *tt = get_target_type(target);
|
||||
return tt->halt(target);
|
||||
}
|
||||
|
||||
static void trigger_from_breakpoint(struct trigger *trigger,
|
||||
const struct breakpoint *breakpoint)
|
||||
{
|
||||
|
@ -820,6 +814,8 @@ int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoi
|
|||
{
|
||||
struct watchpoint *wp = target->watchpoints;
|
||||
|
||||
if (riscv_rtos_enabled(target))
|
||||
riscv_set_current_hartid(target, target->rtos->current_thread - 1);
|
||||
LOG_DEBUG("Current hartid = %d", riscv_current_hartid(target));
|
||||
|
||||
/*TODO instead of disassembling the instruction that we think caused the
|
||||
|
@ -957,13 +953,124 @@ static int old_or_new_riscv_poll(struct target *target)
|
|||
return riscv_openocd_poll(target);
|
||||
}
|
||||
|
||||
static int old_or_new_riscv_halt(struct target *target)
|
||||
int halt_prep(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
if (r->is_halted == NULL)
|
||||
return oldriscv_halt(target);
|
||||
else
|
||||
return riscv_openocd_halt(target);
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
continue;
|
||||
|
||||
LOG_DEBUG("prep hart %d", i);
|
||||
if (riscv_set_current_hartid(target, i) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (riscv_is_halted(target)) {
|
||||
LOG_DEBUG("Hart %d is already halted.", i);
|
||||
} else {
|
||||
if (r->halt_prep(target) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
r->prepped = true;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_halt_go_all_harts(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
continue;
|
||||
|
||||
if (riscv_set_current_hartid(target, i) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (riscv_is_halted(target)) {
|
||||
LOG_DEBUG("Hart %d is already halted.", i);
|
||||
} else {
|
||||
if (r->halt_go(target) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
riscv_invalidate_register_cache(target);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int halt_go(struct target *target)
|
||||
{
|
||||
riscv_info_t *r = riscv_info(target);
|
||||
int result;
|
||||
if (r->is_halted == NULL) {
|
||||
struct target_type *tt = get_target_type(target);
|
||||
result = tt->halt(target);
|
||||
} else {
|
||||
result = riscv_halt_go_all_harts(target);
|
||||
}
|
||||
target->state = TARGET_HALTED;
|
||||
if (target->debug_reason == DBG_REASON_NOTHALTED)
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int halt_finish(struct target *target)
|
||||
{
|
||||
return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
}
|
||||
|
||||
int riscv_halt(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
||||
if (r->is_halted == NULL) {
|
||||
struct target_type *tt = get_target_type(target);
|
||||
return tt->halt(target);
|
||||
}
|
||||
|
||||
LOG_DEBUG("[%d] halting all harts", target->coreid);
|
||||
|
||||
int result = ERROR_OK;
|
||||
if (target->smp) {
|
||||
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
|
||||
struct target *t = tlist->target;
|
||||
if (halt_prep(t) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
}
|
||||
|
||||
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
|
||||
struct target *t = tlist->target;
|
||||
riscv_info_t *i = riscv_info(t);
|
||||
if (i->prepped) {
|
||||
if (halt_go(t) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
|
||||
struct target *t = tlist->target;
|
||||
if (halt_finish(t) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (halt_prep(target) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
if (halt_go(target) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
if (halt_finish(target) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (riscv_rtos_enabled(target)) {
|
||||
if (r->rtos_hartid != -1) {
|
||||
LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid);
|
||||
target->rtos->current_threadid = r->rtos_hartid + 1;
|
||||
target->rtos->current_thread = r->rtos_hartid + 1;
|
||||
} else
|
||||
LOG_DEBUG("halt requested, but no known RTOS hartid");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int riscv_assert_reset(struct target *target)
|
||||
|
@ -998,6 +1105,10 @@ int riscv_resume_prep_all_harts(struct target *target)
|
|||
LOG_DEBUG(" hart %d requested resume, but was already resumed", i);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("[%d] mark as prepped", target->coreid);
|
||||
r->prepped = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -1087,6 +1198,7 @@ static int resume_finish(struct target *target)
|
|||
register_cache_invalidate(target->reg_cache);
|
||||
|
||||
target->state = TARGET_RUNNING;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
return target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
|
||||
}
|
||||
|
||||
|
@ -1322,7 +1434,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
|
|||
LOG_ERROR("Algorithm timed out after %d ms.", timeout_ms);
|
||||
LOG_ERROR(" now = 0x%08x", (uint32_t) now);
|
||||
LOG_ERROR(" start = 0x%08x", (uint32_t) start);
|
||||
oldriscv_halt(target);
|
||||
riscv_halt(target);
|
||||
old_or_new_riscv_poll(target);
|
||||
return ERROR_TARGET_TIMEOUT;
|
||||
}
|
||||
|
@ -1401,6 +1513,7 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
|
|||
} else if (target->state != TARGET_RUNNING && !halted) {
|
||||
LOG_DEBUG(" triggered running");
|
||||
target->state = TARGET_RUNNING;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
return RPH_DISCOVERED_RUNNING;
|
||||
}
|
||||
|
||||
|
@ -1457,14 +1570,21 @@ int riscv_openocd_poll(struct target *target)
|
|||
}
|
||||
LOG_DEBUG(" hart %d halted", halted_hart);
|
||||
|
||||
/* 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
|
||||
* the invariant we hold here. Some harts might have already
|
||||
* halted (as we're either in single-step mode or they also
|
||||
* triggered a breakpoint), so don't attempt to halt those
|
||||
* harts. */
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i)
|
||||
riscv_halt_one_hart(target, i);
|
||||
target->state = TARGET_HALTED;
|
||||
if (set_debug_reason(target, halted_hart) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
target->rtos->current_threadid = halted_hart + 1;
|
||||
target->rtos->current_thread = halted_hart + 1;
|
||||
riscv_set_rtos_hartid(target, halted_hart);
|
||||
|
||||
/* If we're here then at least one hart triggered. That means we want
|
||||
* to go and halt _every_ hart (configured with -rtos riscv) in the
|
||||
* system, as that's the invariant we hold here. Some harts might have
|
||||
* already halted (as we're either in single-step mode or they also
|
||||
* triggered a breakpoint), so don't attempt to halt those harts.
|
||||
* riscv_halt() will do all that for us. */
|
||||
riscv_halt(target);
|
||||
|
||||
} else if (target->smp) {
|
||||
bool halt_discovered = false;
|
||||
|
@ -1481,6 +1601,7 @@ int riscv_openocd_poll(struct target *target)
|
|||
break;
|
||||
case RPH_DISCOVERED_RUNNING:
|
||||
t->state = TARGET_RUNNING;
|
||||
t->debug_reason = DBG_REASON_NOTHALTED;
|
||||
break;
|
||||
case RPH_DISCOVERED_HALTED:
|
||||
halt_discovered = true;
|
||||
|
@ -1495,24 +1616,6 @@ int riscv_openocd_poll(struct target *target)
|
|||
}
|
||||
|
||||
if (halt_discovered) {
|
||||
LOG_DEBUG("Halt other targets in this SMP group.");
|
||||
i = 0;
|
||||
for (struct target_list *list = target->head; list != NULL;
|
||||
list = list->next, i++) {
|
||||
struct target *t = list->target;
|
||||
riscv_info_t *r = riscv_info(t);
|
||||
if (t->state != TARGET_HALTED) {
|
||||
if (riscv_halt_one_hart(t, r->current_hartid) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
t->state = TARGET_HALTED;
|
||||
if (set_debug_reason(t, r->current_hartid) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
newly_halted[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that we have all our ducks in a row, tell the higher layers
|
||||
* what just happened. */
|
||||
i = 0;
|
||||
for (struct target_list *list = target->head; list != NULL;
|
||||
list = list->next, i++) {
|
||||
|
@ -1520,6 +1623,9 @@ int riscv_openocd_poll(struct target *target)
|
|||
if (newly_halted[i])
|
||||
target_call_event_callbacks(t, TARGET_EVENT_HALTED);
|
||||
}
|
||||
|
||||
LOG_DEBUG("Halt other targets in this SMP group.");
|
||||
riscv_halt(target);
|
||||
}
|
||||
return ERROR_OK;
|
||||
|
||||
|
@ -1533,20 +1639,12 @@ int riscv_openocd_poll(struct target *target)
|
|||
|
||||
halted_hart = riscv_current_hartid(target);
|
||||
LOG_DEBUG(" hart %d halted", halted_hart);
|
||||
|
||||
if (set_debug_reason(target, halted_hart) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
target->state = TARGET_HALTED;
|
||||
}
|
||||
|
||||
target->state = TARGET_HALTED;
|
||||
if (set_debug_reason(target, halted_hart) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (riscv_rtos_enabled(target)) {
|
||||
target->rtos->current_threadid = halted_hart + 1;
|
||||
target->rtos->current_thread = halted_hart + 1;
|
||||
riscv_set_rtos_hartid(target, halted_hart);
|
||||
}
|
||||
|
||||
target->state = TARGET_HALTED;
|
||||
|
||||
if (target->debug_reason == DBG_REASON_BREAKPOINT) {
|
||||
int retval;
|
||||
if (riscv_semihosting(target, &retval) != 0)
|
||||
|
@ -1557,44 +1655,6 @@ int riscv_openocd_poll(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_openocd_halt(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
int result;
|
||||
|
||||
LOG_DEBUG("[%d] halting all harts", target->coreid);
|
||||
|
||||
if (target->smp) {
|
||||
LOG_DEBUG("Halt other targets in this SMP group.");
|
||||
struct target_list *targets = target->head;
|
||||
result = ERROR_OK;
|
||||
while (targets) {
|
||||
struct target *t = targets->target;
|
||||
targets = targets->next;
|
||||
if (t->state != TARGET_HALTED) {
|
||||
if (riscv_halt_all_harts(t) != ERROR_OK)
|
||||
result = ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = riscv_halt_all_harts(target);
|
||||
}
|
||||
|
||||
if (riscv_rtos_enabled(target)) {
|
||||
if (r->rtos_hartid != -1) {
|
||||
LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid);
|
||||
target->rtos->current_threadid = r->rtos_hartid + 1;
|
||||
target->rtos->current_thread = r->rtos_hartid + 1;
|
||||
} else
|
||||
LOG_DEBUG("halt requested, but no known RTOS hartid");
|
||||
}
|
||||
|
||||
target->state = TARGET_HALTED;
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
return result;
|
||||
}
|
||||
|
||||
int riscv_openocd_step(
|
||||
struct target *target,
|
||||
int current,
|
||||
|
@ -2178,7 +2238,7 @@ struct target_type riscv_target = {
|
|||
/* poll current target status */
|
||||
.poll = old_or_new_riscv_poll,
|
||||
|
||||
.halt = old_or_new_riscv_halt,
|
||||
.halt = riscv_halt,
|
||||
.resume = riscv_resume,
|
||||
.step = old_or_new_riscv_step,
|
||||
|
||||
|
@ -2228,36 +2288,6 @@ void riscv_info_init(struct target *target, riscv_info_t *r)
|
|||
}
|
||||
}
|
||||
|
||||
int riscv_halt_all_harts(struct target *target)
|
||||
{
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
continue;
|
||||
|
||||
riscv_halt_one_hart(target, i);
|
||||
}
|
||||
|
||||
riscv_invalidate_register_cache(target);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_halt_one_hart(struct target *target, int hartid)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
LOG_DEBUG("halting hart %d", hartid);
|
||||
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (riscv_is_halted(target)) {
|
||||
LOG_DEBUG(" hart %d requested halt, but was already halted", hartid);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int result = r->halt_current_hart(target);
|
||||
register_cache_invalidate(target->reg_cache);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int riscv_resume_go_all_harts(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
|
|
@ -99,6 +99,8 @@ typedef struct {
|
|||
|
||||
/* This target has been prepped and is ready to step/resume. */
|
||||
bool prepped;
|
||||
/* This target was selected using hasel. */
|
||||
bool selected;
|
||||
|
||||
/* Helper functions that target the various RISC-V debug spec
|
||||
* implementations. */
|
||||
|
@ -108,7 +110,6 @@ typedef struct {
|
|||
uint64_t value);
|
||||
int (*select_current_hart)(struct target *);
|
||||
bool (*is_halted)(struct target *target);
|
||||
int (*halt_current_hart)(struct target *);
|
||||
/* Resume this target, as well as every other prepped target that can be
|
||||
* resumed near-simultaneously. Clear the prepped flag on any target that
|
||||
* was resumed. */
|
||||
|
@ -118,6 +119,8 @@ typedef struct {
|
|||
/* Get this target as ready as possible to resume, without actually
|
||||
* resuming. */
|
||||
int (*resume_prep)(struct target *target);
|
||||
int (*halt_prep)(struct target *target);
|
||||
int (*halt_go)(struct target *target);
|
||||
int (*on_step)(struct target *target);
|
||||
enum riscv_halt_reason (*halt_reason)(struct target *target);
|
||||
int (*write_debug_buffer)(struct target *target, unsigned index,
|
||||
|
@ -179,7 +182,7 @@ void select_dmi_via_bscan(struct target *target);
|
|||
/*** OpenOCD Interface */
|
||||
int riscv_openocd_poll(struct target *target);
|
||||
|
||||
int riscv_openocd_halt(struct target *target);
|
||||
int riscv_halt(struct target *target);
|
||||
|
||||
int riscv_resume(
|
||||
struct target *target,
|
||||
|
@ -204,12 +207,6 @@ int riscv_openocd_deassert_reset(struct target *target);
|
|||
/* Initializes the shared RISC-V structure. */
|
||||
void riscv_info_init(struct target *target, riscv_info_t *r);
|
||||
|
||||
/* Run control, possibly for multiple harts. The _all_harts versions resume
|
||||
* all the enabled harts, which when running in RTOS mode is all the harts on
|
||||
* the system. */
|
||||
int riscv_halt_all_harts(struct target *target);
|
||||
int riscv_halt_one_hart(struct target *target, int hartid);
|
||||
|
||||
/* Steps the hart that's currently selected in the RTOS, or if there is no RTOS
|
||||
* then the only hart. */
|
||||
int riscv_step_rtos_hart(struct target *target);
|
||||
|
|
Loading…
Reference in New Issue