helper: Remove src/helper from include dirs
[openocd.git] / src / target / riscv / riscv.c
index 0d1cee1bfa27c244e22c7218d522ca163d643b3c..07fb95550c99cf379753e4b3c37be67f34755425 100644 (file)
@@ -8,14 +8,14 @@
 #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"
@@ -23,8 +23,6 @@
 #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)
@@ -184,10 +182,10 @@ struct scan_field _bscan_tunnel_nested_tap_select_dmi[] = {
                }
 };
 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;
@@ -348,8 +346,8 @@ uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out)
                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();
@@ -953,7 +951,7 @@ static int old_or_new_riscv_step(struct target *target, int current,
 {
        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);
@@ -977,7 +975,7 @@ static int riscv_examine(struct target *target)
        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);
@@ -996,7 +994,7 @@ static int oldriscv_poll(struct target *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);
@@ -1051,7 +1049,7 @@ int halt_go(struct target *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 {
@@ -1073,7 +1071,7 @@ int riscv_halt(struct target *target)
 {
        RISCV_INFO(r);
 
-       if (r->is_halted == NULL) {
+       if (!r->is_halted) {
                struct target_type *tt = get_target_type(target);
                return tt->halt(target);
        }
@@ -1299,7 +1297,7 @@ static int resume_go(struct target *target, int current,
 {
        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);
@@ -1446,7 +1444,7 @@ static int riscv_address_translate(struct target *target,
        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))
@@ -1616,6 +1614,18 @@ static int riscv_write_memory(struct target *target, target_addr_t address,
        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)
@@ -1706,7 +1716,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
        }
 
        /* 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);
@@ -1715,7 +1725,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
        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;
@@ -1749,7 +1759,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
 
        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;
@@ -1788,7 +1798,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
                                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, &reg_value, regno) != ERROR_OK)
@@ -1830,7 +1840,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
        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;
@@ -1838,7 +1848,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
                        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);
@@ -1853,7 +1863,86 @@ static int riscv_checksum_memory(struct target *target,
                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(&reg_params[0], "a0", xlen, PARAM_IN_OUT);
+       init_reg_param(&reg_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(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+
+       target_free_working_area(target, crc_algorithm);
+
+       LOG_DEBUG("checksum=0x%" PRIx32 ", result=%d", *checksum, retval);
+
+       return retval;
 }
 
 /*** OpenOCD Helper Functions ***/
@@ -1961,16 +2050,14 @@ int riscv_openocd_poll(struct target *target)
        } 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:
@@ -1981,7 +2068,6 @@ int riscv_openocd_poll(struct target *target)
                                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);
@@ -2293,7 +2379,7 @@ COMMAND_HANDLER(riscv_authdata_read)
                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.");
@@ -2739,6 +2825,14 @@ static unsigned riscv_xlen_nonconst(struct target *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",
 
@@ -2766,6 +2860,7 @@ struct target_type riscv_target = {
        .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,
 
@@ -2783,6 +2878,7 @@ struct target_type riscv_target = {
        .commands = riscv_command_handlers,
 
        .address_bits = riscv_xlen_nonconst,
+       .data_bits = riscv_data_bits
 };
 
 /*** RISC-V Interface ***/
@@ -2960,10 +3056,10 @@ void riscv_set_rtos_hartid(struct target *target, int hartid)
 
 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);
 }
@@ -3692,7 +3788,7 @@ int riscv_init_registers(struct target *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;
@@ -3952,7 +4048,7 @@ int riscv_init_registers(struct target *target)
                        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) {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)