summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorHsiangkai Wang <kai.wang@sifive.com>2021-12-10 15:56:54 +0800
committerAlistair Francis <alistair.francis@wdc.com>2021-12-20 14:53:31 +1000
commit719d3561b269d880b2d31e64ed7632407952bad0 (patch)
tree982331798264dc5d9883796288c53e230450d688 /target
parentd6c4d3f2a693f4520ec72b0bd25be6ec03fee13a (diff)
downloadqemu-719d3561b269d880b2d31e64ed7632407952bad0.zip
target/riscv: gdb: support vector registers for rv64 & rv32
Signed-off-by: Hsiangkai Wang <kai.wang@sifive.com> Signed-off-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Frank Chang <frank.chang@sifive.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20211210075704.23951-69-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target')
-rw-r--r--target/riscv/cpu.c2
-rw-r--r--target/riscv/cpu.h1
-rw-r--r--target/riscv/gdbstub.c184
3 files changed, 187 insertions, 0 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 728092f78c..9776297c79 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -675,6 +675,8 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
if (strcmp(xmlname, "riscv-csr.xml") == 0) {
return cpu->dyn_csr_xml;
+ } else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
+ return cpu->dyn_vreg_xml;
}
return NULL;
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5d93ccdfa7..dc10f27093 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -291,6 +291,7 @@ struct RISCVCPU {
CPURISCVState env;
char *dyn_csr_xml;
+ char *dyn_vreg_xml;
/* Configuration Settings */
struct {
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 23429179e2..881ab33392 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -20,6 +20,32 @@
#include "exec/gdbstub.h"
#include "cpu.h"
+struct TypeSize {
+ const char *gdb_type;
+ const char *id;
+ int size;
+ const char suffix;
+};
+
+static const struct TypeSize vec_lanes[] = {
+ /* quads */
+ { "uint128", "quads", 128, 'q' },
+ /* 64 bit */
+ { "uint64", "longs", 64, 'l' },
+ /* 32 bit */
+ { "uint32", "words", 32, 'w' },
+ /* 16 bit */
+ { "uint16", "shorts", 16, 's' },
+ /*
+ * TODO: currently there is no reliable way of telling
+ * if the remote gdb actually understands ieee_half so
+ * we don't expose it in the target description for now.
+ * { "ieee_half", 16, 'h', 'f' },
+ */
+ /* bytes */
+ { "uint8", "bytes", 8, 'b' },
+};
+
int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
RISCVCPU *cpu = RISCV_CPU(cs);
@@ -101,6 +127,96 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
+/*
+ * Convert register index number passed by GDB to the correspond
+ * vector CSR number. Vector CSRs are defined after vector registers
+ * in dynamic generated riscv-vector.xml, thus the starting register index
+ * of vector CSRs is 32.
+ * Return 0 if register index number is out of range.
+ */
+static int riscv_gdb_vector_csrno(int num_regs)
+{
+ /*
+ * The order of vector CSRs in the switch case
+ * should match with the order defined in csr_ops[].
+ */
+ switch (num_regs) {
+ case 32:
+ return CSR_VSTART;
+ case 33:
+ return CSR_VXSAT;
+ case 34:
+ return CSR_VXRM;
+ case 35:
+ return CSR_VCSR;
+ case 36:
+ return CSR_VL;
+ case 37:
+ return CSR_VTYPE;
+ case 38:
+ return CSR_VLENB;
+ default:
+ /* Unknown register. */
+ return 0;
+ }
+}
+
+static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
+{
+ uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+ if (n < 32) {
+ int i;
+ int cnt = 0;
+ for (i = 0; i < vlenb; i += 8) {
+ cnt += gdb_get_reg64(buf,
+ env->vreg[(n * vlenb + i) / 8]);
+ }
+ return cnt;
+ }
+
+ int csrno = riscv_gdb_vector_csrno(n);
+
+ if (!csrno) {
+ return 0;
+ }
+
+ target_ulong val = 0;
+ int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);
+
+ if (result == 0) {
+ return gdb_get_regl(buf, val);
+ }
+
+ return 0;
+}
+
+static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
+{
+ uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
+ if (n < 32) {
+ int i;
+ for (i = 0; i < vlenb; i += 8) {
+ env->vreg[(n * vlenb + i) / 8] = ldq_p(mem_buf + i);
+ }
+ return vlenb;
+ }
+
+ int csrno = riscv_gdb_vector_csrno(n);
+
+ if (!csrno) {
+ return 0;
+ }
+
+ target_ulong val = ldtul_p(mem_buf);
+ int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
+
+ if (result == 0) {
+ return sizeof(target_ulong);
+ }
+
+ return 0;
+}
+
static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < CSR_TABLE_SIZE) {
@@ -187,6 +303,68 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
return CSR_TABLE_SIZE;
}
+static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
+{
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ GString *s = g_string_new(NULL);
+ g_autoptr(GString) ts = g_string_new("");
+ int reg_width = cpu->cfg.vlen;
+ int num_regs = 0;
+ int i;
+
+ g_string_printf(s, "<?xml version=\"1.0\"?>");
+ g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.vector\">");
+
+ /* First define types and totals in a whole VL */
+ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ int count = reg_width / vec_lanes[i].size;
+ g_string_printf(ts, "%s", vec_lanes[i].id);
+ g_string_append_printf(s,
+ "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
+ ts->str, vec_lanes[i].gdb_type, count);
+ }
+
+ /* Define unions */
+ g_string_append_printf(s, "<union id=\"riscv_vector\">");
+ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ g_string_append_printf(s, "<field name=\"%c\" type=\"%s\"/>",
+ vec_lanes[i].suffix,
+ vec_lanes[i].id);
+ }
+ g_string_append(s, "</union>");
+
+ /* Define vector registers */
+ for (i = 0; i < 32; i++) {
+ g_string_append_printf(s,
+ "<reg name=\"v%d\" bitsize=\"%d\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"riscv_vector\"/>",
+ i, reg_width, base_reg++);
+ num_regs++;
+ }
+
+ /* Define vector CSRs */
+ const char *vector_csrs[7] = {
+ "vstart", "vxsat", "vxrm", "vcsr",
+ "vl", "vtype", "vlenb"
+ };
+
+ for (i = 0; i < 7; i++) {
+ g_string_append_printf(s,
+ "<reg name=\"%s\" bitsize=\"%d\""
+ " regnum=\"%d\" group=\"vector\""
+ " type=\"int\"/>",
+ vector_csrs[i], TARGET_LONG_BITS, base_reg++);
+ num_regs++;
+ }
+
+ g_string_append_printf(s, "</feature>");
+
+ cpu->dyn_vreg_xml = g_string_free(s, false);
+ return num_regs;
+}
+
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
@@ -198,6 +376,12 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
36, "riscv-32bit-fpu.xml", 0);
}
+ if (env->misa_ext & RVV) {
+ gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
+ ricsv_gen_dynamic_vector_xml(cs,
+ cs->gdb_num_regs),
+ "riscv-vector.xml", 0);
+ }
#if defined(TARGET_RISCV32)
gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
1, "riscv-32bit-virtual.xml", 0);