-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <assert.h>
#include <stdlib.h>
#define MAX_HWBPS 16
#define DRAM_CACHE_SIZE 16
-uint8_t ir_dtmcontrol[4] = {DTMCONTROL};
+static uint8_t ir_dtmcontrol[4] = {DTMCONTROL};
struct scan_field select_dtmcontrol = {
.in_value = NULL,
.out_value = ir_dtmcontrol
};
-uint8_t ir_dbus[4] = {DBUS};
+static uint8_t ir_dbus[4] = {DBUS};
struct scan_field select_dbus = {
.in_value = NULL,
.out_value = ir_dbus
};
-uint8_t ir_idcode[4] = {0x1};
+static uint8_t ir_idcode[4] = {0x1};
struct scan_field select_idcode = {
.in_value = NULL,
.out_value = ir_idcode
};
-bscan_tunnel_type_t bscan_tunnel_type;
+static bscan_tunnel_type_t bscan_tunnel_type;
int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */
static const uint8_t bscan_zero[4] = {0};
static const uint8_t bscan_one[4] = {1};
-uint8_t ir_user4[4];
-struct scan_field select_user4 = {
+static uint8_t ir_user4[4];
+static struct scan_field select_user4 = {
.in_value = NULL,
.out_value = ir_user4
};
-uint8_t bscan_tunneled_ir_width[4] = {5}; /* overridden by assignment in riscv_init_target */
-struct scan_field _bscan_tunnel_data_register_select_dmi[] = {
+static uint8_t bscan_tunneled_ir_width[4] = {5}; /* overridden by assignment in riscv_init_target */
+static struct scan_field _bscan_tunnel_data_register_select_dmi[] = {
{
.num_bits = 3,
.out_value = bscan_zero,
}
};
-struct scan_field _bscan_tunnel_nested_tap_select_dmi[] = {
+static struct scan_field _bscan_tunnel_nested_tap_select_dmi[] = {
{
.num_bits = 1,
.out_value = bscan_zero,
.in_value = NULL,
}
};
-struct scan_field *bscan_tunnel_nested_tap_select_dmi = _bscan_tunnel_nested_tap_select_dmi;
-uint32_t bscan_tunnel_nested_tap_select_dmi_num_fields = ARRAY_SIZE(_bscan_tunnel_nested_tap_select_dmi);
+static struct scan_field *bscan_tunnel_nested_tap_select_dmi = _bscan_tunnel_nested_tap_select_dmi;
+static uint32_t bscan_tunnel_nested_tap_select_dmi_num_fields = ARRAY_SIZE(_bscan_tunnel_nested_tap_select_dmi);
-struct scan_field *bscan_tunnel_data_register_select_dmi = _bscan_tunnel_data_register_select_dmi;
-uint32_t bscan_tunnel_data_register_select_dmi_num_fields = ARRAY_SIZE(_bscan_tunnel_data_register_select_dmi);
+static struct scan_field *bscan_tunnel_data_register_select_dmi = _bscan_tunnel_data_register_select_dmi;
+static uint32_t bscan_tunnel_data_register_select_dmi_num_fields = ARRAY_SIZE(_bscan_tunnel_data_register_select_dmi);
struct trigger {
uint64_t address;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
-bool riscv_enable_virt2phys = true;
+static bool riscv_enable_virt2phys = true;
bool riscv_ebreakm = true;
bool riscv_ebreaks = true;
bool riscv_ebreaku = true;
RO_REVERSED
} resume_order;
-const virt2phys_info_t sv32 = {
+static const virt2phys_info_t sv32 = {
.name = "Sv32",
.va_bits = 32,
.level = 2,
.pa_ppn_mask = {0x3ff, 0xfff},
};
-const virt2phys_info_t sv39 = {
+static const virt2phys_info_t sv39 = {
.name = "Sv39",
.va_bits = 39,
.level = 3,
.pa_ppn_mask = {0x1ff, 0x1ff, 0x3ffffff},
};
-const virt2phys_info_t sv48 = {
+static const virt2phys_info_t sv48 = {
.name = "Sv48",
.va_bits = 48,
.level = 4,
.pa_ppn_mask = {0x1ff, 0x1ff, 0x1ff, 0x1ffff},
};
-void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before)
+static enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid);
+static void riscv_info_init(struct target *target, struct riscv_info *r);
+static void riscv_invalidate_register_cache(struct target *target);
+static int riscv_step_rtos_hart(struct target *target);
+
+static void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before)
{
RISCV_INFO(r);
uint32_t now = timeval_ms() & 0xffffffff;
static struct target_type *get_target_type(struct target *target)
{
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
-
- if (!info) {
+ if (!target->arch_info) {
LOG_ERROR("Target has not been initialized");
return NULL;
}
+ RISCV_INFO(info);
switch (info->dtm_version) {
case 0:
return &riscv011_target;
static int riscv_create_target(struct target *target, Jim_Interp *interp)
{
LOG_DEBUG("riscv_create_target()");
- target->arch_info = calloc(1, sizeof(riscv_info_t));
+ target->arch_info = calloc(1, sizeof(struct riscv_info));
if (!target->arch_info) {
LOG_ERROR("Failed to allocate RISC-V target structure.");
return ERROR_FAIL;
if (bscan_tunnel_ir_width != 0) {
assert(target->tap->ir_length >= 6);
uint32_t ir_user4_raw = 0x23 << (target->tap->ir_length - 6);
- ir_user4[0] = (uint8_t)ir_user4_raw;
- ir_user4[1] = (uint8_t)(ir_user4_raw >>= 8);
- ir_user4[2] = (uint8_t)(ir_user4_raw >>= 8);
- ir_user4[3] = (uint8_t)(ir_user4_raw >>= 8);
+ h_u32_to_le(ir_user4, ir_user4_raw);
select_user4.num_bits = target->tap->ir_length;
bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width;
if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
{
LOG_DEBUG("riscv_deinit_target()");
- riscv_info_t *info = target->arch_info;
+ struct riscv_info *info = target->arch_info;
struct target_type *tt = get_target_type(target);
- if (tt && info->version_specific)
+ if (tt && info && info->version_specific)
tt->deinit_target(target);
riscv_free_registers(target);
+ if (!info)
+ return;
+
range_list_t *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &info->expose_csr, list) {
free(entry->name);
return result;
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
- result = ERROR_OK;
switch (type) {
case 1:
result = maybe_add_trigger_t1(target, trigger, tdata1);
return ERROR_FAIL;
}
-int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
{
LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, breakpoint->address);
assert(breakpoint);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- breakpoint->set = true;
+ breakpoint->is_set = true;
return ERROR_OK;
}
return ERROR_OK;
}
-int riscv_remove_breakpoint(struct target *target,
+static int riscv_remove_breakpoint(struct target *target,
struct breakpoint *breakpoint)
{
if (breakpoint->type == BKPT_SOFT) {
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- breakpoint->set = false;
+ breakpoint->is_set = false;
return ERROR_OK;
}
int result = add_trigger(target, &trigger);
if (result != ERROR_OK)
return result;
- watchpoint->set = true;
+ watchpoint->is_set = true;
return ERROR_OK;
}
int result = remove_trigger(target, &trigger);
if (result != ERROR_OK)
return result;
- watchpoint->set = false;
+ watchpoint->is_set = false;
return ERROR_OK;
}
* The GDB server uses this information to tell GDB what data address has
* been hit, which enables GDB to print the hit variable along with its old
* and new value. */
-int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
+static int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
{
struct watchpoint *wp = target->watchpoints;
return riscv_set_current_hartid(target, target->coreid);
}
-int halt_prep(struct target *target)
+static int halt_prep(struct target *target)
{
RISCV_INFO(r);
return ERROR_OK;
}
-int riscv_halt_go_all_harts(struct target *target)
+static int riscv_halt_go_all_harts(struct target *target)
{
RISCV_INFO(r);
return ERROR_OK;
}
-int halt_go(struct target *target)
+static int halt_go(struct target *target)
{
- riscv_info_t *r = riscv_info(target);
+ RISCV_INFO(r);
int result;
if (!r->is_halted) {
struct target_type *tt = get_target_type(target);
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target;
- riscv_info_t *i = riscv_info(t);
+ struct riscv_info *i = riscv_info(t);
if (i->prepped) {
if (halt_go(t) != ERROR_OK)
result = ERROR_FAIL;
return tt->deassert_reset(target);
}
-int riscv_resume_prep_all_harts(struct target *target)
+static int riscv_resume_prep_all_harts(struct target *target)
{
RISCV_INFO(r);
struct watchpoint *watchpoint = target->watchpoints;
int i = 0;
while (watchpoint) {
- LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set);
- state[i] = watchpoint->set;
- if (watchpoint->set) {
+ LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->is_set);
+ state[i] = watchpoint->is_set;
+ if (watchpoint->is_set) {
if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK)
return ERROR_FAIL;
}
static int resume_go(struct target *target, int current,
target_addr_t address, int handle_breakpoints, int debug_execution)
{
- riscv_info_t *r = riscv_info(target);
+ RISCV_INFO(r);
int result;
if (!r->is_halted) {
struct target_type *tt = get_target_type(target);
* @par single_hart When true, only resume a single hart even if SMP is
* configured. This is used to run algorithms on just one hart.
*/
-int riscv_resume(
+static int riscv_resume(
struct target *target,
int current,
target_addr_t address,
foreach_smp_target_direction(resume_order == RO_NORMAL,
tlist, target->smp_targets) {
struct target *t = tlist->target;
- riscv_info_t *i = riscv_info(t);
+ struct riscv_info *i = riscv_info(t);
if (i->prepped) {
if (resume_go(t, current, address, handle_breakpoints,
debug_execution) != ERROR_OK)
LOG_DEBUG("virtual=0x%" TARGET_PRIxADDR "; mode=%s", virtual, info->name);
/* verify bits xlen-1:va_bits-1 are all equal */
+ assert(xlen >= info->va_bits);
target_addr_t mask = ((target_addr_t)1 << (xlen - (info->va_bits - 1))) - 1;
target_addr_t masked_msbs = (virtual >> (info->va_bits - 1)) & mask;
if (masked_msbs != 0 && masked_msbs != mask) {
return tt->write_memory(target, address, size, count, buffer);
}
-const char *riscv_get_gdb_arch(struct target *target)
+static const char *riscv_get_gdb_arch(const struct target *target)
{
switch (riscv_xlen(target)) {
case 32:
static int riscv_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point,
- target_addr_t exit_point, int timeout_ms, void *arch_info)
+ target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
{
RISCV_INFO(info);
}
if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
+ LOG_TARGET_ERROR(target, "not halted (run target algo)");
return ERROR_TARGET_NOT_HALTED;
}
buf_set_u64(reg_params[1].value, 0, xlen, count);
/* 20 second timeout/megabyte */
- int timeout = 20000 * (1 + (count / (1024 * 1024)));
+ unsigned int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
crc_algorithm->address,
return RPH_NO_CHANGE;
}
-int set_debug_reason(struct target *target, enum riscv_halt_reason halt_reason)
+static int set_debug_reason(struct target *target, enum riscv_halt_reason halt_reason)
{
switch (halt_reason) {
case RISCV_HALT_BREAKPOINT:
return ERROR_OK;
}
-int sample_memory(struct target *target)
+static int sample_memory(struct target *target)
{
RISCV_INFO(r);
int halted_hart = -1;
if (target->smp) {
- unsigned halts_discovered = 0;
unsigned should_remain_halted = 0;
unsigned should_resume = 0;
struct target_list *list;
foreach_smp_target(list, target->smp_targets) {
struct target *t = list->target;
- riscv_info_t *r = riscv_info(t);
+ struct riscv_info *r = riscv_info(t);
enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid);
switch (out) {
case RPH_NO_CHANGE:
t->debug_reason = DBG_REASON_NOTHALTED;
break;
case RPH_DISCOVERED_HALTED:
- halts_discovered++;
t->state = TARGET_HALTED;
enum riscv_halt_reason halt_reason =
riscv_halt_reason(t, r->current_hartid);
if (halt_reason == RISCV_HALT_BREAKPOINT) {
int retval;
switch (riscv_semihosting(t, &retval)) {
- case SEMI_NONE:
- case SEMI_WAITING:
+ case SEMIHOSTING_NONE:
+ case SEMIHOSTING_WAITING:
/* This hart should remain halted. */
should_remain_halted++;
break;
- case SEMI_HANDLED:
+ case SEMIHOSTING_HANDLED:
/* This hart should be resumed, along with any other
* harts that halted due to haltgroups. */
should_resume++;
break;
- case SEMI_ERROR:
+ case SEMIHOSTING_ERROR:
return retval;
}
} else if (halt_reason != RISCV_HALT_GROUP) {
if (target->debug_reason == DBG_REASON_BREAKPOINT) {
int retval;
switch (riscv_semihosting(target, &retval)) {
- case SEMI_NONE:
- case SEMI_WAITING:
+ case SEMIHOSTING_NONE:
+ case SEMIHOSTING_WAITING:
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
break;
- case SEMI_HANDLED:
+ case SEMIHOSTING_HANDLED:
if (riscv_resume(target, true, 0, 0, 0, false) != ERROR_OK)
return ERROR_FAIL;
break;
- case SEMI_ERROR:
+ case SEMIHOSTING_ERROR:
return retval;
}
} else {
return ERROR_OK;
}
-COMMAND_HANDLER(riscv_set_prefer_sba)
-{
- struct target *target = get_current_target(CMD_CTX);
- RISCV_INFO(r);
- bool prefer_sba;
- LOG_WARNING("`riscv set_prefer_sba` is deprecated. Please use `riscv set_mem_access` instead.");
- if (CMD_ARGC != 1) {
- LOG_ERROR("Command takes exactly 1 parameter");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], prefer_sba);
- if (prefer_sba) {
- /* Use system bus with highest priority */
- r->mem_access_methods[0] = RISCV_MEM_ACCESS_SYSBUS;
- r->mem_access_methods[1] = RISCV_MEM_ACCESS_PROGBUF;
- r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT;
- } else {
- /* Use progbuf with highest priority */
- r->mem_access_methods[0] = RISCV_MEM_ACCESS_PROGBUF;
- r->mem_access_methods[1] = RISCV_MEM_ACCESS_SYSBUS;
- r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT;
- }
-
- /* Reset warning flags */
- r->mem_access_progbuf_warn = true;
- r->mem_access_sysbus_warn = true;
- r->mem_access_abstract_warn = true;
-
- return ERROR_OK;
-}
-
COMMAND_HANDLER(riscv_set_mem_access)
{
struct target *target = get_current_target(CMD_CTX);
return ERROR_OK;
}
-int parse_ranges(struct list_head *ranges, const char *tcl_arg, const char *reg_type, unsigned int max_val)
+static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const char *reg_type, unsigned int max_val)
{
char *args = strdup(tcl_arg);
if (!args)
uint32_t value;
unsigned int index = 0;
- if (CMD_ARGC == 0) {
- /* nop */
- } else if (CMD_ARGC == 1) {
+ if (CMD_ARGC == 0 || CMD_ARGC > 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (CMD_ARGC == 1) {
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value);
- } else if (CMD_ARGC == 2) {
+ } else {
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], index);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- } else {
- LOG_ERROR("Command takes at most 2 arguments");
- return ERROR_COMMAND_SYNTAX_ERROR;
}
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);
- if (r->authdata_write) {
- return r->authdata_write(target, value, index);
- } else {
+ if (!r->authdata_write) {
LOG_ERROR("authdata_write is not implemented for this target.");
return ERROR_FAIL;
}
+
+ return r->authdata_write(target, value, index);
}
COMMAND_HANDLER(riscv_dmi_read)
}
}
-COMMAND_HANDLER(riscv_test_sba_config_reg)
-{
- if (CMD_ARGC != 4) {
- LOG_ERROR("Command takes exactly 4 arguments");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- struct target *target = get_current_target(CMD_CTX);
- RISCV_INFO(r);
-
- target_addr_t legal_address;
- uint32_t num_words;
- target_addr_t illegal_address;
- bool run_sbbusyerror_test;
-
- COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], legal_address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], num_words);
- COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[2], illegal_address);
- COMMAND_PARSE_ON_OFF(CMD_ARGV[3], run_sbbusyerror_test);
-
- if (r->test_sba_config_reg) {
- return r->test_sba_config_reg(target, legal_address, num_words,
- illegal_address, run_sbbusyerror_test);
- } else {
- LOG_ERROR("test_sba_config_reg is not implemented for this target.");
- return ERROR_FAIL;
- }
-}
-
COMMAND_HANDLER(riscv_reset_delays)
{
int wait = 0;
.usage = "[sec]",
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
},
- {
- .name = "set_prefer_sba",
- .handler = riscv_set_prefer_sba,
- .mode = COMMAND_ANY,
- .usage = "on|off",
- .help = "When on, prefer to use System Bus Access to access memory. "
- "When off (default), prefer to use the Program Buffer to access memory."
- },
{
.name = "set_mem_access",
.handler = riscv_set_mem_access,
.usage = "address value",
.help = "Perform a 32-bit DMI write of value at address."
},
- {
- .name = "test_sba_config_reg",
- .handler = riscv_test_sba_config_reg,
- .mode = COMMAND_ANY,
- .usage = "legal_address num_words "
- "illegal_address run_sbbusyerror_test[on/off]",
- .help = "Perform a series of tests on the SBCS register. "
- "Inputs are a legal, 128-byte aligned address and a number of words to "
- "read/write starting at that address (i.e., address range [legal address, "
- "legal_address+word_size*num_words) must be legally readable/writable), "
- "an illegal, 128-byte aligned address for error flag/handling cases, "
- "and whether sbbusyerror test should be run."
- },
{
.name = "reset_delays",
.handler = riscv_reset_delays,
* protocol, then a command like `riscv semihosting enable` will make
* sense, but for now all semihosting commands are prefixed with `arm`.
*/
-extern const struct command_registration semihosting_common_handlers[];
-const struct command_registration riscv_command_handlers[] = {
+static const struct command_registration riscv_command_handlers[] = {
{
.name = "riscv",
.mode = COMMAND_ANY,
/*** RISC-V Interface ***/
-void riscv_info_init(struct target *target, riscv_info_t *r)
+/* Initializes the shared RISC-V structure. */
+static void riscv_info_init(struct target *target, struct riscv_info *r)
{
memset(r, 0, sizeof(*r));
+
+ r->common_magic = RISCV_COMMON_MAGIC;
+
r->dtm_version = 1;
- r->registers_initialized = false;
r->current_hartid = target->coreid;
r->version_specific = NULL;
return ERROR_OK;
}
-int riscv_step_rtos_hart(struct target *target)
+/* Steps the hart that's currently selected in the RTOS, or if there is no RTOS
+ * then the only hart. */
+static int riscv_step_rtos_hart(struct target *target)
{
RISCV_INFO(r);
if (riscv_select_current_hart(target) != ERROR_OK)
return ERROR_OK;
}
-void riscv_invalidate_register_cache(struct target *target)
+/* Invalidates the register cache. */
+static void riscv_invalidate_register_cache(struct target *target)
{
- RISCV_INFO(r);
-
LOG_DEBUG("[%d]", target->coreid);
register_cache_invalidate(target->reg_cache);
for (size_t i = 0; i < target->reg_cache->num_regs; ++i) {
struct reg *reg = &target->reg_cache->reg_list[i];
reg->valid = false;
}
-
- r->registers_initialized = true;
}
int riscv_current_hartid(const struct target *target)
return r->is_halted(target);
}
-enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
+static enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
{
RISCV_INFO(r);
if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
.type = REG_TYPE_ARCH_DEFINED,
.id = "FPU_FD",
.type_class = REG_TYPE_CLASS_UNION,
- .reg_type_union = &single_double_union
+ { .reg_type_union = &single_double_union }
};
static struct reg_data_type type_uint8 = { .type = REG_TYPE_UINT8, .id = "uint8" };
static struct reg_data_type type_uint16 = { .type = REG_TYPE_UINT16, .id = "uint16" };