diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index e0f92d41c..d999ab397 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -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, diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 90824c6b4..494eeaa20 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -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); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index d7b5f4805..4a1145bb6 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -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; } diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 898d8b5c0..74eff7007 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -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. */