aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2021-01-18 12:22:43 -0800
committerGitHub <noreply@github.com>2021-01-18 12:22:43 -0800
commitd52e4668a60212524b3d29b92b47cc21c5317b66 (patch)
tree0231b279ea62174b88a5eab76818a825cbcee5bf
parented37337b0d39383285b1d86fbefc9ce289470bb3 (diff)
downloadriscv-openocd-d52e4668a60212524b3d29b92b47cc21c5317b66.zip
riscv-openocd-d52e4668a60212524b3d29b92b47cc21c5317b66.tar.gz
riscv-openocd-d52e4668a60212524b3d29b92b47cc21c5317b66.tar.bz2
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 <tim@sifive.com>
-rw-r--r--src/rtos/Makefile.am4
-rw-r--r--src/rtos/riscv_debug.c373
-rw-r--r--src/rtos/riscv_debug.h13
-rw-r--r--src/rtos/rtos.c2
-rw-r--r--src/target/riscv/riscv-011.c29
-rw-r--r--src/target/riscv/riscv-013.c651
-rw-r--r--src/target/riscv/riscv.c616
-rw-r--r--src/target/riscv/riscv.h44
8 files changed, 271 insertions, 1461 deletions
diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
index 2cb8bd1..de54596 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 af8c4f1..0000000
--- 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, &reg_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, &reg_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 539edf2..0000000
--- 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 b391b2c..f88925a 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 45a44f2..78cd55f 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 6848505..4163a38 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,54 +1716,49 @@ 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;
- }
+ 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;
}
+ }
- /* 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;
+ /* Without knowing anything else we can at least mess with the
+ * program buffer. */
+ r->debug_buffer_size = info->progbufsize;
- if (register_read(target, &r->misa[i], GDB_REGNO_MISA)) {
- LOG_ERROR("Fatal: Failed to read MISA from hart %d.", i);
- return ERROR_FAIL;
- }
+ int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64);
+ if (result == ERROR_OK)
+ r->xlen = 64;
+ else
+ r->xlen = 32;
- if (riscv_supports_extension(target, i, 'V')) {
- if (discover_vlenb(target, i) != ERROR_OK)
- return ERROR_FAIL;
- }
+ 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;
+ }
- /* Now init registers based on what we discovered. */
- if (riscv_init_registers(target) != ERROR_OK)
+ if (riscv_supports_extension(target, 'V')) {
+ if (discover_vlenb(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]);
+ /* Now init registers based on what we discovered. */
+ if (riscv_init_registers(target) != ERROR_OK)
+ return ERROR_FAIL;
- if (!halted)
- riscv013_step_or_resume_current_hart(target, false, false);
- }
+ /* 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);
@@ -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 9a56561..fb198cb 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);
@@ -3191,13 +3044,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.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,
.mode = COMMAND_ANY,
@@ -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,64 +3637,57 @@ 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(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;
+ }
- 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 = t;
- 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(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;
- /* 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)
+ 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;
- 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)
+ case 2:
+ if (tdata1 & MCONTROL_DMODE(riscv_xlen(target)))
+ riscv_set_register(target, GDB_REGNO_TDATA1, 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);
+ riscv_set_register(target, GDB_REGNO_TSELECT, tselect);
- LOG_INFO("[%d] Found %d triggers", hartid, r->trigger_count[hartid]);
- }
+ 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 aa9614a..094851b 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);