From d52e4668a60212524b3d29b92b47cc21c5317b66 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Jan 2021 12:22:43 -0800 Subject: [PATCH] Remove `-rtos riscv` (#567) * Remove `-rtos riscv`. `-rtos hwwthread` is target-independent and a cleaner way to achieve the same thing. Change-Id: I863a91f9ad66e37dc36f2fbcbffe403b91355556 * Little more cleanup. Change-Id: I8fda2317368a94760bc734abc7f1de6ee5b82a7c * Clean up some more. Change-Id: I64a1e96aa3bd8c0561d4d19930f99e9bc40eab86 * Get rid of riscv_[sg]et_register_on_hart Change-Id: I5ea9439bad0e74d7ed2099935e7fc7292c4a2b7f * Remove hartid arg from set_register. Change-Id: Ib560e3c63ff32191589c74d3ee06b12295107c6f * Remove more references to hartid. Change-Id: Ie9d932fb8b671c478271c1084dad43cad3b2bfbc * Remove some unused code. Change-Id: I233360c6c420d1fc98b923d067e65a9419d88d7b Signed-off-by: Tim Newsome --- src/rtos/Makefile.am | 4 +- src/rtos/riscv_debug.c | 373 -------------------- src/rtos/riscv_debug.h | 13 - src/rtos/rtos.c | 2 - src/target/riscv/riscv-011.c | 29 +- src/target/riscv/riscv-013.c | 661 ++++------------------------------- src/target/riscv/riscv.c | 630 ++++++++++----------------------- src/target/riscv/riscv.h | 44 +-- 8 files changed, 283 insertions(+), 1473 deletions(-) delete mode 100644 src/rtos/riscv_debug.c delete mode 100644 src/rtos/riscv_debug.h diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 2cb8bd147..de54596cd 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -16,7 +16,6 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/chromium-ec.c \ %D%/embKernel.c \ %D%/mqx.c \ - %D%/riscv_debug.c \ %D%/uCOS-III.c \ %D%/nuttx.c \ %D%/hwthread.c \ @@ -30,8 +29,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/rtos_mqx_stackings.h \ %D%/rtos_riot_stackings.h \ %D%/rtos_ucos_iii_stackings.h \ - %D%/nuttx_header.h \ - %D%/riscv_debug.h + %D%/nuttx_header.h %C%_librtos_la_CFLAGS = $(AM_CFLAGS) diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c deleted file mode 100644 index af8c4f1f8..000000000 --- a/src/rtos/riscv_debug.c +++ /dev/null @@ -1,373 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "riscv_debug.h" -#include "target/register.h" -#include "target/target.h" -#include "target/riscv/riscv.h" -#include "server/gdb_server.h" -#include "helper/binarybuffer.h" - -static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size); -static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size); - -static bool riscv_detect_rtos(struct target *target) -{ - LOG_ERROR("riscv_detect_rtos() unimplemented"); - return -1; -} - -extern bool enable_rtos_riscv; - -static int riscv_create_rtos(struct target *target) -{ - LOG_DEBUG("RISC-V Debug 'RTOS' created: this doesn't mean you're running an RTOS, just that you have multi-hart support on RISC-V"); - - if (enable_rtos_riscv) { - LOG_WARNING("`-rtos riscv` is deprecated and will be removed at the end of 2020! Please"); - LOG_WARNING("change your configuration to use `-rtos hwthread` instead. To do that, you"); - LOG_WARNING("will have to explicitly list every hart in the system as a separate target. See"); - LOG_WARNING("https://github.com/riscv/riscv-tests/blob/ec6537fc4a527ca88be2f045e01c460e640ab9c5/debug/targets/SiFive/HiFiveUnleashed.cfg#L11"); - LOG_WARNING("for an example."); - } else { - LOG_ERROR("`-rtos riscv` is deprecated and will be removed at the end of 2020! Until"); - LOG_ERROR("then, you can still use it by adding `enable_rtos_riscv` to your"); - LOG_ERROR("configuration."); - LOG_ERROR("Please change your configuration to use `-rtos hwthread` instead. To do "); - LOG_ERROR("that, you will have to explicitly list every hart in the system as a separate "); - LOG_ERROR("target. See"); - LOG_ERROR("https://github.com/riscv/riscv-tests/blob/ec6537fc4a527ca88be2f045e01c460e640ab9c5/debug/targets/SiFive/HiFiveUnleashed.cfg#L11"); - LOG_ERROR("for an example."); - return ERROR_FAIL; - } - - struct riscv_rtos *r = calloc(1, sizeof(*r)); - target->rtos->rtos_specific_params = r; - - target->rtos->current_threadid = 1; - target->rtos->current_thread = 1; - - target->rtos->gdb_thread_packet = riscv_gdb_thread_packet; - target->rtos->gdb_v_packet = riscv_gdb_v_packet; - - return JIM_OK; -} - -int riscv_update_threads(struct rtos *rtos) -{ - LOG_DEBUG("Updating the RISC-V Hart List"); - - struct target *target = rtos->target; - - /* Figures out how many harts there are on the system. */ - int hart_count = riscv_count_harts(rtos->target); - if (rtos->thread_count != hart_count) { - rtos_free_threadlist(rtos); - rtos->thread_count = hart_count; - rtos->thread_details = calloc(rtos->thread_count, sizeof(*rtos->thread_details)); - for (int i = 0; i < rtos->thread_count; ++i) { - LOG_DEBUG(" Setting up Hart %d", i); - rtos->thread_details[i].threadid = i + 1; - rtos->thread_details[i].exists = true; - if (asprintf(&rtos->thread_details[i].thread_name_str, "Hart %d", i) < 0) - LOG_ERROR("riscv_update_threads() failed asprintf"); - if (asprintf(&rtos->thread_details[i].extra_info_str, "RV%d", - riscv_xlen_of_hart(target, i)) < 0) - LOG_ERROR("riscv_update_threads() failed asprintf"); - } - } - return JIM_OK; -} - -static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size) -{ - struct target *target = get_target_from_connection(connection); - struct rtos *rtos = target->rtos; - struct riscv_rtos *r = (struct riscv_rtos *)(target->rtos->rtos_specific_params); - - char *packet_stttrr = malloc(packet_size + 1); - memset(packet_stttrr, '\0', packet_size + 1); - memcpy(packet_stttrr, packet, packet_size); - LOG_DEBUG("handling packet '%s'", packet_stttrr); - - switch (packet[0]) { - case 'q': - if (strncmp(packet, "qfThreadInfo", 12) == 0) { - riscv_update_threads(target->rtos); - r->qs_thread_info_offset = 1; - - char m[16]; - snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid); - gdb_put_packet(connection, m, strlen(m)); - return ERROR_OK; - } - - if (strncmp(packet, "qsThreadInfo", 12) == 0) { - if (r->qs_thread_info_offset >= rtos->thread_count) { - gdb_put_packet(connection, "l", 1); - return ERROR_OK; - } - - int tid = r->qs_thread_info_offset++; - char m[16]; - snprintf(m, 16, "m%08x", (int)rtos->thread_details[tid].threadid); - gdb_put_packet(connection, m, strlen(m)); - return ERROR_OK; - } - - if (strncmp(packet, "qAttached", 9) == 0) { - gdb_put_packet(connection, "1", 1); - return ERROR_OK; - } - - if (strncmp(packet, "qThreadExtraInfo", 16) == 0) { - char tid_str[32]; - memcpy(tid_str, packet + 17, packet_size - 17); - tid_str[packet_size - 17] = '\0'; - char *end; - int tid = strtol(tid_str, &end, 16); - if (*end != '\0') { - LOG_ERROR("Got qThreadExtraInfo with non-numeric TID: '%s'", tid_str); - gdb_put_packet(connection, NULL, 0); - return ERROR_FAIL; - } - - char m[16]; - snprintf(m, 16, "hart %d", tid); - char h[33]; - h[0] = '\0'; - for (size_t i = 0; i < strlen(m); ++i) { - char byte[3]; - snprintf(byte, 3, "%02x", m[i]); - strncat(h, byte, 32); - } - gdb_put_packet(connection, h, strlen(h)); - return ERROR_OK; - } - - if (strcmp(packet, "qTStatus") == 0) { - gdb_put_packet(connection, "T0", 2); - return ERROR_OK; - } - - if (strcmp(packet, "qC") == 0) { - char rep_str[32]; - snprintf(rep_str, 32, "QC%" PRIx64, rtos->current_threadid); - gdb_put_packet(connection, rep_str, strlen(rep_str)); - return ERROR_OK; - } - - return GDB_THREAD_PACKET_NOT_CONSUMED; - - case 'Q': - return GDB_THREAD_PACKET_NOT_CONSUMED; - - case 'H': - /* ‘H op thread-id’ - * - * Set thread for subsequent operations (‘m’, ‘M’, ‘g’, ‘G’, - * et.al.). Depending on the operation to be performed, op - * should be ‘c’ for step and continue operations (note that - * this is deprecated, supporting the ‘vCont’ command is a - * better option), and ‘g’ for other operations. The thread - * designator thread-id has the format and interpretation - * described in thread-id syntax. - * - * Reply: - * ‘OK’ for success - * ‘E NN’ for an error - */ - { - char tid_str[32]; - memcpy(tid_str, packet + 2, packet_size - 2); - tid_str[packet_size - 2] = '\0'; - char *entptr; - int tid = strtol(tid_str, &entptr, 16); - if (*entptr != '\0') { - LOG_ERROR("Got H packet, but without integer: %s", tid_str); - return GDB_THREAD_PACKET_NOT_CONSUMED; - } - - switch (tid) { - case 0: - case -1: - riscv_set_all_rtos_harts(target); - break; - default: - riscv_set_rtos_hartid(target, tid - 1); - rtos->current_threadid = tid; - break; - } - - switch (packet[1]) { - case 'g': - case 'c': - gdb_put_packet(connection, "OK", 2); - return ERROR_OK; - default: - LOG_ERROR("Unknown H packet subtype %2x\n", packet[1]); - gdb_put_packet(connection, NULL, 0); - return ERROR_FAIL; - } - } - - case 'T': - { - char tid_str[32]; - memcpy(tid_str, packet + 1, packet_size - 1); - tid_str[packet_size - 1] = '\0'; - char *end; - int tid = strtol(tid_str, &end, 16); - if (*end != '\0') { - LOG_ERROR("T packet with non-numeric tid %s", tid_str); - gdb_put_packet(connection, NULL, 0); - return ERROR_FAIL; - } - - riscv_update_threads(target->rtos); - if (tid <= target->rtos->thread_count) { - gdb_put_packet(connection, "OK", 2); - return ERROR_OK; - } else { - gdb_put_packet(connection, "E00", 3); - return ERROR_OK; - } - } - - case 'c': - case 's': - target->state = TARGET_HALTED; - return JIM_OK; - - case 'R': - gdb_put_packet(connection, "E00", 3); - return JIM_OK; - - default: - LOG_ERROR("Unknown packet of type 0x%2.2x", packet[0]); - gdb_put_packet(connection, NULL, 0); - return JIM_OK; - } -} - -static int riscv_gdb_v_packet(struct connection *connection, const char *packet, int packet_size) -{ - char *packet_stttrr = malloc(packet_size + 1); - memset(packet_stttrr, '\0', packet_size + 1); - memcpy(packet_stttrr, packet, packet_size); - LOG_DEBUG("handling packet '%s'", packet_stttrr); - - struct target *target = get_target_from_connection(connection); - - if (strcmp(packet_stttrr, "vCont?") == 0) { - static const char *message = "OK"; - gdb_put_packet(connection, (char *)message, strlen(message)); - return JIM_OK; - } - - int threadid; - if (sscanf(packet_stttrr, "vCont;s:%d;c", &threadid) == 1) { - riscv_set_rtos_hartid(target, threadid - 1); - riscv_step_rtos_hart(target); - /* Stepping changes the current thread to whichever thread was stepped. */ - target->rtos->current_threadid = threadid; - - gdb_put_packet(connection, "S05", 3); - return JIM_OK; - - } else if (strcmp(packet_stttrr, "vCont;c") == 0) { - target_call_event_callbacks(target, TARGET_EVENT_GDB_START); - target_call_event_callbacks(target, TARGET_EVENT_RESUME_START); - riscv_set_all_rtos_harts(target); - riscv_resume(target, 1, 0, 0, 0, false); - target->state = TARGET_RUNNING; - gdb_set_frontend_state_running(connection); - target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - target_call_event_callbacks(target, TARGET_EVENT_RESUME_END); - return JIM_OK; - - } else if (strncmp(packet_stttrr, "vCont", 5) == 0) { - LOG_ERROR("Got unknown vCont-type packet"); - } - - return GDB_THREAD_PACKET_NOT_CONSUMED; -} - -static int riscv_get_thread_reg(struct rtos *rtos, int64_t thread_id, - uint32_t reg_num, struct rtos_reg *rtos_reg) -{ - LOG_DEBUG("thread_id=%" PRId64 ", reg_num=%d", thread_id, reg_num); - - struct target *target = rtos->target; - struct reg *reg = register_get_by_number(target->reg_cache, reg_num, true); - if (!reg) - return ERROR_FAIL; - - uint64_t reg_value = 0; - if (riscv_get_register_on_hart(rtos->target, ®_value, thread_id - 1, - reg_num) != ERROR_OK) - return ERROR_FAIL; - - buf_set_u64(rtos_reg->value, 0, 64, reg_value); - rtos_reg->number = reg->number; - rtos_reg->size = reg->size; - return ERROR_OK; -} - -static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, - struct rtos_reg **reg_list, int *num_regs) -{ - LOG_DEBUG("Updating RISC-V register list for hart %d", (int)(thread_id - 1)); - - /* We return just the GPRs here. */ - - *num_regs = 33; - int xlen = riscv_xlen_of_hart(rtos->target, thread_id - 1); - - *reg_list = calloc(*num_regs, sizeof(struct rtos_reg)); - for (int i = 0; i < *num_regs; ++i) { - uint64_t reg_value; - if (riscv_get_register_on_hart(rtos->target, ®_value, thread_id - 1, - i) != ERROR_OK) - return JIM_ERR; - - (*reg_list)[i].number = i; - (*reg_list)[i].size = xlen; - buf_set_u64((*reg_list)[i].value, 0, 64, reg_value); - } - return JIM_OK; -} - -static int riscv_set_reg(struct rtos *rtos, uint32_t reg_num, - uint8_t *reg_value) -{ - struct target *target = rtos->target; - struct reg *reg = register_get_by_number(target->reg_cache, reg_num, true); - if (!reg) - return ERROR_FAIL; - - int hartid = rtos->current_threadid - 1; - uint64_t value = buf_get_u64(reg_value, 0, reg->size); - - return riscv_set_register_on_hart(target, hartid, reg_num, value); -} - -static int riscv_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) -{ - *symbol_list = calloc(1, sizeof(symbol_table_elem_t)); - (*symbol_list)[0].symbol_name = NULL; - (*symbol_list)[0].optional = false; - return JIM_OK; -} - -const struct rtos_type riscv_rtos = { - .name = "riscv", - .detect_rtos = riscv_detect_rtos, - .create = riscv_create_rtos, - .update_threads = riscv_update_threads, - .get_thread_reg = riscv_get_thread_reg, - .get_thread_reg_list = riscv_get_thread_reg_list, - .get_symbol_list_to_lookup = riscv_get_symbol_list_to_lookup, - .set_reg = riscv_set_reg, -}; diff --git a/src/rtos/riscv_debug.h b/src/rtos/riscv_debug.h deleted file mode 100644 index 539edf288..000000000 --- a/src/rtos/riscv_debug.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef RTOS__RISCV_H -#define RTOS__RISCV_H - -#include "rtos.h" - -struct riscv_rtos { - /* The index into the thread list used to handle */ - int qs_thread_info_offset; -}; - -int riscv_update_threads(struct rtos *rtos); - -#endif diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index b391b2cc5..f88925a65 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -27,7 +27,6 @@ #include "server/gdb_server.h" /* RTOSs */ -extern struct rtos_type riscv_rtos; extern struct rtos_type FreeRTOS_rtos; extern struct rtos_type ThreadX_rtos; extern struct rtos_type eCos_rtos; @@ -42,7 +41,6 @@ extern struct rtos_type hwthread_rtos; extern struct rtos_type riot_rtos; static struct rtos_type *rtos_types[] = { - &riscv_rtos, &ThreadX_rtos, &FreeRTOS_rtos, &eCos_rtos, diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 45a44f252..78cd55fae 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -218,8 +218,7 @@ typedef struct { static int poll_target(struct target *target, bool announce); static int riscv011_poll(struct target *target); -static int get_register(struct target *target, riscv_reg_t *value, int hartid, - int regid); +static int get_register(struct target *target, riscv_reg_t *value, int regid); /*** Utility functions. ***/ @@ -1234,7 +1233,7 @@ static int update_mstatus_actual(struct target *target) /* Force reading the register. In that process mstatus_actual will be * updated. */ riscv_reg_t mstatus; - return get_register(target, &mstatus, 0, GDB_REGNO_MSTATUS); + return get_register(target, &mstatus, GDB_REGNO_MSTATUS); } /*** OpenOCD target functions. ***/ @@ -1338,10 +1337,8 @@ static int register_write(struct target *target, unsigned int number, return ERROR_OK; } -static int get_register(struct target *target, riscv_reg_t *value, int hartid, - int regid) +static int get_register(struct target *target, riscv_reg_t *value, int regid) { - assert(hartid == 0); riscv011_info_t *info = get_info(target); maybe_write_tselect(target); @@ -1384,10 +1381,8 @@ static int get_register(struct target *target, riscv_reg_t *value, int hartid, return ERROR_OK; } -static int set_register(struct target *target, int hartid, int regid, - uint64_t value) +static int set_register(struct target *target, int regid, uint64_t value) { - assert(hartid == 0); return register_write(target, regid, value); } @@ -1527,7 +1522,7 @@ static int examine(struct target *target) } /* Pretend this is a 32-bit system until we have found out the true value. */ - r->xlen[0] = 32; + r->xlen = 32; /* Figure out XLEN, and test writing all of Debug RAM while we're at it. */ cache_set32(target, 0, xori(S1, ZERO, -1)); @@ -1555,11 +1550,11 @@ static int examine(struct target *target) uint32_t word1 = cache_get32(target, 1); riscv_info_t *generic_info = (riscv_info_t *) target->arch_info; if (word0 == 1 && word1 == 0) { - generic_info->xlen[0] = 32; + generic_info->xlen = 32; } else if (word0 == 0xffffffff && word1 == 3) { - generic_info->xlen[0] = 64; + generic_info->xlen = 64; } else if (word0 == 0xffffffff && word1 == 0xffffffff) { - generic_info->xlen[0] = 128; + generic_info->xlen = 128; } else { uint32_t exception = cache_get32(target, info->dramsize-1); LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x, exception=0x%x", @@ -1569,11 +1564,11 @@ static int examine(struct target *target) } LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target)); - if (read_remote_csr(target, &r->misa[0], CSR_MISA) != ERROR_OK) { + if (read_remote_csr(target, &r->misa, CSR_MISA) != ERROR_OK) { const unsigned old_csr_misa = 0xf10; LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA, old_csr_misa); - if (read_remote_csr(target, &r->misa[0], old_csr_misa) != ERROR_OK) { + if (read_remote_csr(target, &r->misa, old_csr_misa) != ERROR_OK) { /* Maybe this is an old core that still has $misa at the old * address. */ LOG_ERROR("Failed to read misa at 0x%x.", old_csr_misa); @@ -1595,7 +1590,7 @@ static int examine(struct target *target) for (size_t i = 0; i < 32; ++i) reg_cache_set(target, i, -1); LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64, - riscv_xlen(target), r->misa[0]); + riscv_xlen(target), r->misa); return ERROR_OK; } @@ -2312,7 +2307,7 @@ static int init_target(struct command_context *cmd_ctx, return ERROR_FAIL; /* Assume 32-bit until we discover the real value in examine(). */ - generic_info->xlen[0] = 32; + generic_info->xlen = 32; riscv_init_registers(target); return ERROR_OK; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6848505e1..4163a38cb 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -23,7 +23,6 @@ #include "helper/time_support.h" #include "helper/list.h" #include "riscv.h" -#include "rtos/riscv_debug.h" #include "debug_defines.h" #include "rtos/rtos.h" #include "program.h" @@ -40,8 +39,8 @@ static void riscv013_clear_abstract_error(struct target *target); /* Implementations of the functions in riscv_info_t. */ static int riscv013_get_register(struct target *target, - riscv_reg_t *value, int hid, int rid); -static int riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value); + 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 riscv013_halt_prep(struct target *target); static int riscv013_halt_go(struct target *target); @@ -75,7 +74,6 @@ void write_memory_sba_simple(struct target *target, target_addr_t addr, uint32_t uint32_t write_size, uint32_t sbcs); void read_memory_sba_simple(struct target *target, target_addr_t addr, uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs); -static int riscv013_test_compliance(struct target *target); /** * Since almost everything can be accomplish by scanning the dbus register, all @@ -1329,7 +1327,7 @@ static int register_write_direct(struct target *target, unsigned number, scratch_mem_t scratch; bool use_scratch = false; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && - riscv_supports_extension(target, riscv_current_hartid(target), 'D') && + riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) { /* There are no instructions to move all the bits from a register, so * we need to use some scratch RAM. */ @@ -1359,7 +1357,7 @@ static int register_write_direct(struct target *target, unsigned number, return ERROR_FAIL; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - if (riscv_supports_extension(target, riscv_current_hartid(target), 'D')) + if (riscv_supports_extension(target, 'D')) riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0)); else riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0)); @@ -1443,7 +1441,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t return ERROR_FAIL; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - if (riscv_supports_extension(target, riscv_current_hartid(target), 'D') + if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) { /* There are no instructions to move all the bits from a * register, so we need to use some scratch RAM. */ @@ -1459,8 +1457,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t scratch_release(target, &scratch); return ERROR_FAIL; } - } else if (riscv_supports_extension(target, - riscv_current_hartid(target), 'D')) { + } else if (riscv_supports_extension(target, 'D')) { riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0)); } else { riscv_program_insert(&program, fmv_x_w(S0, number - GDB_REGNO_FPR0)); @@ -1549,7 +1546,7 @@ static int set_haltgroup(struct target *target, bool *supported) return ERROR_OK; } -static int discover_vlenb(struct target *target, int hartid) +static int discover_vlenb(struct target *target) { RISCV_INFO(r); riscv_reg_t vlenb; @@ -1557,12 +1554,12 @@ static int discover_vlenb(struct target *target, int hartid) if (register_read(target, &vlenb, GDB_REGNO_VLENB) != ERROR_OK) { LOG_WARNING("Couldn't read vlenb for %s; vector register access won't work.", target_name(target)); - r->vlenb[hartid] = 0; + r->vlenb = 0; return ERROR_OK; } - r->vlenb[hartid] = vlenb; + r->vlenb = vlenb; - LOG_INFO("hart %d: Vector support with vlenb=%d", hartid, r->vlenb[hartid]); + LOG_INFO("Vector support with vlenb=%d", r->vlenb); return ERROR_OK; } @@ -1710,6 +1707,8 @@ 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; @@ -1717,55 +1716,50 @@ static int examine(struct target *target) /* Don't call any riscv_* functions until after we've counted the number of * cores and initialized registers. */ - for (int i = 0; i < dm->hart_count; ++i) { - if (!riscv_rtos_enabled(target) && i != target->coreid) - continue; - r->current_hartid = i; - if (riscv013_select_current_hart(target) != ERROR_OK) - return ERROR_FAIL; + if (riscv013_select_current_hart(target) != ERROR_OK) + return ERROR_FAIL; - bool halted = riscv_is_halted(target); - if (!halted) { - if (riscv013_halt_go(target) != ERROR_OK) { - LOG_ERROR("Fatal: Hart %d failed to halt during examine()", i); - return ERROR_FAIL; - } - } - - /* Without knowing anything else we can at least mess with the - * program buffer. */ - r->debug_buffer_size[i] = info->progbufsize; - - int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64); - if (result == ERROR_OK) - r->xlen[i] = 64; - else - r->xlen[i] = 32; - - if (register_read(target, &r->misa[i], GDB_REGNO_MISA)) { - LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i); + bool halted = riscv_is_halted(target); + if (!halted) { + if (riscv013_halt_go(target) != ERROR_OK) { + LOG_ERROR("Fatal: Hart %d failed to halt during examine()", r->current_hartid); return ERROR_FAIL; } - - if (riscv_supports_extension(target, i, 'V')) { - if (discover_vlenb(target, i) != ERROR_OK) - return ERROR_FAIL; - } - - /* Now init registers based on what we discovered. */ - if (riscv_init_registers(target) != ERROR_OK) - return ERROR_FAIL; - - /* Display this as early as possible to help people who are using - * really slow simulators. */ - LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i], - r->misa[i]); - - if (!halted) - riscv013_step_or_resume_current_hart(target, false, false); } + /* Without knowing anything else we can at least mess with the + * program buffer. */ + r->debug_buffer_size = info->progbufsize; + + int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64); + if (result == ERROR_OK) + r->xlen = 64; + else + r->xlen = 32; + + if (register_read(target, &r->misa, GDB_REGNO_MISA)) { + LOG_ERROR("Fatal: Failed to read MISA from hart %d.", r->current_hartid); + return ERROR_FAIL; + } + + if (riscv_supports_extension(target, 'V')) { + if (discover_vlenb(target) != ERROR_OK) + return ERROR_FAIL; + } + + /* Now init registers based on what we discovered. */ + if (riscv_init_registers(target) != ERROR_OK) + return ERROR_FAIL; + + /* Display this as early as possible to help people who are using + * really slow simulators. */ + LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, r->current_hartid, r->xlen, + r->misa); + + if (!halted) + riscv013_step_or_resume_current_hart(target, false, false); + target_set_examined(target); if (target->smp) { @@ -1785,14 +1779,8 @@ static int examine(struct target *target) * We will need to update those suites if we want to change that text. */ LOG_INFO("Examined RISC-V core; found %d harts", riscv_count_harts(target)); - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (riscv_hart_enabled(target, i)) { - LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i], - r->misa[i]); - } else { - LOG_INFO(" hart %d: currently disabled", i); - } - } + LOG_INFO(" hart %d: XLEN=%d, misa=0x%" PRIx64, r->current_hartid, r->xlen, + r->misa); return ERROR_OK; } @@ -1919,8 +1907,7 @@ static int prep_for_vector_access(struct target *target, uint64_t *vtype, if (register_write_direct(target, GDB_REGNO_VTYPE, encoded_vsew << 3) != ERROR_OK) return ERROR_FAIL; - *debug_vl = DIV_ROUND_UP(r->vlenb[r->current_hartid] * 8, - riscv_xlen(target)); + *debug_vl = DIV_ROUND_UP(r->vlenb * 8, riscv_xlen(target)); if (register_write_direct(target, GDB_REGNO_VL, *debug_vl) != ERROR_OK) return ERROR_FAIL; @@ -2286,7 +2273,6 @@ static int init_target(struct command_context *cmd_ctx, generic_info->dmi_write = &dmi_write; generic_info->read_memory = read_memory; generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg; - generic_info->test_compliance = &riscv013_test_compliance; generic_info->hart_count = &riscv013_hart_count; generic_info->data_bits = &riscv013_data_bits; generic_info->print_info = &riscv013_print_info; @@ -2337,15 +2323,12 @@ static int assert_reset(struct target *target) /* Set haltreq for each hart. */ uint32_t control = control_base; - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - control = set_hartsel(control_base, i); - control = set_field(control, DM_DMCONTROL_HALTREQ, - target->reset_halt ? 1 : 0); - dmi_write(target, DM_DMCONTROL, control); - } + control = set_hartsel(control_base, target->coreid); + control = set_field(control, DM_DMCONTROL_HALTREQ, + target->reset_halt ? 1 : 0); + dmi_write(target, DM_DMCONTROL, control); + /* Assert ndmreset */ control = set_field(control, DM_DMCONTROL_NDMRESET, 1); dmi_write(target, DM_DMCONTROL, control); @@ -2393,7 +2376,7 @@ static int deassert_reset(struct target *target) for (int i = 0; i < riscv_count_harts(target); ++i) { int index = i; if (target->rtos) { - if (!riscv_hart_enabled(target, index)) + if (index != target->coreid) continue; dmi_write(target, DM_DMCONTROL, set_hartsel(control, index)); @@ -2447,8 +2430,6 @@ static int deassert_reset(struct target *target) static int execute_fence(struct target *target) { - int old_hartid = riscv_current_hartid(target); - /* FIXME: For non-coherent systems we need to flush the caches right * here, but there's no ISA-defined way of doing that. */ { @@ -2461,27 +2442,6 @@ static int execute_fence(struct target *target) LOG_DEBUG("Unable to execute pre-fence"); } - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - - if (i == old_hartid) - /* Fence already executed for this hart */ - continue; - - riscv_set_current_hartid(target, i); - - struct riscv_program program; - riscv_program_init(&program, target); - riscv_program_fence_i(&program); - riscv_program_fence(&program); - int result = riscv_program_exec(&program, target); - if (result != ERROR_OK) - LOG_DEBUG("Unable to execute fence on hart %d", i); - } - - riscv_set_current_hartid(target, old_hartid); - return ERROR_OK; } @@ -4053,12 +4013,12 @@ struct target_type riscv013_target = { /*** 0.13-specific implementations of various RISC-V helper functions. ***/ static int riscv013_get_register(struct target *target, - riscv_reg_t *value, int hid, int rid) + riscv_reg_t *value, int rid) { - LOG_DEBUG("[%d] reading register %s on hart %d", target->coreid, - gdb_regno_name(rid), hid); + LOG_DEBUG("[%s] reading register %s", target_name(target), + gdb_regno_name(rid)); - riscv_set_current_hartid(target, hid); + riscv_select_current_hart(target); int result = ERROR_OK; if (rid == GDB_REGNO_PC) { @@ -4079,12 +4039,11 @@ static int riscv013_get_register(struct target *target, return result; } -static int riscv013_set_register(struct target *target, int hid, int rid, uint64_t value) +static int riscv013_set_register(struct target *target, int rid, uint64_t value) { - LOG_DEBUG("[%d] writing 0x%" PRIx64 " to register %s on hart %d", - target->coreid, value, gdb_regno_name(rid), hid); - - riscv_set_current_hartid(target, hid); + riscv013_select_current_hart(target); + LOG_DEBUG("[%d] writing 0x%" PRIx64 " to register %s", + target->coreid, value, gdb_regno_name(rid)); if (rid <= GDB_REGNO_XPR31) { return register_write_direct(target, rid, value); @@ -4193,10 +4152,8 @@ static int riscv013_halt_prep(struct target *target) static int riscv013_halt_go(struct target *target) { bool use_hasel = false; - if (!riscv_rtos_enabled(target)) { - if (select_prepped_harts(target, &use_hasel) != ERROR_OK) - return ERROR_FAIL; - } + if (select_prepped_harts(target, &use_hasel) != ERROR_OK) + return ERROR_FAIL; RISCV_INFO(r); LOG_DEBUG("halting hart %d", r->current_hartid); @@ -4247,10 +4204,8 @@ static int riscv013_halt_go(struct target *target) static int riscv013_resume_go(struct target *target) { bool use_hasel = false; - if (!riscv_rtos_enabled(target)) { - if (select_prepped_harts(target, &use_hasel) != ERROR_OK) - return ERROR_FAIL; - } + if (select_prepped_harts(target, &use_hasel) != ERROR_OK) + return ERROR_FAIL; return riscv013_step_or_resume_current_hart(target, false, use_hasel); } @@ -4845,477 +4800,3 @@ void riscv013_clear_abstract_error(struct target *target) /* Clear the error status. */ dmi_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); } - -#ifdef _WIN32 -#define FILE_SEP '\\' -#else -#define FILE_SEP '/' -#endif -#define COMPLIANCE_TEST(b, message) \ -{ \ - const char *last_sep = strrchr(__FILE__, FILE_SEP); \ - const char *fname = (last_sep == NULL ? __FILE__ : last_sep + 1); \ - LOG_INFO("Executing test %d (%s:%d): %s", total_tests, fname, __LINE__, message); \ - int pass = 0; \ - if (b) { \ - pass = 1; \ - passed_tests++; \ - } \ - LOG_INFO(" %s", (pass) ? "PASSED" : "FAILED"); \ - assert(pass); \ - total_tests++; \ -} - -#define COMPLIANCE_MUST_PASS(b) COMPLIANCE_TEST(ERROR_OK == (b), "Regular calls must return ERROR_OK") - -#define COMPLIANCE_READ(target, addr, value) COMPLIANCE_MUST_PASS(dmi_read(target, addr, value)) -#define COMPLIANCE_WRITE(target, addr, value) COMPLIANCE_MUST_PASS(dmi_write(target, addr, value)) - -#define COMPLIANCE_CHECK_RO(target, addr) \ -{ \ - uint32_t orig; \ - uint32_t inverse; \ - COMPLIANCE_READ(target, &orig, addr); \ - COMPLIANCE_WRITE(target, addr, ~orig); \ - COMPLIANCE_READ(target, &inverse, addr); \ - COMPLIANCE_TEST(orig == inverse, "Register must be read-only"); \ -} - -int riscv013_test_compliance(struct target *target) -{ - LOG_INFO("Basic compliance test against RISC-V Debug Spec v0.13"); - LOG_INFO("This test is not complete, and not well supported."); - LOG_INFO("Your core might pass this test without being compliant."); - LOG_INFO("Your core might fail this test while being compliant."); - LOG_INFO("Use your judgment, and please contribute improvements."); - - if (!riscv_rtos_enabled(target)) { - LOG_ERROR("Please run with -rtos riscv to run compliance test."); - return ERROR_FAIL; - } - - if (!target_was_examined(target)) { - LOG_ERROR("Cannot run compliance test, because target has not yet " - "been examined, or the examination failed.\n"); - return ERROR_FAIL; - } - - int total_tests = 0; - int passed_tests = 0; - - uint32_t dmcontrol_orig = DM_DMCONTROL_DMACTIVE; - uint32_t dmcontrol; - uint32_t testvar; - uint32_t testvar_read; - riscv_reg_t value; - RISCV013_INFO(info); - - /* All the bits of HARTSEL are covered by the examine sequence. */ - - /* hartreset */ - /* This field is optional. Either we can read and write it to 1/0, - or it is tied to 0. This check doesn't really do anything, but - it does attempt to set the bit to 1 and then back to 0, which needs to - work if its implemented. */ - COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HARTRESET, 1)); - COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HARTRESET, 0)); - COMPLIANCE_READ(target, &dmcontrol, DM_DMCONTROL); - COMPLIANCE_TEST((get_field(dmcontrol, DM_DMCONTROL_HARTRESET) == 0), - "DMCONTROL.hartreset can be 0 or RW."); - - /* hasel */ - COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HASEL, 1)); - COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HASEL, 0)); - COMPLIANCE_READ(target, &dmcontrol, DM_DMCONTROL); - COMPLIANCE_TEST((get_field(dmcontrol, DM_DMCONTROL_HASEL) == 0), - "DMCONTROL.hasel can be 0 or RW."); - /* TODO: test that hamask registers exist if hasel does. */ - - /* haltreq */ - COMPLIANCE_MUST_PASS(riscv_halt(target)); - /* This bit is not actually readable according to the spec, so nothing to check.*/ - - /* DMSTATUS */ - COMPLIANCE_CHECK_RO(target, DM_DMSTATUS); - - /* resumereq */ - /* This bit is not actually readable according to the spec, so nothing to check.*/ - COMPLIANCE_MUST_PASS(riscv_resume(target, true, 0, false, false, false)); - - /* Halt all harts again so the test can continue.*/ - COMPLIANCE_MUST_PASS(riscv_halt(target)); - - /* HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel. */ - uint32_t hartinfo; - COMPLIANCE_READ(target, &hartinfo, DM_HARTINFO); - for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { - COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); - - COMPLIANCE_CHECK_RO(target, DM_HARTINFO); - - /* $dscratch CSRs */ - uint32_t nscratch = get_field(hartinfo, DM_HARTINFO_NSCRATCH); - for (unsigned int d = 0; d < nscratch; d++) { - riscv_reg_t testval, testval_read; - /* Because DSCRATCH0 is not guaranteed to last across PB executions, need to put - this all into one PB execution. Which may not be possible on all implementations.*/ - if (info->progbufsize >= 5) { - for (testval = 0x0011223300112233; - testval != 0xDEAD; - testval = testval == 0x0011223300112233 ? ~testval : 0xDEAD) { - COMPLIANCE_TEST(register_write_direct(target, GDB_REGNO_S0, testval) == ERROR_OK, - "Need to be able to write S0 in order to test DSCRATCH0."); - struct riscv_program program32; - riscv_program_init(&program32, target); - riscv_program_csrw(&program32, GDB_REGNO_S0, GDB_REGNO_DSCRATCH0 + d); - riscv_program_csrr(&program32, GDB_REGNO_S1, GDB_REGNO_DSCRATCH0 + d); - riscv_program_fence(&program32); - riscv_program_ebreak(&program32); - COMPLIANCE_TEST(riscv_program_exec(&program32, target) == ERROR_OK, - "Accessing DSCRATCH0 with program buffer should succeed."); - COMPLIANCE_TEST(register_read_direct(target, &testval_read, GDB_REGNO_S1) == ERROR_OK, - "Need to be able to read S1 in order to test DSCRATCH0."); - if (riscv_xlen(target) > 32) { - COMPLIANCE_TEST(testval == testval_read, - "All DSCRATCH0 registers in HARTINFO must be R/W."); - } else { - COMPLIANCE_TEST(testval_read == (testval & 0xFFFFFFFF), - "All DSCRATCH0 registers in HARTINFO must be R/W."); - } - } - } - } - /* TODO: dataaccess */ - if (get_field(hartinfo, DM_HARTINFO_DATAACCESS)) { - /* TODO: Shadowed in memory map. */ - /* TODO: datasize */ - /* TODO: dataaddr */ - } else { - /* TODO: Shadowed in CSRs. */ - /* TODO: datasize */ - /* TODO: dataaddr */ - } - - } - - /* HALTSUM -- TODO: More than 32 harts. Would need to loop over this to set hartsel */ - /* TODO: HALTSUM2, HALTSUM3 */ - /* HALTSUM0 */ - uint32_t expected_haltsum0 = 0; - for (int i = 0; i < MIN(riscv_count_harts(target), 32); i++) - expected_haltsum0 |= (1 << i); - - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0); - COMPLIANCE_TEST(testvar_read == expected_haltsum0, - "HALTSUM0 should report summary of up to 32 halted harts"); - - COMPLIANCE_WRITE(target, DM_HALTSUM0, 0xffffffff); - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0); - COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O"); - - COMPLIANCE_WRITE(target, DM_HALTSUM0, 0x0); - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0); - COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O"); - - /* HALTSUM1 */ - uint32_t expected_haltsum1 = 0; - for (int i = 0; i < MIN(riscv_count_harts(target), 1024); i += 32) - expected_haltsum1 |= (1 << (i/32)); - - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1); - COMPLIANCE_TEST(testvar_read == expected_haltsum1, - "HALTSUM1 should report summary of up to 1024 halted harts"); - - COMPLIANCE_WRITE(target, DM_HALTSUM1, 0xffffffff); - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1); - COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O"); - - COMPLIANCE_WRITE(target, DM_HALTSUM1, 0x0); - COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1); - COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O"); - - /* TODO: HAWINDOWSEL */ - - /* TODO: HAWINDOW */ - - /* ABSTRACTCS */ - - uint32_t abstractcs; - COMPLIANCE_READ(target, &abstractcs, DM_ABSTRACTCS); - - /* Check that all reported Data Words are really R/W */ - for (int invert = 0; invert < 2; invert++) { - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) { - testvar = (i + 1) * 0x11111111; - if (invert) - testvar = ~testvar; - COMPLIANCE_WRITE(target, DM_DATA0 + i, testvar); - } - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) { - testvar = (i + 1) * 0x11111111; - if (invert) - testvar = ~testvar; - COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i); - COMPLIANCE_TEST(testvar_read == testvar, "All reported DATA words must be R/W"); - } - } - - /* Check that all reported ProgBuf words are really R/W */ - for (int invert = 0; invert < 2; invert++) { - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) { - testvar = (i + 1) * 0x11111111; - if (invert) - testvar = ~testvar; - COMPLIANCE_WRITE(target, DM_PROGBUF0 + i, testvar); - } - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) { - testvar = (i + 1) * 0x11111111; - if (invert) - testvar = ~testvar; - COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i); - COMPLIANCE_TEST(testvar_read == testvar, "All reported PROGBUF words must be R/W"); - } - } - - /* TODO: Cause and clear all error types */ - - /* COMMAND - According to the spec, this register is only W, so can't really check the read result. - But at any rate, this is not legal and should cause an error. */ - COMPLIANCE_WRITE(target, DM_COMMAND, 0xAAAAAAAA); - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, - "Illegal COMMAND should result in UNSUPPORTED"); - COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); - - COMPLIANCE_WRITE(target, DM_COMMAND, 0x55555555); - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, - "Illegal COMMAND should result in UNSUPPORTED"); - COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); - - /* Basic Abstract Commands */ - for (unsigned int i = 1; i < 32; i = i << 1) { - riscv_reg_t testval = i | ((i + 1ULL) << 32); - riscv_reg_t testval_read; - COMPLIANCE_TEST(ERROR_OK == register_write_direct(target, GDB_REGNO_ZERO + i, testval), - "GPR Writes should be supported."); - COMPLIANCE_MUST_PASS(write_abstract_arg(target, 0, 0xDEADBEEFDEADBEEF, 64)); - COMPLIANCE_TEST(ERROR_OK == register_read_direct(target, &testval_read, GDB_REGNO_ZERO + i), - "GPR Reads should be supported."); - if (riscv_xlen(target) > 32) { - /* Dummy comment to satisfy linter, since removing the branches here doesn't actually compile. */ - COMPLIANCE_TEST(testval == testval_read, "GPR Reads and writes should be supported."); - } else { - /* Dummy comment to satisfy linter, since removing the branches here doesn't actually compile. */ - COMPLIANCE_TEST((testval & 0xFFFFFFFF) == testval_read, "GPR Reads and writes should be supported."); - } - } - - /* ABSTRACTAUTO - See which bits are actually writable */ - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF); - uint32_t abstractauto; - uint32_t busy; - COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO); - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0x0); - if (abstractauto > 0) { - /* This mechanism only works when you have a reasonable sized progbuf, which is not - a true compliance requirement. */ - if (info->progbufsize >= 3) { - - testvar = 0; - COMPLIANCE_TEST(ERROR_OK == register_write_direct(target, GDB_REGNO_S0, 0), - "Need to be able to write S0 to test ABSTRACTAUTO"); - struct riscv_program program; - COMPLIANCE_MUST_PASS(riscv_program_init(&program, target)); - /* This is also testing that WFI() is a NOP during debug mode. */ - COMPLIANCE_MUST_PASS(riscv_program_insert(&program, wfi())); - COMPLIANCE_MUST_PASS(riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, 1)); - COMPLIANCE_MUST_PASS(riscv_program_ebreak(&program)); - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0x0); - COMPLIANCE_MUST_PASS(riscv_program_exec(&program, target)); - testvar++; - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF); - COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO); - uint32_t autoexec_data = get_field(abstractauto, DM_ABSTRACTAUTO_AUTOEXECDATA); - uint32_t autoexec_progbuf = get_field(abstractauto, DM_ABSTRACTAUTO_AUTOEXECPROGBUF); - for (unsigned int i = 0; i < 12; i++) { - COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i); - do { - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - busy = get_field(testvar_read, DM_ABSTRACTCS_BUSY); - } while (busy); - if (autoexec_data & (1 << i)) { - COMPLIANCE_TEST(i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT), - "AUTOEXEC may be writable up to DATACOUNT bits."); - testvar++; - } - } - for (unsigned int i = 0; i < 16; i++) { - COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i); - do { - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - busy = get_field(testvar_read, DM_ABSTRACTCS_BUSY); - } while (busy); - if (autoexec_progbuf & (1 << i)) { - COMPLIANCE_TEST(i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE), - "AUTOEXEC may be writable up to PROGBUFSIZE bits."); - testvar++; - } - } - - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0); - COMPLIANCE_TEST(ERROR_OK == register_read_direct(target, &value, GDB_REGNO_S0), - "Need to be able to read S0 to test ABSTRACTAUTO"); - - COMPLIANCE_TEST(testvar == value, - "ABSTRACTAUTO should cause COMMAND to run the expected number of times."); - } - } - - /* Single-Step each hart. */ - for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { - COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); - COMPLIANCE_MUST_PASS(riscv013_on_step(target)); - COMPLIANCE_MUST_PASS(riscv013_step_current_hart(target)); - COMPLIANCE_TEST(riscv_halt_reason(target, hartsel) == RISCV_HALT_SINGLESTEP, - "Single Step should result in SINGLESTEP"); - } - - /* Core Register Tests */ - uint64_t bogus_dpc = 0xdeadbeef; - for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { - COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); - - /* DCSR Tests */ - COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0x0)); - COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR)); - COMPLIANCE_TEST(value != 0, "Not all bits in DCSR are writable by Debugger"); - COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0xFFFFFFFF)); - COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR)); - COMPLIANCE_TEST(value != 0, "At least some bits in DCSR must be 1"); - - /* DPC. Note that DPC is sign-extended. */ - riscv_reg_t dpcmask = 0xFFFFFFFCUL; - riscv_reg_t dpc; - - if (riscv_xlen(target) > 32) - dpcmask |= (0xFFFFFFFFULL << 32); - - if (riscv_supports_extension(target, riscv_current_hartid(target), 'C')) - dpcmask |= 0x2; - - COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, dpcmask)); - COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC)); - COMPLIANCE_TEST(dpcmask == dpc, - "DPC must be sign-extended to XLEN and writable to all-1s (except the least significant bits)"); - COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, 0)); - COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC)); - COMPLIANCE_TEST(dpc == 0, "DPC must be writable to 0."); - if (hartsel == 0) - bogus_dpc = dpc; /* For a later test step */ - } - - /* NDMRESET - Asserting non-debug module reset should not reset Debug Module state. - But it should reset Hart State, e.g. DPC should get a different value. - Also make sure that DCSR reports cause of 'HALT' even though previously we single-stepped. - */ - - /* Write some registers. They should not be impacted by ndmreset. */ - COMPLIANCE_WRITE(target, DM_COMMAND, 0xFFFFFFFF); - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) { - testvar = (i + 1) * 0x11111111; - COMPLIANCE_WRITE(target, DM_PROGBUF0 + i, testvar); - } - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) { - testvar = (i + 1) * 0x11111111; - COMPLIANCE_WRITE(target, DM_DATA0 + i, testvar); - } - - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF); - COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO); - - /* Pulse reset. */ - target->reset_halt = true; - COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, 0)); - COMPLIANCE_TEST(ERROR_OK == assert_reset(target), "Must be able to assert NDMRESET"); - COMPLIANCE_TEST(ERROR_OK == deassert_reset(target), "Must be able to deassert NDMRESET"); - - /* Verify that most stuff is not affected by ndmreset. */ - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, - "NDMRESET should not affect DM_ABSTRACTCS"); - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTAUTO); - COMPLIANCE_TEST(testvar_read == abstractauto, "NDMRESET should not affect DM_ABSTRACTAUTO"); - - /* Clean up to avoid future test failures */ - COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR); - COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0); - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) { - testvar = (i + 1) * 0x11111111; - COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i); - COMPLIANCE_TEST(testvar_read == testvar, "PROGBUF words must not be affected by NDMRESET"); - } - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) { - testvar = (i + 1) * 0x11111111; - COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i); - COMPLIANCE_TEST(testvar_read == testvar, "DATA words must not be affected by NDMRESET"); - } - - /* Verify that DPC *is* affected by ndmreset. Since we don't know what it *should* be, - just verify that at least it's not the bogus value anymore. */ - - COMPLIANCE_TEST(bogus_dpc != 0xdeadbeef, "BOGUS DPC should have been set somehow (bug in compliance test)"); - COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DPC)); - COMPLIANCE_TEST(bogus_dpc != value, "NDMRESET should move DPC to reset value."); - - COMPLIANCE_TEST(riscv_halt_reason(target, 0) == RISCV_HALT_INTERRUPT, - "After NDMRESET halt, DCSR should report cause of halt"); - - /* DMACTIVE -- deasserting DMACTIVE should reset all the above values. */ - - /* Toggle dmactive */ - COMPLIANCE_WRITE(target, DM_DMCONTROL, 0); - COMPLIANCE_WRITE(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE); - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS); - COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == 0, "ABSTRACTCS.cmderr should reset to 0"); - COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTAUTO); - COMPLIANCE_TEST(testvar_read == 0, "ABSTRACTAUTO should reset to 0"); - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) { - COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i); - COMPLIANCE_TEST(testvar_read == 0, "PROGBUF words should reset to 0"); - } - - for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) { - COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i); - COMPLIANCE_TEST(testvar_read == 0, "DATA words should reset to 0"); - } - - /* - * TODO: - * DCSR.cause priorities - * DCSR.stoptime/stopcycle - * DCSR.stepie - * DCSR.ebreak - * DCSR.prv - */ - - /* Halt every hart for any follow-up tests*/ - COMPLIANCE_MUST_PASS(riscv_halt(target)); - - uint32_t failed_tests = total_tests - passed_tests; - if (total_tests == passed_tests) { - LOG_INFO("ALL TESTS PASSED\n"); - return ERROR_OK; - } else { - LOG_INFO("%d TESTS FAILED\n", failed_tests); - return ERROR_FAIL; - } -} diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 9a5656142..fb198cbd0 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -523,7 +523,7 @@ static void trigger_from_breakpoint(struct trigger *trigger, trigger->unique_id = breakpoint->unique_id; } -static int maybe_add_trigger_t1(struct target *target, unsigned hartid, +static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger, uint64_t tdata1) { RISCV_INFO(r); @@ -547,20 +547,19 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid, tdata1 = set_field(tdata1, bpcontrol_w, trigger->write); tdata1 = set_field(tdata1, bpcontrol_x, trigger->execute); tdata1 = set_field(tdata1, bpcontrol_u, - !!(r->misa[hartid] & (1 << ('U' - 'A')))); + !!(r->misa & (1 << ('U' - 'A')))); tdata1 = set_field(tdata1, bpcontrol_s, - !!(r->misa[hartid] & (1 << ('S' - 'A')))); + !!(r->misa & (1 << ('S' - 'A')))); tdata1 = set_field(tdata1, bpcontrol_h, - !!(r->misa[hartid] & (1 << ('H' - 'A')))); + !!(r->misa & (1 << ('H' - 'A')))); tdata1 |= bpcontrol_m; tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */ tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */ - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1); + riscv_set_register(target, GDB_REGNO_TDATA1, tdata1); riscv_reg_t tdata1_rb; - if (riscv_get_register_on_hart(target, &tdata1_rb, hartid, - GDB_REGNO_TDATA1) != ERROR_OK) + if (riscv_get_register(target, &tdata1_rb, GDB_REGNO_TDATA1) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb); @@ -568,16 +567,16 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid, LOG_DEBUG("Trigger doesn't support what we need; After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64, tdata1, tdata1_rb); - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); + riscv_set_register(target, GDB_REGNO_TDATA1, 0); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA2, trigger->address); + riscv_set_register(target, GDB_REGNO_TDATA2, trigger->address); return ERROR_OK; } -static int maybe_add_trigger_t2(struct target *target, unsigned hartid, +static int maybe_add_trigger_t2(struct target *target, struct trigger *trigger, uint64_t tdata1) { RISCV_INFO(r); @@ -594,11 +593,11 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid, MCONTROL_ACTION_DEBUG_MODE); tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL); tdata1 |= MCONTROL_M; - if (r->misa[hartid] & (1 << ('H' - 'A'))) + if (r->misa & (1 << ('H' - 'A'))) tdata1 |= MCONTROL_H; - if (r->misa[hartid] & (1 << ('S' - 'A'))) + if (r->misa & (1 << ('S' - 'A'))) tdata1 |= MCONTROL_S; - if (r->misa[hartid] & (1 << ('U' - 'A'))) + if (r->misa & (1 << ('U' - 'A'))) tdata1 |= MCONTROL_U; if (trigger->execute) @@ -608,10 +607,10 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid, if (trigger->write) tdata1 |= MCONTROL_STORE; - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1); + riscv_set_register(target, GDB_REGNO_TDATA1, tdata1); uint64_t tdata1_rb; - int result = riscv_get_register_on_hart(target, &tdata1_rb, hartid, GDB_REGNO_TDATA1); + int result = riscv_get_register(target, &tdata1_rb, GDB_REGNO_TDATA1); if (result != ERROR_OK) return result; LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb); @@ -620,11 +619,11 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid, LOG_DEBUG("Trigger doesn't support what we need; After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64, tdata1, tdata1_rb); - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); + riscv_set_register(target, GDB_REGNO_TDATA1, 0); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA2, trigger->address); + riscv_set_register(target, GDB_REGNO_TDATA2, trigger->address); return ERROR_OK; } @@ -636,61 +635,33 @@ static int add_trigger(struct target *target, struct trigger *trigger) if (riscv_enumerate_triggers(target) != ERROR_OK) return ERROR_FAIL; - /* In RTOS mode, we need to set the same trigger in the same slot on every - * hart, to keep up the illusion that each hart is a thread running on the - * same core. */ - - /* Otherwise, we just set the trigger on the one hart this target deals - * with. */ - - riscv_reg_t tselect[RISCV_MAX_HARTS]; - - int first_hart = -1; - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - if (first_hart < 0) - first_hart = hartid; - int result = riscv_get_register_on_hart(target, &tselect[hartid], - hartid, GDB_REGNO_TSELECT); - if (result != ERROR_OK) - return result; - } - assert(first_hart >= 0); + riscv_reg_t tselect; + if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) + return ERROR_FAIL; unsigned int i; - for (i = 0; i < r->trigger_count[first_hart]; i++) { + for (i = 0; i < r->trigger_count; i++) { if (r->trigger_unique_id[i] != -1) continue; - riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i); + riscv_set_register(target, GDB_REGNO_TSELECT, i); uint64_t tdata1; - int result = riscv_get_register_on_hart(target, &tdata1, first_hart, - GDB_REGNO_TDATA1); + int result = riscv_get_register(target, &tdata1, GDB_REGNO_TDATA1); if (result != ERROR_OK) return result; int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); result = ERROR_OK; - for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - if (hartid > first_hart) - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i); - switch (type) { - case 1: - result = maybe_add_trigger_t1(target, hartid, trigger, tdata1); - break; - case 2: - result = maybe_add_trigger_t2(target, hartid, trigger, tdata1); - break; - default: - LOG_DEBUG("trigger %d has unknown type %d", i, type); - continue; - } - - if (result != ERROR_OK) + switch (type) { + case 1: + result = maybe_add_trigger_t1(target, trigger, tdata1); + break; + case 2: + result = maybe_add_trigger_t2(target, trigger, tdata1); + break; + default: + LOG_DEBUG("trigger %d has unknown type %d", i, type); continue; } @@ -703,14 +674,9 @@ static int add_trigger(struct target *target, struct trigger *trigger) break; } - for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, - tselect[hartid]); - } + riscv_set_register(target, GDB_REGNO_TSELECT, tselect); - if (i >= r->trigger_count[first_hart]) { + if (i >= r->trigger_count) { LOG_ERROR("Couldn't find an available hardware trigger."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -891,40 +857,26 @@ static int remove_trigger(struct target *target, struct trigger *trigger) if (riscv_enumerate_triggers(target) != ERROR_OK) return ERROR_FAIL; - int first_hart = -1; - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - if (first_hart < 0) { - first_hart = hartid; - break; - } - } - assert(first_hart >= 0); - unsigned int i; - for (i = 0; i < r->trigger_count[first_hart]; i++) { + for (i = 0; i < r->trigger_count; i++) { if (r->trigger_unique_id[i] == trigger->unique_id) break; } - if (i >= r->trigger_count[first_hart]) { + if (i >= r->trigger_count) { LOG_ERROR("Couldn't find the hardware resources used by hardware " "trigger."); return ERROR_FAIL; } LOG_DEBUG("[%d] Stop using resource %d for bp %d", target->coreid, i, trigger->unique_id); - for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - riscv_reg_t tselect; - int result = riscv_get_register_on_hart(target, &tselect, hartid, GDB_REGNO_TSELECT); - if (result != ERROR_OK) - return result; - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i); - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect); - } + + riscv_reg_t tselect; + int result = riscv_get_register(target, &tselect, GDB_REGNO_TSELECT); + if (result != ERROR_OK) + return result; + riscv_set_register(target, GDB_REGNO_TSELECT, i); + riscv_set_register(target, GDB_REGNO_TDATA1, 0); + riscv_set_register(target, GDB_REGNO_TSELECT, tselect); r->trigger_unique_id[i] = -1; return ERROR_OK; @@ -1012,8 +964,6 @@ int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoi { struct watchpoint *wp = target->watchpoints; - if (riscv_rtos_enabled(target)) - riscv_set_current_hartid(target, target->rtos->current_thread - 1); LOG_DEBUG("Current hartid = %d", riscv_current_hartid(target)); /*TODO instead of disassembling the instruction that we think caused the @@ -1148,44 +1098,42 @@ 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 halt_prep(struct target *target) { RISCV_INFO(r); - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - LOG_DEBUG("[%s] prep hart, debug_reason=%d", target_name(target), - target->debug_reason); - if (riscv_set_current_hartid(target, i) != ERROR_OK) + 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 (reason=%d).", + target_name(target), target->debug_reason); + } else { + if (r->halt_prep(target) != ERROR_OK) return ERROR_FAIL; - if (riscv_is_halted(target)) { - LOG_DEBUG("Hart %d is already halted (reason=%d).", i, - target->debug_reason); - } else { - if (r->halt_prep(target) != ERROR_OK) - return ERROR_FAIL; - r->prepped = true; - } + r->prepped = true; } + return ERROR_OK; } int riscv_halt_go_all_harts(struct target *target) { RISCV_INFO(r); - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - if (riscv_set_current_hartid(target, i) != ERROR_OK) + 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 { + if (r->halt_go(target) != ERROR_OK) return ERROR_FAIL; - if (riscv_is_halted(target)) { - LOG_DEBUG("Hart %d is already halted.", i); - } else { - if (r->halt_go(target) != ERROR_OK) - return ERROR_FAIL; - } } riscv_invalidate_register_cache(target); @@ -1258,15 +1206,6 @@ int riscv_halt(struct target *target) return ERROR_FAIL; } - if (riscv_rtos_enabled(target)) { - if (r->rtos_hartid != -1) { - LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid); - target->rtos->current_threadid = r->rtos_hartid + 1; - target->rtos->current_thread = r->rtos_hartid + 1; - } else - LOG_DEBUG("halt requested, but no known RTOS hartid"); - } - return result; } @@ -1288,22 +1227,19 @@ static int riscv_deassert_reset(struct target *target) int riscv_resume_prep_all_harts(struct target *target) { RISCV_INFO(r); - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - LOG_DEBUG("prep hart %d", i); - if (riscv_set_current_hartid(target, i) != ERROR_OK) + LOG_DEBUG("[%s] prep hart", target_name(target)); + if (riscv_select_current_hart(target) != ERROR_OK) + return ERROR_FAIL; + if (riscv_is_halted(target)) { + if (r->resume_prep(target) != ERROR_OK) return ERROR_FAIL; - if (riscv_is_halted(target)) { - if (r->resume_prep(target) != ERROR_OK) - return ERROR_FAIL; - } else { - LOG_DEBUG(" hart %d requested resume, but was already resumed", i); - } + } else { + LOG_DEBUG("[%s] hart requested resume, but was already resumed", + target_name(target)); } - LOG_DEBUG("[%d] mark as prepped", target->coreid); + LOG_DEBUG("[%s] mark as prepped", target_name(target)); r->prepped = true; return ERROR_OK; @@ -1319,13 +1255,12 @@ static int disable_triggers(struct target *target, riscv_reg_t *state) if (riscv_enumerate_triggers(target) != ERROR_OK) return ERROR_FAIL; - int hartid = riscv_current_hartid(target); if (r->manual_hwbp_set) { /* Look at every trigger that may have been set. */ riscv_reg_t tselect; if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) return ERROR_FAIL; - for (unsigned t = 0; t < r->trigger_count[hartid]; t++) { + for (unsigned t = 0; t < r->trigger_count; t++) { if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK) return ERROR_FAIL; riscv_reg_t tdata1; @@ -1363,14 +1298,12 @@ static int enable_triggers(struct target *target, riscv_reg_t *state) { RISCV_INFO(r); - int hartid = riscv_current_hartid(target); - if (r->manual_hwbp_set) { /* Look at every trigger that may have been set. */ riscv_reg_t tselect; if (riscv_get_register(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) return ERROR_FAIL; - for (unsigned t = 0; t < r->trigger_count[hartid]; t++) { + for (unsigned t = 0; t < r->trigger_count; t++) { if (state[t] != 0) { if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK) return ERROR_FAIL; @@ -1524,17 +1457,6 @@ static int riscv_target_resume(struct target *target, int current, target_addr_t debug_execution, false); } -static int riscv_select_current_hart(struct target *target) -{ - RISCV_INFO(r); - if (riscv_rtos_enabled(target)) { - if (r->rtos_hartid == -1) - r->rtos_hartid = target->rtos->current_threadid - 1; - return riscv_set_current_hartid(target, r->rtos_hartid); - } else - return riscv_set_current_hartid(target, target->coreid); -} - static int riscv_mmu(struct target *target, int *enabled) { if (!riscv_enable_virt2phys) { @@ -1542,9 +1464,6 @@ static int riscv_mmu(struct target *target, int *enabled) return ERROR_OK; } - if (riscv_rtos_enabled(target)) - riscv_set_current_hartid(target, target->rtos->current_thread - 1); - /* Don't use MMU in explicit or effective M (machine) mode */ riscv_reg_t priv; if (riscv_get_register(target, &priv, GDB_REGNO_PRIV) != ERROR_OK) { @@ -1595,9 +1514,6 @@ static int riscv_address_translate(struct target *target, uint64_t pte; int i; - if (riscv_rtos_enabled(target)) - riscv_set_current_hartid(target, target->rtos->current_thread - 1); - int result = riscv_get_register(target, &satp_value, GDB_REGNO_SATP); if (result != ERROR_OK) return result; @@ -1767,8 +1683,8 @@ static int riscv_get_gdb_reg_list_internal(struct target *target, enum target_register_class reg_class, bool read) { RISCV_INFO(r); - LOG_DEBUG("rtos_hartid=%d, current_hartid=%d, reg_class=%d, read=%d", - r->rtos_hartid, r->current_hartid, reg_class, read); + LOG_DEBUG("current_hartid=%d, reg_class=%d, read=%d", + r->current_hartid, reg_class, read); if (!target->reg_cache) { LOG_ERROR("Target not initialized. Return ERROR_FAIL."); @@ -1839,7 +1755,6 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, target_addr_t exit_point, int timeout_ms, void *arch_info) { RISCV_INFO(info); - int hartid = riscv_current_hartid(target); if (num_mem_params > 0) { LOG_ERROR("Memory parameters are not supported for RISC-V algorithms."); @@ -1904,7 +1819,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, reg_mstatus->type->get(reg_mstatus); current_mstatus = buf_get_u64(reg_mstatus->value, 0, reg_mstatus->size); uint64_t ie_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; - buf_set_u64(mstatus_bytes, 0, info->xlen[0], set_field(current_mstatus, + buf_set_u64(mstatus_bytes, 0, info->xlen, set_field(current_mstatus, ie_mask, 0)); reg_mstatus->type->set(reg_mstatus, mstatus_bytes); @@ -1950,7 +1865,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, } /* The current hart id might have been changed in poll(). */ - if (riscv_set_current_hartid(target, hartid) != ERROR_OK) + if (riscv_select_current_hart(target) != ERROR_OK) return ERROR_FAIL; if (reg_pc->type->get(reg_pc) != ERROR_OK) @@ -1964,12 +1879,12 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, /* Restore Interrupts */ LOG_DEBUG("Restoring Interrupts"); - buf_set_u64(mstatus_bytes, 0, info->xlen[0], current_mstatus); + buf_set_u64(mstatus_bytes, 0, info->xlen, current_mstatus); reg_mstatus->type->set(reg_mstatus, mstatus_bytes); /* Restore registers */ uint8_t buf[8] = { 0 }; - buf_set_u64(buf, 0, info->xlen[0], saved_pc); + buf_set_u64(buf, 0, info->xlen, saved_pc); if (reg_pc->type->set(reg_pc, buf) != ERROR_OK) return ERROR_FAIL; @@ -1985,7 +1900,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, } 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); - buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]); + buf_set_u64(buf, 0, info->xlen, saved_regs[r->number]); if (r->type->set(r, buf) != ERROR_OK) { LOG_ERROR("set(%s) failed", r->name); return ERROR_FAIL; @@ -2193,45 +2108,7 @@ int riscv_openocd_poll(struct target *target) LOG_DEBUG("polling all harts"); int halted_hart = -1; - if (riscv_rtos_enabled(target)) { - /* Check every hart for an event. */ - for (int i = 0; i < riscv_count_harts(target); ++i) { - enum riscv_poll_hart out = riscv_poll_hart(target, i); - switch (out) { - case RPH_NO_CHANGE: - case RPH_DISCOVERED_RUNNING: - continue; - case RPH_DISCOVERED_HALTED: - halted_hart = i; - break; - case RPH_ERROR: - return ERROR_FAIL; - } - } - if (halted_hart == -1) { - LOG_DEBUG(" no harts just halted, target->state=%d", target->state); - return ERROR_OK; - } - LOG_DEBUG(" hart %d halted", halted_hart); - - target->state = TARGET_HALTED; - enum riscv_halt_reason halt_reason = riscv_halt_reason(target, halted_hart); - if (set_debug_reason(target, halt_reason) != ERROR_OK) - return ERROR_FAIL; - - target->rtos->current_threadid = halted_hart + 1; - target->rtos->current_thread = halted_hart + 1; - riscv_set_rtos_hartid(target, halted_hart); - - /* If we're here then at least one hart triggered. That means we want - * to go and halt _every_ hart (configured with -rtos riscv) in the - * system, as that's the invariant we hold here. Some harts might have - * already halted (as we're either in single-step mode or they also - * triggered a breakpoint), so don't attempt to halt those harts. - * riscv_halt() will do all that for us. */ - riscv_halt(target); - - } else if (target->smp) { + if (target->smp) { unsigned halts_discovered = 0; bool newly_halted[RISCV_MAX_HARTS] = {0}; unsigned should_remain_halted = 0; @@ -2417,25 +2294,6 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec) return ERROR_OK; } -COMMAND_HANDLER(riscv_test_compliance) { - - struct target *target = get_current_target(CMD_CTX); - - RISCV_INFO(r); - - if (CMD_ARGC > 0) { - LOG_ERROR("Command does not take any parameters."); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - if (r->test_compliance) { - return r->test_compliance(target); - } else { - LOG_ERROR("This target does not support this command (may implement an older version of the spec)."); - return ERROR_FAIL; - } -} - COMMAND_HANDLER(riscv_set_prefer_sba) { struct target *target = get_current_target(CMD_CTX); @@ -3016,11 +2874,6 @@ COMMAND_HANDLER(handle_memory_sample_command) return ERROR_COMMAND_SYNTAX_ERROR; } - if (riscv_rtos_enabled(target)) { - LOG_ERROR("Memory sampling is not supported with `-rtos riscv`."); - return ERROR_FAIL; - } - uint32_t bucket; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bucket); if (bucket > DIM(r->sample_config.bucket)) { @@ -3153,7 +3006,7 @@ COMMAND_HANDLER(handle_info) riscv_print_info_line(CMD, "hart", "xlen", riscv_xlen(target)); riscv_enumerate_triggers(target); riscv_print_info_line(CMD, "hart", "trigger_count", - r->trigger_count[target->coreid]); + r->trigger_count); if (r->print_info) return CALL_COMMAND_HANDLER(r->print_info, target); @@ -3190,13 +3043,6 @@ static const struct command_registration riscv_exec_command_handlers[] = { .usage = "count address [size=4]", .help = "Repeatedly read the value at address." }, - { - .name = "test_compliance", - .handler = riscv_test_compliance, - .usage = "", - .mode = COMMAND_EXEC, - .help = "Runs a basic compliance test suite against the RISC-V Debug Spec." - }, { .name = "set_command_timeout_sec", .handler = riscv_set_command_timeout_sec, @@ -3473,8 +3319,7 @@ void riscv_info_init(struct target *target, riscv_info_t *r) memset(r->trigger_unique_id, 0xff, sizeof(r->trigger_unique_id)); - for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) - r->xlen[h] = -1; + r->xlen = -1; r->mem_access_methods[0] = RISCV_MEM_ACCESS_PROGBUF; r->mem_access_methods[1] = RISCV_MEM_ACCESS_SYSBUS; @@ -3492,38 +3337,15 @@ static int riscv_resume_go_all_harts(struct target *target) { RISCV_INFO(r); - /* Dummy variables to make mingw32-gcc happy. */ - int first = 0; - int last = 1; - int step = 1; - switch (resume_order) { - case RO_NORMAL: - first = 0; - last = riscv_count_harts(target) - 1; - step = 1; - break; - case RO_REVERSED: - first = riscv_count_harts(target) - 1; - last = 0; - step = -1; - break; - default: - assert(0); - } - - for (int i = first; i != last + step; i += step) { - if (!riscv_hart_enabled(target, i)) - continue; - - LOG_DEBUG("resuming hart %d", i); - if (riscv_set_current_hartid(target, i) != ERROR_OK) + LOG_DEBUG("[%s] resuming hart", target_name(target)); + 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; - if (riscv_is_halted(target)) { - if (r->resume_go(target) != ERROR_OK) - return ERROR_FAIL; - } else { - LOG_DEBUG(" hart %d requested resume, but was already resumed", i); - } + } else { + LOG_DEBUG("[%s] hart requested resume, but was already resumed", + target_name(target)); } riscv_invalidate_register_cache(target); @@ -3533,17 +3355,9 @@ static int riscv_resume_go_all_harts(struct target *target) int riscv_step_rtos_hart(struct target *target) { RISCV_INFO(r); - int hartid = r->current_hartid; - if (riscv_rtos_enabled(target)) { - hartid = r->rtos_hartid; - if (hartid == -1) { - LOG_DEBUG("GDB has asked me to step \"any\" thread, so I'm stepping hart 0."); - hartid = 0; - } - } - if (riscv_set_current_hartid(target, hartid) != ERROR_OK) + if (riscv_select_current_hart(target) != ERROR_OK) return ERROR_FAIL; - LOG_DEBUG("stepping hart %d", hartid); + LOG_DEBUG("[%s] stepping", target_name(target)); if (!riscv_is_halted(target)) { LOG_ERROR("Hart isn't halted before single step!"); @@ -3562,7 +3376,7 @@ int riscv_step_rtos_hart(struct target *target) return ERROR_OK; } -bool riscv_supports_extension(struct target *target, int hartid, char letter) +bool riscv_supports_extension(struct target *target, char letter) { RISCV_INFO(r); unsigned num; @@ -3572,25 +3386,13 @@ bool riscv_supports_extension(struct target *target, int hartid, char letter) num = letter - 'A'; else return false; - return r->misa[hartid] & (1 << num); + return r->misa & (1 << num); } unsigned riscv_xlen(const struct target *target) -{ - return riscv_xlen_of_hart(target, riscv_current_hartid(target)); -} - -int riscv_xlen_of_hart(const struct target *target, int hartid) { RISCV_INFO(r); - assert(r->xlen[hartid] != -1); - return r->xlen[hartid]; -} - -extern struct rtos_type riscv_rtos; -bool riscv_rtos_enabled(const struct target *target) -{ - return target->rtos && target->rtos->type == &riscv_rtos; + return r->xlen; } int riscv_set_current_hartid(struct target *target, int hartid) @@ -3601,16 +3403,10 @@ int riscv_set_current_hartid(struct target *target, int hartid) int previous_hartid = riscv_current_hartid(target); r->current_hartid = hartid; - assert(riscv_hart_enabled(target, hartid)); LOG_DEBUG("setting hartid to %d, was %d", hartid, previous_hartid); if (r->select_current_hart(target) != ERROR_OK) return ERROR_FAIL; - /* This might get called during init, in which case we shouldn't be - * setting up the register cache. */ - if (target_was_examined(target) && riscv_rtos_enabled(target)) - riscv_invalidate_register_cache(target); - return ERROR_OK; } @@ -3634,19 +3430,6 @@ int riscv_current_hartid(const struct target *target) return r->current_hartid; } -void riscv_set_all_rtos_harts(struct target *target) -{ - RISCV_INFO(r); - r->rtos_hartid = -1; -} - -void riscv_set_rtos_hartid(struct target *target, int hartid) -{ - LOG_DEBUG("setting RTOS hartid %d", hartid); - RISCV_INFO(r); - r->rtos_hartid = hartid; -} - int riscv_count_harts(struct target *target) { if (target == NULL) @@ -3657,11 +3440,6 @@ int riscv_count_harts(struct target *target) return r->hart_count(target); } -bool riscv_has_register(struct target *target, int hartid, int regid) -{ - return 1; -} - /** * If write is true: * return true iff we are guaranteed that the register will contain exactly @@ -3715,75 +3493,63 @@ static bool gdb_regno_cacheable(enum gdb_regno regno, bool write) * This function is called when the debug user wants to change the value of a * register. The new value may be cached, and may not be written until the hart * is resumed. */ -int riscv_set_register(struct target *target, enum gdb_regno r, riscv_reg_t v) -{ - return riscv_set_register_on_hart(target, riscv_current_hartid(target), r, v); -} - -int riscv_set_register_on_hart(struct target *target, int hartid, - enum gdb_regno regid, uint64_t value) +int riscv_set_register(struct target *target, enum gdb_regno regid, riscv_reg_t value) { RISCV_INFO(r); - LOG_DEBUG("{%d} %s <- %" PRIx64, hartid, gdb_regno_name(regid), value); + LOG_DEBUG("[%s] %s <- %" PRIx64, target_name(target), gdb_regno_name(regid), value); assert(r->set_register); /* TODO: Hack to deal with gdb that thinks these registers still exist. */ if (regid > GDB_REGNO_XPR15 && regid <= GDB_REGNO_XPR31 && value == 0 && - riscv_supports_extension(target, hartid, 'E')) + riscv_supports_extension(target, 'E')) return ERROR_OK; struct reg *reg = &target->reg_cache->reg_list[regid]; buf_set_u64(reg->value, 0, reg->size, value); - int result = r->set_register(target, hartid, regid, value); + int result = r->set_register(target, regid, value); if (result == ERROR_OK) reg->valid = gdb_regno_cacheable(regid, true); else reg->valid = false; - LOG_DEBUG("[%s]{%d} wrote 0x%" PRIx64 " to %s valid=%d", - target_name(target), hartid, value, reg->name, reg->valid); + LOG_DEBUG("[%s] wrote 0x%" PRIx64 " to %s valid=%d", + target_name(target), value, reg->name, reg->valid); return result; } int riscv_get_register(struct target *target, riscv_reg_t *value, - enum gdb_regno r) -{ - return riscv_get_register_on_hart(target, value, - riscv_current_hartid(target), r); -} - -int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value, - int hartid, enum gdb_regno regid) + enum gdb_regno regid) { RISCV_INFO(r); struct reg *reg = &target->reg_cache->reg_list[regid]; if (!reg->exist) { - LOG_DEBUG("[%s]{%d} %s does not exist.", - target_name(target), hartid, gdb_regno_name(regid)); + LOG_DEBUG("[%s] %s does not exist.", + target_name(target), gdb_regno_name(regid)); return ERROR_FAIL; } - if (reg && reg->valid && hartid == riscv_current_hartid(target)) { + if (reg && reg->valid) { *value = buf_get_u64(reg->value, 0, reg->size); - LOG_DEBUG("{%d} %s: %" PRIx64 " (cached)", hartid, + LOG_DEBUG("[%s] %s: %" PRIx64 " (cached)", target_name(target), gdb_regno_name(regid), *value); return ERROR_OK; } /* TODO: Hack to deal with gdb that thinks these registers still exist. */ if (regid > GDB_REGNO_XPR15 && regid <= GDB_REGNO_XPR31 && - riscv_supports_extension(target, hartid, 'E')) { + riscv_supports_extension(target, 'E')) { *value = 0; return ERROR_OK; } - int result = r->get_register(target, value, hartid, regid); + int result = r->get_register(target, value, regid); if (result == ERROR_OK) reg->valid = gdb_regno_cacheable(regid, false); - LOG_DEBUG("{%d} %s: %" PRIx64, hartid, gdb_regno_name(regid), *value); + LOG_DEBUG("[%s] %s: %" PRIx64, target_name(target), + gdb_regno_name(regid), *value); return result; } @@ -3809,7 +3575,7 @@ enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid) size_t riscv_debug_buffer_size(struct target *target) { RISCV_INFO(r); - return r->debug_buffer_size[riscv_current_hartid(target)]; + return r->debug_buffer_size; } int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn) @@ -3855,15 +3621,6 @@ int riscv_dmi_write_u64_bits(struct target *target) return r->dmi_write_u64_bits(target); } -bool riscv_hart_enabled(struct target *target, int hartid) -{ - /* FIXME: Add a hart mask to the RTOS. */ - if (riscv_rtos_enabled(target)) - return hartid < riscv_count_harts(target); - - return hartid == target->coreid; -} - /** * Count triggers, and initialize trigger_count for each hart. * trigger_count is initialized even if this function fails to discover @@ -3880,65 +3637,58 @@ int riscv_enumerate_triggers(struct target *target) r->triggers_enumerated = true; /* At the very least we tried. */ - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { - if (!riscv_hart_enabled(target, hartid)) - continue; - - riscv_reg_t tselect; - int result = riscv_get_register_on_hart(target, &tselect, hartid, - GDB_REGNO_TSELECT); - /* If tselect is not readable, the trigger module is likely not - * implemented. There are no triggers to enumerate then and no error - * should be thrown. */ - if (result != ERROR_OK) { - LOG_DEBUG("Cannot access tselect register on hart %d. " - "Assuming that triggers are not implemented.", hartid); - continue; - } - - for (unsigned t = 0; t < RISCV_MAX_TRIGGERS; ++t) { - r->trigger_count[hartid] = t; - - /* If we can't write tselect, then this hart does not support triggers. */ - if (riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, t) != ERROR_OK) - break; - uint64_t tselect_rb; - result = riscv_get_register_on_hart(target, &tselect_rb, hartid, - GDB_REGNO_TSELECT); - if (result != ERROR_OK) - return result; - /* Mask off the top bit, which is used as tdrmode in old - * implementations. */ - tselect_rb &= ~(1ULL << (riscv_xlen(target)-1)); - if (tselect_rb != t) - break; - uint64_t tdata1; - result = riscv_get_register_on_hart(target, &tdata1, hartid, - GDB_REGNO_TDATA1); - if (result != ERROR_OK) - return result; - - int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); - if (type == 0) - break; - switch (type) { - case 1: - /* On these older cores we don't support software using - * triggers. */ - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); - break; - case 2: - if (tdata1 & MCONTROL_DMODE(riscv_xlen(target))) - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); - break; - } - } - - riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect); - - LOG_INFO("[%d] Found %d triggers", hartid, r->trigger_count[hartid]); + riscv_reg_t tselect; + int result = riscv_get_register(target, &tselect, GDB_REGNO_TSELECT); + /* If tselect is not readable, the trigger module is likely not + * implemented. There are no triggers to enumerate then and no error + * should be thrown. */ + if (result != ERROR_OK) { + LOG_DEBUG("[%s] Cannot access tselect register. " + "Assuming that triggers are not implemented.", target_name(target)); + r->trigger_count = 0; + return ERROR_OK; } + for (unsigned t = 0; t < RISCV_MAX_TRIGGERS; ++t) { + r->trigger_count = t; + + /* If we can't write tselect, then this hart does not support triggers. */ + if (riscv_set_register(target, GDB_REGNO_TSELECT, t) != ERROR_OK) + break; + uint64_t tselect_rb; + result = riscv_get_register(target, &tselect_rb, GDB_REGNO_TSELECT); + if (result != ERROR_OK) + return result; + /* Mask off the top bit, which is used as tdrmode in old + * implementations. */ + tselect_rb &= ~(1ULL << (riscv_xlen(target)-1)); + if (tselect_rb != t) + break; + uint64_t tdata1; + result = riscv_get_register(target, &tdata1, GDB_REGNO_TDATA1); + if (result != ERROR_OK) + return result; + + int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); + if (type == 0) + break; + switch (type) { + case 1: + /* On these older cores we don't support software using + * triggers. */ + riscv_set_register(target, GDB_REGNO_TDATA1, 0); + break; + case 2: + if (tdata1 & MCONTROL_DMODE(riscv_xlen(target))) + riscv_set_register(target, GDB_REGNO_TDATA1, 0); + break; + } + } + + riscv_set_register(target, GDB_REGNO_TSELECT, tselect); + + LOG_INFO("[%s] Found %d triggers", target_name(target), r->trigger_count); + return ERROR_OK; } @@ -4148,8 +3898,8 @@ static int register_get(struct reg *reg) } reg->valid = gdb_regno_cacheable(reg->number, false); char *str = buf_to_hex_str(reg->value, reg->size); - LOG_DEBUG("[%d]{%d} read 0x%s from %s (valid=%d)", target->coreid, - riscv_current_hartid(target), str, reg->name, reg->valid); + LOG_DEBUG("[%s] read 0x%s from %s (valid=%d)", target_name(target), + str, reg->name, reg->valid); free(str); return ERROR_OK; } @@ -4161,8 +3911,8 @@ static int register_set(struct reg *reg, uint8_t *buf) RISCV_INFO(r); char *str = buf_to_hex_str(buf, reg->size); - LOG_DEBUG("[%d]{%d} write 0x%s to %s (valid=%d)", target->coreid, - riscv_current_hartid(target), str, reg->name, reg->valid); + LOG_DEBUG("[%s] write 0x%s to %s (valid=%d)", target_name(target), + str, reg->name, reg->valid); free(str); /* Exit early for writing x0, which on the hardware would be ignored, and we @@ -4251,8 +4001,6 @@ int riscv_init_registers(struct target *target) return ERROR_FAIL; char *reg_name = info->reg_names; - int hartid = riscv_current_hartid(target); - static struct reg_feature feature_cpu = { .name = "org.gnu.gdb.riscv.cpu" }; @@ -4310,35 +4058,35 @@ int riscv_init_registers(struct target *target) */ info->vector_uint8.type = &type_uint8; - info->vector_uint8.count = info->vlenb[hartid]; + info->vector_uint8.count = info->vlenb; info->type_uint8_vector.type = REG_TYPE_ARCH_DEFINED; info->type_uint8_vector.id = "bytes"; info->type_uint8_vector.type_class = REG_TYPE_CLASS_VECTOR; info->type_uint8_vector.reg_type_vector = &info->vector_uint8; info->vector_uint16.type = &type_uint16; - info->vector_uint16.count = info->vlenb[hartid] / 2; + info->vector_uint16.count = info->vlenb / 2; info->type_uint16_vector.type = REG_TYPE_ARCH_DEFINED; info->type_uint16_vector.id = "shorts"; info->type_uint16_vector.type_class = REG_TYPE_CLASS_VECTOR; info->type_uint16_vector.reg_type_vector = &info->vector_uint16; info->vector_uint32.type = &type_uint32; - info->vector_uint32.count = info->vlenb[hartid] / 4; + info->vector_uint32.count = info->vlenb / 4; info->type_uint32_vector.type = REG_TYPE_ARCH_DEFINED; info->type_uint32_vector.id = "words"; info->type_uint32_vector.type_class = REG_TYPE_CLASS_VECTOR; info->type_uint32_vector.reg_type_vector = &info->vector_uint32; info->vector_uint64.type = &type_uint64; - info->vector_uint64.count = info->vlenb[hartid] / 8; + info->vector_uint64.count = info->vlenb / 8; info->type_uint64_vector.type = REG_TYPE_ARCH_DEFINED; info->type_uint64_vector.id = "longs"; info->type_uint64_vector.type_class = REG_TYPE_CLASS_VECTOR; info->type_uint64_vector.reg_type_vector = &info->vector_uint64; info->vector_uint128.type = &type_uint128; - info->vector_uint128.count = info->vlenb[hartid] / 16; + info->vector_uint128.count = info->vlenb / 16; info->type_uint128_vector.type = REG_TYPE_ARCH_DEFINED; info->type_uint128_vector.id = "quads"; info->type_uint128_vector.type_class = REG_TYPE_CLASS_VECTOR; @@ -4346,28 +4094,28 @@ int riscv_init_registers(struct target *target) info->vector_fields[0].name = "b"; info->vector_fields[0].type = &info->type_uint8_vector; - if (info->vlenb[hartid] >= 2) { + if (info->vlenb >= 2) { info->vector_fields[0].next = info->vector_fields + 1; info->vector_fields[1].name = "s"; info->vector_fields[1].type = &info->type_uint16_vector; } else { info->vector_fields[0].next = NULL; } - if (info->vlenb[hartid] >= 4) { + if (info->vlenb >= 4) { info->vector_fields[1].next = info->vector_fields + 2; info->vector_fields[2].name = "w"; info->vector_fields[2].type = &info->type_uint32_vector; } else { info->vector_fields[1].next = NULL; } - if (info->vlenb[hartid] >= 8) { + if (info->vlenb >= 8) { info->vector_fields[2].next = info->vector_fields + 3; info->vector_fields[3].name = "l"; info->vector_fields[3].type = &info->type_uint64_vector; } else { info->vector_fields[2].next = NULL; } - if (info->vlenb[hartid] >= 16) { + if (info->vlenb >= 16) { info->vector_fields[3].next = info->vector_fields + 4; info->vector_fields[4].name = "q"; info->vector_fields[4].type = &info->type_uint128_vector; @@ -4418,7 +4166,7 @@ int riscv_init_registers(struct target *target) * of other things to break in that case as well. */ if (number <= GDB_REGNO_XPR31) { r->exist = number <= GDB_REGNO_XPR15 || - !riscv_supports_extension(target, hartid, 'E'); + !riscv_supports_extension(target, 'E'); /* TODO: For now we fake that all GPRs exist because otherwise gdb * doesn't work. */ r->exist = true; @@ -4530,13 +4278,13 @@ int riscv_init_registers(struct target *target) r->feature = &feature_cpu; } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { r->caller_save = true; - if (riscv_supports_extension(target, hartid, 'D')) { + if (riscv_supports_extension(target, 'D')) { r->size = 64; - if (riscv_supports_extension(target, hartid, 'F')) + if (riscv_supports_extension(target, 'F')) r->reg_data_type = &type_ieee_single_double; else r->reg_data_type = &type_ieee_double; - } else if (riscv_supports_extension(target, hartid, 'F')) { + } else if (riscv_supports_extension(target, 'F')) { r->reg_data_type = &type_ieee_single; r->size = 32; } else { @@ -4667,7 +4415,7 @@ int riscv_init_registers(struct target *target) case CSR_FFLAGS: case CSR_FRM: case CSR_FCSR: - r->exist = riscv_supports_extension(target, hartid, 'F'); + r->exist = riscv_supports_extension(target, 'F'); r->group = "float"; r->feature = &feature_fpu; break; @@ -4681,15 +4429,15 @@ int riscv_init_registers(struct target *target) case CSR_SCAUSE: case CSR_STVAL: case CSR_SATP: - r->exist = riscv_supports_extension(target, hartid, 'S'); + r->exist = riscv_supports_extension(target, 'S'); break; case CSR_MEDELEG: case CSR_MIDELEG: /* "In systems with only M-mode, or with both M-mode and * U-mode but without U-mode trap support, the medeleg and * mideleg registers should not exist." */ - r->exist = riscv_supports_extension(target, hartid, 'S') || - riscv_supports_extension(target, hartid, 'N'); + r->exist = riscv_supports_extension(target, 'S') || + riscv_supports_extension(target, 'N'); break; case CSR_PMPCFG1: @@ -4766,7 +4514,7 @@ int riscv_init_registers(struct target *target) case CSR_VL: case CSR_VTYPE: case CSR_VLENB: - r->exist = riscv_supports_extension(target, hartid, 'V'); + r->exist = riscv_supports_extension(target, 'V'); break; } @@ -4795,8 +4543,8 @@ int riscv_init_registers(struct target *target) } else if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31) { r->caller_save = false; - r->exist = riscv_supports_extension(target, hartid, 'V') && info->vlenb[hartid]; - r->size = info->vlenb[hartid] * 8; + r->exist = riscv_supports_extension(target, 'V') && info->vlenb; + r->size = info->vlenb * 8; sprintf(reg_name, "v%d", number - GDB_REGNO_V0); r->group = "vector"; r->feature = &feature_vector; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index aa9614a2f..094851b7d 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -90,9 +90,6 @@ typedef struct { struct command_context *cmd_ctx; void *version_specific; - /* The hart that the RTOS thinks is currently being debugged. */ - int rtos_hartid; - /* 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 @@ -109,13 +106,13 @@ typedef struct { char *reg_names; /* It's possible that each core has a different supported ISA set. */ - int xlen[RISCV_MAX_HARTS]; - riscv_reg_t misa[RISCV_MAX_HARTS]; + int xlen; + riscv_reg_t misa; /* Cached value of vlenb. 0 if vlenb is not readable for some reason. */ - unsigned vlenb[RISCV_MAX_HARTS]; + unsigned vlenb; /* The number of triggers per hart. */ - unsigned trigger_count[RISCV_MAX_HARTS]; + unsigned trigger_count; /* For each physical trigger, contains -1 if the hwbp is available, or the * unique_id of the breakpoint/watchpoint that is using it. @@ -124,7 +121,7 @@ typedef struct { int trigger_unique_id[RISCV_MAX_HWBPS]; /* The number of entries in the debug buffer. */ - int debug_buffer_size[RISCV_MAX_HARTS]; + int debug_buffer_size; /* This avoids invalidating the register cache too often. */ bool registers_initialized; @@ -145,10 +142,8 @@ typedef struct { /* Helper functions that target the various RISC-V debug spec * implementations. */ - int (*get_register)(struct target *target, - riscv_reg_t *value, int hid, int rid); - int (*set_register)(struct target *target, int hartid, int regid, - uint64_t value); + int (*get_register)(struct target *target, riscv_reg_t *value, int regid); + int (*set_register)(struct target *target, int regid, uint64_t value); 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); @@ -185,8 +180,6 @@ typedef struct { int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address, uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test); - int (*test_compliance)(struct target *target); - int (*sample_memory)(struct target *target, riscv_sample_buf_t *buf, riscv_sample_config_t *config, @@ -333,44 +326,30 @@ void riscv_info_init(struct target *target, riscv_info_t *r); * then the only hart. */ int riscv_step_rtos_hart(struct target *target); -bool riscv_supports_extension(struct target *target, int hartid, char letter); +bool riscv_supports_extension(struct target *target, char letter); /* Returns XLEN for the given (or current) hart. */ unsigned riscv_xlen(const struct target *target); -int riscv_xlen_of_hart(const struct target *target, int hartid); - -bool riscv_rtos_enabled(const struct target *target); +int riscv_xlen_of_hart(const struct target *target); /* Sets the current hart, which is the hart that will actually be used when * issuing debug commands. */ int riscv_set_current_hartid(struct target *target, int hartid); +int riscv_select_current_hart(struct target *target); int riscv_current_hartid(const struct target *target); /*** Support functions for the RISC-V 'RTOS', which provides multihart support * without requiring multiple targets. */ -/* When using the RTOS to debug, this selects the hart that is currently being - * debugged. This doesn't propagate to the hardware. */ -void riscv_set_all_rtos_harts(struct target *target); -void riscv_set_rtos_hartid(struct target *target, int hartid); - /* 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); -/* Returns TRUE if the target has the given register on the given hart. */ -bool riscv_has_register(struct target *target, int hartid, int regid); - /** Set register, updating the cache. */ int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v); -/** Set register, updating the cache. */ -int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v); /** Get register, from the cache if it's in there. */ int riscv_get_register(struct target *target, riscv_reg_t *value, enum gdb_regno r); -/** Get register, from the cache if it's in there. */ -int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value, - int hartid, enum gdb_regno regid); /* Checks the state of the current hart -- "is_halted" checks the actual * on-device register. */ @@ -393,9 +372,6 @@ int riscv_dmi_write_u64_bits(struct target *target); /* Invalidates the register cache. */ void riscv_invalidate_register_cache(struct target *target); -/* Returns TRUE when a hart is enabled in this target. */ -bool riscv_hart_enabled(struct target *target, int hartid); - int riscv_enumerate_triggers(struct target *target); int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint);