#include "config.h"
#endif
+#include <helper/log.h>
+#include <helper/time_support.h>
#include "target/target.h"
#include "target/algorithm.h"
#include "target/target_type.h"
-#include "log.h"
#include "jtag/jtag.h"
#include "target/register.h"
#include "target/breakpoints.h"
-#include "helper/time_support.h"
#include "riscv.h"
#include "gdb_regs.h"
#include "rtos/rtos.h"
#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
-#define DIM(x) (sizeof(x)/sizeof(*x))
-
/* Constants for legacy SiFive hardware breakpoints. */
#define CSR_BPCONTROL_X (1<<0)
#define CSR_BPCONTROL_W (1<<1)
}
};
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 = DIM(_bscan_tunnel_nested_tap_select_dmi);
+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 = DIM(_bscan_tunnel_data_register_select_dmi);
+uint32_t bscan_tunnel_data_register_select_dmi_num_fields = ARRAY_SIZE(_bscan_tunnel_data_register_select_dmi);
struct trigger {
uint64_t address;
tunneled_dr[0].in_value = NULL;
}
jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
- jtag_add_dr_scan(target->tap, DIM(tunneled_ir), tunneled_ir, TAP_IDLE);
- jtag_add_dr_scan(target->tap, DIM(tunneled_dr), tunneled_dr, TAP_IDLE);
+ jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_ir), tunneled_ir, TAP_IDLE);
+ jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_dr), tunneled_dr, TAP_IDLE);
select_dmi_via_bscan(target);
int retval = jtag_execute_queue();
{
RISCV_INFO(r);
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
- if (r->is_halted == NULL)
+ if (!r->is_halted)
return oldriscv_step(target, current, address, handle_breakpoints);
else
return riscv_openocd_step(target, current, address, handle_breakpoints);
LOG_DEBUG(" version=0x%x", info->dtm_version);
struct target_type *tt = get_target_type(target);
- if (tt == NULL)
+ if (!tt)
return ERROR_FAIL;
int result = tt->init_target(info->cmd_ctx, target);
static int old_or_new_riscv_poll(struct target *target)
{
RISCV_INFO(r);
- if (r->is_halted == NULL)
+ if (!r->is_halted)
return oldriscv_poll(target);
else
return riscv_openocd_poll(target);
{
riscv_info_t *r = riscv_info(target);
int result;
- if (r->is_halted == NULL) {
+ if (!r->is_halted) {
struct target_type *tt = get_target_type(target);
result = tt->halt(target);
} else {
{
RISCV_INFO(r);
- if (r->is_halted == NULL) {
+ if (!r->is_halted) {
struct target_type *tt = get_target_type(target);
return tt->halt(target);
}
{
riscv_info_t *r = riscv_info(target);
int result;
- if (r->is_halted == NULL) {
+ if (!r->is_halted) {
struct target_type *tt = get_target_type(target);
result = tt->resume(target, current, address, handle_breakpoints,
debug_execution);
uint64_t ppn_value;
target_addr_t table_address;
virt2phys_info_t *info;
- uint64_t pte;
+ uint64_t pte = 0;
int i;
if (riscv_rtos_enabled(target))
return tt->write_memory(target, address, size, count, buffer);
}
+const char *riscv_get_gdb_arch(struct target *target)
+{
+ switch (riscv_xlen(target)) {
+ case 32:
+ return "riscv:rv32";
+ case 64:
+ return "riscv:rv64";
+ }
+ LOG_ERROR("Unsupported xlen: %d", riscv_xlen(target));
+ return NULL;
+}
+
static int riscv_get_gdb_reg_list_internal(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class, bool read)
}
/* Save registers */
- struct reg *reg_pc = register_get_by_name(target->reg_cache, "pc", 1);
+ struct reg *reg_pc = register_get_by_name(target->reg_cache, "pc", true);
if (!reg_pc || reg_pc->type->get(reg_pc) != ERROR_OK)
return ERROR_FAIL;
uint64_t saved_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
uint64_t saved_regs[32];
for (int i = 0; i < num_reg_params; i++) {
LOG_DEBUG("save %s", reg_params[i].reg_name);
- struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
+ struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, false);
if (!r) {
LOG_ERROR("Couldn't find register named '%s'", reg_params[i].reg_name);
return ERROR_FAIL;
LOG_DEBUG("Disabling Interrupts");
struct reg *reg_mstatus = register_get_by_name(target->reg_cache,
- "mstatus", 1);
+ "mstatus", true);
if (!reg_mstatus) {
LOG_ERROR("Couldn't find mstatus!");
return ERROR_FAIL;
GDB_REGNO_PC,
GDB_REGNO_MSTATUS, GDB_REGNO_MEPC, GDB_REGNO_MCAUSE,
};
- for (unsigned i = 0; i < DIM(regnums); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(regnums); i++) {
enum gdb_regno regno = regnums[i];
riscv_reg_t reg_value;
if (riscv_get_register(target, ®_value, regno) != ERROR_OK)
for (int i = 0; i < num_reg_params; i++) {
if (reg_params[i].direction == PARAM_IN ||
reg_params[i].direction == PARAM_IN_OUT) {
- struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
+ struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, false);
if (r->type->get(r) != ERROR_OK) {
LOG_ERROR("get(%s) failed", r->name);
return ERROR_FAIL;
buf_cpy(r->value, reg_params[i].value, reg_params[i].size);
}
LOG_DEBUG("restore %s", reg_params[i].reg_name);
- struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
+ struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, false);
buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]);
if (r->type->set(r, buf) != ERROR_OK) {
LOG_ERROR("set(%s) failed", r->name);
target_addr_t address, uint32_t count,
uint32_t *checksum)
{
- return ERROR_FAIL;
+ struct working_area *crc_algorithm;
+ struct reg_param reg_params[2];
+ int retval;
+
+ LOG_DEBUG("address=0x%" TARGET_PRIxADDR "; count=0x%" PRIx32, address, count);
+
+ static const uint8_t riscv32_crc_code[] = {
+#include "contrib/loaders/checksum/riscv32_crc.inc"
+ };
+ static const uint8_t riscv64_crc_code[] = {
+#include "contrib/loaders/checksum/riscv64_crc.inc"
+ };
+
+ static const uint8_t *crc_code;
+
+ unsigned xlen = riscv_xlen(target);
+ unsigned crc_code_size;
+ if (xlen == 32) {
+ crc_code = riscv32_crc_code;
+ crc_code_size = sizeof(riscv32_crc_code);
+ } else {
+ crc_code = riscv64_crc_code;
+ crc_code_size = sizeof(riscv64_crc_code);
+ }
+
+ if (count < crc_code_size * 4) {
+ /* Don't use the algorithm for relatively small buffers. It's faster
+ * just to read the memory. target_checksum_memory() will take care of
+ * that if we fail. */
+ return ERROR_FAIL;
+ }
+
+ retval = target_alloc_working_area(target, crc_code_size, &crc_algorithm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (crc_algorithm->address + crc_algorithm->size > address &&
+ crc_algorithm->address < address + count) {
+ /* Region to checksum overlaps with the work area we've been assigned.
+ * Bail. (Would be better to manually checksum what we read there, and
+ * use the algorithm for the rest.) */
+ target_free_working_area(target, crc_algorithm);
+ return ERROR_FAIL;
+ }
+
+ retval = target_write_buffer(target, crc_algorithm->address, crc_code_size,
+ crc_code);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
+ crc_algorithm->address, retval);
+ target_free_working_area(target, crc_algorithm);
+ return retval;
+ }
+
+ init_reg_param(®_params[0], "a0", xlen, PARAM_IN_OUT);
+ init_reg_param(®_params[1], "a1", xlen, PARAM_OUT);
+ buf_set_u64(reg_params[0].value, 0, xlen, address);
+ buf_set_u64(reg_params[1].value, 0, xlen, count);
+
+ /* 20 second timeout/megabyte */
+ int timeout = 20000 * (1 + (count / (1024 * 1024)));
+
+ retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
+ crc_algorithm->address,
+ 0, /* Leave exit point unspecified because we don't know. */
+ timeout, NULL);
+
+ if (retval == ERROR_OK)
+ *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+ else
+ LOG_ERROR("error executing RISC-V CRC algorithm");
+
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+
+ target_free_working_area(target, crc_algorithm);
+
+ LOG_DEBUG("checksum=0x%" PRIx32 ", result=%d", *checksum, retval);
+
+ return retval;
}
/*** OpenOCD Helper Functions ***/
} else if (target->smp) {
unsigned halts_discovered = 0;
unsigned total_targets = 0;
- bool newly_halted[RISCV_MAX_HARTS] = {0};
unsigned should_remain_halted = 0;
unsigned should_resume = 0;
unsigned i = 0;
- for (struct target_list *list = target->head; list != NULL;
+ for (struct target_list *list = target->head; list;
list = list->next, i++) {
total_targets++;
struct target *t = list->target;
riscv_info_t *r = riscv_info(t);
- assert(i < DIM(newly_halted));
enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid);
switch (out) {
case RPH_NO_CHANGE:
break;
case RPH_DISCOVERED_HALTED:
halts_discovered++;
- newly_halted[i] = true;
t->state = TARGET_HALTED;
enum riscv_halt_reason halt_reason =
riscv_halt_reason(t, r->current_hartid);
uint32_t value;
if (r->authdata_read(target, &value) != ERROR_OK)
return ERROR_FAIL;
- command_print(CMD, "0x%" PRIx32, value);
+ command_print_sameline(CMD, "0x%08" PRIx32, value);
return ERROR_OK;
} else {
LOG_ERROR("authdata_read is not implemented for this target.");
return riscv_xlen(target);
}
+static unsigned int riscv_data_bits(struct target *target)
+{
+ RISCV_INFO(r);
+ if (r->data_bits)
+ return r->data_bits(target);
+ return riscv_xlen(target);
+}
+
struct target_type riscv_target = {
.name = "riscv",
.mmu = riscv_mmu,
.virt2phys = riscv_virt2phys,
+ .get_gdb_arch = riscv_get_gdb_arch,
.get_gdb_reg_list = riscv_get_gdb_reg_list,
.get_gdb_reg_list_noread = riscv_get_gdb_reg_list_noread,
.commands = riscv_command_handlers,
.address_bits = riscv_xlen_nonconst,
+ .data_bits = riscv_data_bits
};
/*** RISC-V Interface ***/
int riscv_count_harts(struct target *target)
{
- if (target == NULL)
+ if (!target)
return 1;
RISCV_INFO(r);
- if (r == NULL || r->hart_count == NULL)
+ if (!r || !r->hart_count)
return 1;
return r->hart_count(target);
}
#undef DECLARE_CSR
};
/* encoding.h does not contain the registers in sorted order. */
- qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info);
+ qsort(csr_info, ARRAY_SIZE(csr_info), sizeof(*csr_info), cmp_csr_info);
unsigned csr_info_index = 0;
unsigned custom_range_index = 0;
unsigned csr_number = number - GDB_REGNO_CSR0;
while (csr_info[csr_info_index].number < csr_number &&
- csr_info_index < DIM(csr_info) - 1) {
+ csr_info_index < ARRAY_SIZE(csr_info) - 1) {
csr_info_index++;
}
if (csr_info[csr_info_index].number == csr_number) {