From: Hsiangkai Wang <kai.w...@sifive.com> Signed-off-by: Hsiangkai Wang <kai.w...@sifive.com> Signed-off-by: Frank Chang <frank.ch...@sifive.com> --- gdb-xml/riscv-64bit-csr.xml | 7 ++ target/riscv/cpu.c | 1 + target/riscv/cpu.h | 25 +++++++ target/riscv/gdbstub.c | 126 +++++++++++++++++++++++++++++++++++- 4 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/gdb-xml/riscv-64bit-csr.xml b/gdb-xml/riscv-64bit-csr.xml index 90394562930..f768c3202a4 100644 --- a/gdb-xml/riscv-64bit-csr.xml +++ b/gdb-xml/riscv-64bit-csr.xml @@ -248,4 +248,11 @@ <reg name="mucounteren" bitsize="64"/> <reg name="mscounteren" bitsize="64"/> <reg name="mhcounteren" bitsize="64"/> + <reg name="vstart" bitsize="64" group="vector"/> + <reg name="vxsat" bitsize="64" group="vector"/> + <reg name="vxrm" bitsize="64" group="vector"/> + <reg name="vcsr" bitsize="64" group="vector"/> + <reg name="vl" bitsize="64" group="vector"/> + <reg name="vtype" bitsize="64" group="vector"/> + <reg name="vlenb" bitsize="64" group="vector"/> </feature> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8844975bf94..e04cea5514c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -548,6 +548,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) #elif defined(TARGET_RISCV64) cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; #endif + cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml; cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = riscv_cpu_disas_set_info; #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 528814cbfc7..88ca6f71c2e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -102,6 +102,16 @@ FIELD(VTYPE, VEDIV, 8, 2) FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11) FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1) +/** + * DynamicGDBXMLInfo: + * @desc: Contains the XML descriptions. + * @num: Number of the registers in this XML seen by GDB. + */ +typedef struct DynamicGDBXMLInfo { + char *desc; + int num; +} DynamicGDBXMLInfo; + struct CPURISCVState { target_ulong gpr[32]; uint64_t fpr[32]; /* assume both F and D extensions */ @@ -295,6 +305,8 @@ typedef struct RISCVCPU { bool mmu; bool pmp; } cfg; + + DynamicGDBXMLInfo dyn_vreg_xml; } RISCVCPU; static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext) @@ -485,6 +497,19 @@ typedef struct { void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops); void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops); +/* + * Helpers to dynamically generates XML descriptions of the + * vector registers. Returns the number of registers in each set. + */ +int ricsv_gen_dynamic_vector_xml(CPUState *cpu, int base_reg); + +/* + * Returns the dynamically generated XML for the gdb stub. + * Returns a pointer to the XML contents for the specified XML file or NULL + * if the XML name doesn't match the predefined one. + */ +const char *riscv_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname); + void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); #endif /* RISCV_CPU_H */ diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index f7c5212e274..ceb73a08b25 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -268,6 +268,39 @@ static int csr_register_map[] = { CSR_MUCOUNTEREN, CSR_MSCOUNTEREN, CSR_MHCOUNTEREN, + CSR_VSTART, + CSR_VXSAT, + CSR_VXRM, + CSR_VCSR, + CSR_VL, + CSR_VTYPE, + CSR_VLENB, +}; + +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) @@ -351,6 +384,34 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) 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; + } + 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; + } + return 0; +} + static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n) { if (n < ARRAY_SIZE(csr_register_map)) { @@ -405,6 +466,51 @@ static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n) return 0; } +int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + GString *s = g_string_new(NULL); + DynamicGDBXMLInfo *info = &cpu->dyn_vreg_xml; + g_autoptr(GString) ts = g_string_new(""); + int i, reg_width = cpu->cfg.vlen; + info->num = 0; + 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++); + info->num++; + } + + g_string_append_printf(s, "</feature>"); + cpu->dyn_vreg_xml.desc = g_string_free(s, false); + return cpu->dyn_vreg_xml.num; +} + void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); @@ -416,17 +522,33 @@ 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 & 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_csr, riscv_gdb_set_csr, - 241, "riscv-32bit-csr.xml", 0); + 248, "riscv-32bit-csr.xml", 0); gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, 1, "riscv-32bit-virtual.xml", 0); #elif defined(TARGET_RISCV64) gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, - 241, "riscv-64bit-csr.xml", 0); + 248, "riscv-64bit-csr.xml", 0); gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, 1, "riscv-64bit-virtual.xml", 0); #endif } + +const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + + if (strcmp(xmlname, "riscv-vector.xml") == 0) { + return cpu->dyn_vreg_xml.desc; + } + return NULL; +} -- 2.17.1