Merge pull request #738 from riscv/current_hartid

Remove riscv_info_t.current_hartid
This commit is contained in:
Tim Newsome 2022-10-04 13:17:59 -07:00 committed by GitHub
commit 6d4ba7cca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 121 deletions

View File

@ -1590,7 +1590,6 @@ static int examine(struct target *target)
return result;
target_set_examined(target);
riscv_set_current_hartid(target, 0);
for (size_t i = 0; i < 32; ++i)
reg_cache_set(target, i, -1);
LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64,

View File

@ -38,7 +38,7 @@ static void riscv013_clear_abstract_error(struct target *target);
static int riscv013_get_register(struct target *target,
riscv_reg_t *value, int rid);
static int riscv013_set_register(struct target *target, int regid, uint64_t value);
static int riscv013_select_current_hart(struct target *target);
static int dm013_select_hart(struct target *target, int hart_index);
static int riscv013_halt_prep(struct target *target);
static int riscv013_halt_go(struct target *target);
static int riscv013_resume_go(struct target *target);
@ -139,8 +139,12 @@ typedef struct {
bool was_reset;
/* Targets that are connected to this DM. */
struct list_head target_list;
/* The currently selected hartid on this DM. */
/* Contains the ID of the hart that is currently selected by this DM.
* (If multiple harts are selected this is meaningless, and that corner case
* is not currently handled well.)
*/
int current_hartid;
bool hasel_supported;
/* The program buffer stores executable code. 0 is an illegal instruction,
@ -758,6 +762,12 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
}
}
static int dm013_select_target(struct target *target)
{
riscv013_info_t *info = get_info(target);
return dm013_select_hart(target, info->index);
}
static int execute_abstract_command(struct target *target, uint32_t command)
{
RISCV013_INFO(info);
@ -1384,6 +1394,9 @@ static int register_write_direct(struct target *target, unsigned number,
/** Actually read registers from the target right now. */
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
{
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
int result = register_read_abstract(target, value, number,
register_size(target, number));
@ -1659,8 +1672,7 @@ static int examine(struct target *target)
/* Before doing anything else we must first enumerate the harts. */
if (dm->hart_count < 0) {
for (int i = 0; i < MIN(RISCV_MAX_HARTS, 1 << info->hartsellen); ++i) {
r->current_hartid = i;
if (riscv013_select_current_hart(target) != ERROR_OK)
if (dm013_select_hart(target, i) != ERROR_OK)
return ERROR_FAIL;
uint32_t s;
@ -1678,8 +1690,6 @@ static int examine(struct target *target)
LOG_DEBUG("Detected %d harts.", dm->hart_count);
}
r->current_hartid = target->coreid;
if (dm->hart_count == 0) {
LOG_ERROR("No harts found!");
return ERROR_FAIL;
@ -1688,7 +1698,7 @@ static int examine(struct target *target)
/* Don't call any riscv_* functions until after we've counted the number of
* cores and initialized registers. */
if (riscv013_select_current_hart(target) != ERROR_OK)
if (dm013_select_hart(target, info->index) != ERROR_OK)
return ERROR_FAIL;
bool halted = riscv_is_halted(target);
@ -1948,7 +1958,7 @@ static int riscv013_get_register_buf(struct target *target,
{
assert(regno >= GDB_REGNO_V0 && regno <= GDB_REGNO_V31);
if (riscv_select_current_hart(target) != ERROR_OK)
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK)
@ -2004,7 +2014,7 @@ static int riscv013_set_register_buf(struct target *target,
{
assert(regno >= GDB_REGNO_V0 && regno <= GDB_REGNO_V31);
if (riscv_select_current_hart(target) != ERROR_OK)
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK)
@ -2270,7 +2280,7 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->set_register = &riscv013_set_register;
generic_info->get_register_buf = &riscv013_get_register_buf;
generic_info->set_register_buf = &riscv013_set_register_buf;
generic_info->select_current_hart = &riscv013_select_current_hart;
generic_info->select_target = &dm013_select_target;
generic_info->is_halted = &riscv013_is_halted;
generic_info->resume_go = &riscv013_resume_go;
generic_info->step_current_hart = &riscv013_step_current_hart;
@ -2329,7 +2339,7 @@ static int init_target(struct command_context *cmd_ctx,
static int assert_reset(struct target *target)
{
RISCV_INFO(r);
RISCV013_INFO(info);
select_dmi(target);
@ -2347,7 +2357,7 @@ static int assert_reset(struct target *target)
/* Set haltreq for each hart. */
uint32_t control = control_base;
control = set_hartsel(control_base, target->coreid);
control = set_hartsel(control_base, info->index);
control = set_field(control, DM_DMCONTROL_HALTREQ,
target->reset_halt ? 1 : 0);
dmi_write(target, DM_DMCONTROL, control);
@ -2358,7 +2368,7 @@ static int assert_reset(struct target *target)
} else {
/* Reset just this hart. */
uint32_t control = set_hartsel(control_base, r->current_hartid);
uint32_t control = set_hartsel(control_base, info->index);
control = set_field(control, DM_DMCONTROL_HALTREQ,
target->reset_halt ? 1 : 0);
control = set_field(control, DM_DMCONTROL_NDMRESET, 1);
@ -2381,7 +2391,6 @@ static int assert_reset(struct target *target)
static int deassert_reset(struct target *target)
{
RISCV_INFO(r);
RISCV013_INFO(info);
select_dmi(target);
@ -2389,22 +2398,21 @@ static int deassert_reset(struct target *target)
uint32_t control = 0;
control = set_field(control, DM_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
control = set_field(control, DM_DMCONTROL_DMACTIVE, 1);
dmi_write(target, DM_DMCONTROL,
set_hartsel(control, r->current_hartid));
dmi_write(target, DM_DMCONTROL, set_hartsel(control, info->index));
uint32_t dmstatus;
int dmi_busy_delay = info->dmi_busy_delay;
time_t start = time(NULL);
for (int i = 0; i < riscv_count_harts(target); ++i) {
int index = i;
for (unsigned int i = 0; i < riscv_count_harts(target); ++i) {
unsigned int index = i;
if (target->rtos) {
if (index != target->coreid)
if (index != info->index)
continue;
dmi_write(target, DM_DMCONTROL,
set_hartsel(control, index));
} else {
index = r->current_hartid;
index = info->index;
}
LOG_DEBUG("Waiting for hart %d to come out of reset.", index);
@ -2454,6 +2462,9 @@ static int deassert_reset(struct target *target)
static int execute_fence(struct target *target)
{
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
/* FIXME: For non-coherent systems we need to flush the caches right
* here, but there's no ISA-defined way of doing that. */
{
@ -3416,6 +3427,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
size, address);
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
select_dmi(target);
memset(buffer, 0, count*size);
@ -4045,7 +4059,7 @@ static int riscv013_get_register(struct target *target,
LOG_DEBUG("[%s] reading register %s", target_name(target),
gdb_regno_name(rid));
if (riscv_select_current_hart(target) != ERROR_OK)
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
int result = ERROR_OK;
@ -4070,7 +4084,8 @@ static int riscv013_get_register(struct target *target,
static int riscv013_set_register(struct target *target, int rid, uint64_t value)
{
riscv013_select_current_hart(target);
if (dm013_select_target(target) != ERROR_OK)
return ERROR_FAIL;
LOG_TARGET_DEBUG(target, "writing 0x%" PRIx64 " to register %s",
value, gdb_regno_name(rid));
@ -4100,21 +4115,23 @@ static int riscv013_set_register(struct target *target, int rid, uint64_t value)
return ERROR_OK;
}
static int riscv013_select_current_hart(struct target *target)
static int dm013_select_hart(struct target *target, int hart_index)
{
RISCV_INFO(r);
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
if (r->current_hartid == dm->current_hartid)
if (hart_index == dm->current_hartid)
return ERROR_OK;
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE;
dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
int result = dmi_write(target, DM_DMCONTROL, dmcontrol);
dm->current_hartid = r->current_hartid;
return result;
dmcontrol = set_hartsel(dmcontrol, hart_index);
if (dmi_write(target, DM_DMCONTROL, dmcontrol) != ERROR_OK) {
/* Who knows what the state is? */
dm->current_hartid = -2;
return ERROR_FAIL;
}
dm->current_hartid = hart_index;
return ERROR_OK;
}
/* Select all harts that were prepped and that are selectable, clearing the
@ -4128,6 +4145,7 @@ static int select_prepped_harts(struct target *target, bool *use_hasel)
RISCV_INFO(r);
r->prepped = false;
*use_hasel = false;
dm013_select_target(target);
return ERROR_OK;
}
@ -4178,18 +4196,19 @@ static int riscv013_halt_prep(struct target *target)
static int riscv013_halt_go(struct target *target)
{
RISCV013_INFO(info);
bool use_hasel = false;
if (select_prepped_harts(target, &use_hasel) != ERROR_OK)
return ERROR_FAIL;
RISCV_INFO(r);
LOG_DEBUG("halting hart %d", r->current_hartid);
LOG_TARGET_DEBUG(target, "halting hart");
/* Issue the halt command, and then wait for the current hart to halt. */
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_HALTREQ;
if (use_hasel)
dmcontrol |= DM_DMCONTROL_HASEL;
dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
dmcontrol = set_hartsel(dmcontrol, info->index);
dmi_write(target, DM_DMCONTROL, dmcontrol);
for (size_t i = 0; i < 256; ++i)
if (riscv_is_halted(target))
@ -4258,20 +4277,23 @@ static int riscv013_on_halt(struct target *target)
static bool riscv013_is_halted(struct target *target)
{
RISCV013_INFO(info);
uint32_t dmstatus;
if (dm013_select_target(target) != ERROR_OK)
return false;
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
return false;
if (get_field(dmstatus, DM_DMSTATUS_ANYUNAVAIL))
LOG_ERROR("Hart %d is unavailable.", riscv_current_hartid(target));
LOG_TARGET_ERROR(target, "Hart is unavailable.");
if (get_field(dmstatus, DM_DMSTATUS_ANYNONEXISTENT))
LOG_ERROR("Hart %d doesn't exist.", riscv_current_hartid(target));
LOG_TARGET_ERROR(target, "Hart doesn't exist.");
if (get_field(dmstatus, DM_DMSTATUS_ANYHAVERESET)) {
int hartid = riscv_current_hartid(target);
LOG_INFO("Hart %d unexpectedly reset!", hartid);
LOG_TARGET_INFO(target, "Hart unexpectedly reset!");
/* TODO: Can we make this more obvious to eg. a gdb user? */
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE |
DM_DMCONTROL_ACKHAVERESET;
dmcontrol = set_hartsel(dmcontrol, hartid);
dmcontrol = set_hartsel(dmcontrol, info->index);
/* If we had been halted when we reset, request another halt. If we
* ended up running out of reset, then the user will (hopefully) get a
* message that a reset happened, that the target is running, and then
@ -4776,9 +4798,8 @@ static int riscv013_on_step_or_resume(struct target *target, bool step)
static int riscv013_step_or_resume_current_hart(struct target *target,
bool step, bool use_hasel)
{
RISCV_INFO(r);
if (!riscv_is_halted(target)) {
LOG_ERROR("Hart %d is not halted!", r->current_hartid);
LOG_TARGET_ERROR(target, "Hart is not halted!");
return ERROR_FAIL;
}
LOG_TARGET_DEBUG(target, "resuming (for step?=%d)", step);
@ -4786,11 +4807,12 @@ static int riscv013_step_or_resume_current_hart(struct target *target,
if (riscv_flush_registers(target) != ERROR_OK)
return ERROR_FAIL;
dm013_info_t *dm = get_dm(target);
/* Issue the resume command, and then wait for the current hart to resume. */
uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_RESUMEREQ;
if (use_hasel)
dmcontrol |= DM_DMCONTROL_HASEL;
dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
dmcontrol = set_hartsel(dmcontrol, dm->current_hartid);
dmi_write(target, DM_DMCONTROL, dmcontrol);
dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, 0);

View File

@ -1155,11 +1155,6 @@ static int old_or_new_riscv_poll(struct target *target)
return riscv_openocd_poll(target);
}
int riscv_select_current_hart(struct target *target)
{
return riscv_set_current_hartid(target, target->coreid);
}
int riscv_flush_registers(struct target *target)
{
RISCV_INFO(r);
@ -1228,14 +1223,11 @@ int halt_prep(struct target *target)
LOG_DEBUG("[%s] prep hart, debug_reason=%d", target_name(target),
target->debug_reason);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
if (riscv_is_halted(target)) {
LOG_DEBUG("[%s] Hart is already halted (debug_reason=%d).",
target_name(target), target->debug_reason);
if (target->debug_reason == DBG_REASON_NOTHALTED) {
enum riscv_halt_reason halt_reason =
riscv_halt_reason(target, r->current_hartid);
enum riscv_halt_reason halt_reason = riscv_halt_reason(target);
if (set_debug_reason(target, halt_reason) != ERROR_OK)
return ERROR_FAIL;
}
@ -1252,8 +1244,6 @@ int riscv_halt_go_all_harts(struct target *target)
{
RISCV_INFO(r);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
if (riscv_is_halted(target)) {
LOG_DEBUG("[%s] Hart is already halted.", target_name(target));
} else {
@ -1464,8 +1454,6 @@ static int resume_prep(struct target *target, int current,
}
if (r->is_halted) {
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
if (r->resume_prep(target) != ERROR_OK)
return ERROR_FAIL;
}
@ -1738,8 +1726,6 @@ static int riscv_read_phys_memory(struct target *target, target_addr_t phys_addr
uint32_t size, uint32_t count, uint8_t *buffer)
{
RISCV_INFO(r);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
return r->read_memory(target, phys_address, size, count, buffer, size);
}
@ -1751,9 +1737,6 @@ static int riscv_read_memory(struct target *target, target_addr_t address,
return ERROR_OK;
}
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
target_addr_t physical_addr;
if (target->type->virt2phys(target, address, &physical_addr) == ERROR_OK)
address = physical_addr;
@ -1765,8 +1748,6 @@ static int riscv_read_memory(struct target *target, target_addr_t address,
static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
struct target_type *tt = get_target_type(target);
return tt->write_memory(target, phys_address, size, count, buffer);
}
@ -1779,9 +1760,6 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
return ERROR_OK;
}
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
target_addr_t physical_addr;
if (target->type->virt2phys(target, address, &physical_addr) == ERROR_OK)
address = physical_addr;
@ -1813,9 +1791,6 @@ static int riscv_get_gdb_reg_list_internal(struct target *target,
return ERROR_FAIL;
}
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
switch (reg_class) {
case REG_CLASS_GENERAL:
*reg_list_size = 33;
@ -1971,9 +1946,9 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
return result;
}
/* The current hart id might have been changed in poll(). */
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
/* TODO: The current hart id might have been changed in poll(). */
/* if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL; */
if (reg_pc->type->get(reg_pc) != ERROR_OK)
return ERROR_FAIL;
@ -2113,8 +2088,6 @@ enum riscv_poll_hart {
static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
{
RISCV_INFO(r);
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
return RPH_ERROR;
LOG_TARGET_DEBUG(target, "polling, target->state=%d", target->state);
@ -2194,7 +2167,6 @@ exit:
int riscv_openocd_poll(struct target *target)
{
LOG_DEBUG("polling all harts");
int halted_hart = -1;
enum target_state old_state = target->state;
if (target->smp) {
@ -2205,8 +2177,7 @@ int riscv_openocd_poll(struct target *target)
struct target *t = list->target;
if (!target_was_examined(t))
continue;
riscv_info_t *r = riscv_info(t);
enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid);
enum riscv_poll_hart out = riscv_poll_hart(t, t->coreid);
switch (out) {
case RPH_NO_CHANGE:
break;
@ -2217,7 +2188,7 @@ int riscv_openocd_poll(struct target *target)
case RPH_DISCOVERED_HALTED:
t->state = TARGET_HALTED;
enum riscv_halt_reason halt_reason =
riscv_halt_reason(t, r->current_hartid);
riscv_halt_reason(t);
if (set_debug_reason(t, halt_reason) != ERROR_OK)
return ERROR_FAIL;
@ -2273,8 +2244,7 @@ int riscv_openocd_poll(struct target *target)
return ERROR_OK;
} else {
enum riscv_poll_hart out = riscv_poll_hart(target,
riscv_current_hartid(target));
enum riscv_poll_hart out = riscv_poll_hart(target, target->coreid);
if (out == RPH_NO_CHANGE || out == RPH_DISCOVERED_RUNNING) {
if (target->state == TARGET_RUNNING)
sample_memory(target);
@ -2283,10 +2253,10 @@ int riscv_openocd_poll(struct target *target)
return ERROR_FAIL;
}
halted_hart = riscv_current_hartid(target);
LOG_DEBUG(" hart %d halted", halted_hart);
LOG_TARGET_DEBUG(target, "hart halted");
enum riscv_halt_reason halt_reason = riscv_halt_reason(target, halted_hart);
target->state = TARGET_HALTED;
enum riscv_halt_reason halt_reason = riscv_halt_reason(target);
if (set_debug_reason(target, halt_reason) != ERROR_OK)
return ERROR_FAIL;
target->state = TARGET_HALTED;
@ -3516,7 +3486,6 @@ void riscv_info_init(struct target *target, riscv_info_t *r)
{
memset(r, 0, sizeof(*r));
r->dtm_version = 1;
r->current_hartid = target->coreid;
r->version_specific = NULL;
memset(r->trigger_unique_id, 0xff, sizeof(r->trigger_unique_id));
@ -3542,8 +3511,6 @@ static int riscv_resume_go_all_harts(struct target *target)
RISCV_INFO(r);
LOG_TARGET_DEBUG(target, "resuming hart, state=%d", target->state);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
if (riscv_is_halted(target)) {
if (r->resume_go(target) != ERROR_OK)
return ERROR_FAIL;
@ -3605,8 +3572,6 @@ int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus)
int riscv_step_rtos_hart(struct target *target)
{
RISCV_INFO(r);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
LOG_DEBUG("[%s] stepping", target_name(target));
if (!riscv_is_halted(target)) {
@ -3643,21 +3608,6 @@ unsigned riscv_xlen(const struct target *target)
return r->xlen;
}
int riscv_set_current_hartid(struct target *target, int hartid)
{
RISCV_INFO(r);
if (!r->select_current_hart)
return ERROR_OK;
int previous_hartid = riscv_current_hartid(target);
r->current_hartid = hartid;
LOG_DEBUG("setting hartid to %d, was %d", hartid, previous_hartid);
if (r->select_current_hart(target) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
void riscv_invalidate_register_cache(struct target *target)
{
/* Do not invalidate the register cache if it is not yet set up
@ -3673,13 +3623,8 @@ void riscv_invalidate_register_cache(struct target *target)
}
}
int riscv_current_hartid(const struct target *target)
{
RISCV_INFO(r);
return r->current_hartid;
}
int riscv_count_harts(struct target *target)
unsigned int riscv_count_harts(struct target *target)
{
if (!target)
return 1;
@ -3846,12 +3791,10 @@ bool riscv_is_halted(struct target *target)
return r->is_halted(target);
}
enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
enum riscv_halt_reason riscv_halt_reason(struct target *target)
{
RISCV_INFO(r);
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
return RISCV_HALT_ERROR;
if (!riscv_is_halted(target)) {
if (target->state != TARGET_HALTED) {
LOG_ERROR("Hart is not halted!");
return RISCV_HALT_UNKNOWN;
}

View File

@ -99,12 +99,6 @@ typedef struct {
struct command_context *cmd_ctx;
void *version_specific;
/* The hart that is currently being debugged. Note that this is
* different than the hartid that the RTOS is expected to use. This
* one will change all the time, it's more of a global argument to
* every function than an actual */
int current_hartid;
/* Single buffer that contains all register names, instead of calling
* malloc for each register. Needs to be freed when reg_list is freed. */
char *reg_names;
@ -154,7 +148,7 @@ typedef struct {
int (*get_register_buf)(struct target *target, uint8_t *buf, int regno);
int (*set_register_buf)(struct target *target, int regno,
const uint8_t *buf);
int (*select_current_hart)(struct target *target);
int (*select_target)(struct target *target);
bool (*is_halted)(struct target *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
@ -354,7 +348,7 @@ int riscv_current_hartid(const struct target *target);
/* Lists the number of harts in the system, which are assumed to be
* consecutive and start with mhartid=0. */
int riscv_count_harts(struct target *target);
unsigned int riscv_count_harts(struct target *target);
/** Set register, updating the cache. */
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
@ -370,7 +364,7 @@ int riscv_flush_registers(struct target *target);
/* Checks the state of the current hart -- "is_halted" checks the actual
* on-device register. */
bool riscv_is_halted(struct target *target);
enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid);
enum riscv_halt_reason riscv_halt_reason(struct target *target);
/* These helper functions let the generic program interface get target-specific
* information. */