diff options
author | 2023-10-10 11:40:56 +0000 | |
---|---|---|
committer | 2023-10-10 11:40:56 +0000 | |
commit | e02cda008591317b1625707ff8e115a4841aa889 (patch) | |
tree | aee302e3cf8b59ec2d32ec481be3d1afddfc8968 /target/riscv/gdbstub.c | |
parent | cc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff) |
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback
design to work with QEMU and rust-vmm vhost-user backend without require any
changes.
Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'target/riscv/gdbstub.c')
-rw-r--r-- | target/riscv/gdbstub.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c new file mode 100644 index 000000000..23429179e --- /dev/null +++ b/target/riscv/gdbstub.c @@ -0,0 +1,212 @@ +/* + * RISC-V GDB Server Stub + * + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "exec/gdbstub.h" +#include "cpu.h" + +int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + if (n < 32) { + return gdb_get_regl(mem_buf, env->gpr[n]); + } else if (n == 32) { + return gdb_get_regl(mem_buf, env->pc); + } + return 0; +} + +int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + if (n == 0) { + /* discard writes to x0 */ + return sizeof(target_ulong); + } else if (n < 32) { + env->gpr[n] = ldtul_p(mem_buf); + return sizeof(target_ulong); + } else if (n == 32) { + env->pc = ldtul_p(mem_buf); + return sizeof(target_ulong); + } + return 0; +} + +static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) +{ + if (n < 32) { + if (env->misa_ext & RVD) { + return gdb_get_reg64(buf, env->fpr[n]); + } + if (env->misa_ext & RVF) { + return gdb_get_reg32(buf, env->fpr[n]); + } + /* there is hole between ft11 and fflags in fpu.xml */ + } else if (n < 36 && n > 32) { + target_ulong val = 0; + int result; + /* + * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP + * register 33, so we recalculate the map index. + * This also works for CSR_FRM and CSR_FCSR. + */ + result = riscv_csrrw_debug(env, n - 32, &val, + 0, 0); + if (result == RISCV_EXCP_NONE) { + return gdb_get_regl(buf, val); + } + } + return 0; +} + +static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { + env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */ + return sizeof(uint64_t); + /* there is hole between ft11 and fflags in fpu.xml */ + } else if (n < 36 && n > 32) { + target_ulong val = ldtul_p(mem_buf); + int result; + /* + * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP + * register 33, so we recalculate the map index. + * This also works for CSR_FRM and CSR_FCSR. + */ + result = riscv_csrrw_debug(env, n - 32, NULL, + val, -1); + if (result == RISCV_EXCP_NONE) { + return sizeof(target_ulong); + } + } + return 0; +} + +static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n) +{ + if (n < CSR_TABLE_SIZE) { + target_ulong val = 0; + int result; + + result = riscv_csrrw_debug(env, n, &val, 0, 0); + if (result == RISCV_EXCP_NONE) { + return gdb_get_regl(buf, val); + } + } + return 0; +} + +static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n) +{ + if (n < CSR_TABLE_SIZE) { + target_ulong val = ldtul_p(mem_buf); + int result; + + result = riscv_csrrw_debug(env, n, NULL, val, -1); + if (result == RISCV_EXCP_NONE) { + return sizeof(target_ulong); + } + } + return 0; +} + +static int riscv_gdb_get_virtual(CPURISCVState *cs, GByteArray *buf, int n) +{ + if (n == 0) { +#ifdef CONFIG_USER_ONLY + return gdb_get_regl(buf, 0); +#else + return gdb_get_regl(buf, cs->priv); +#endif + } + return 0; +} + +static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n) +{ + if (n == 0) { +#ifndef CONFIG_USER_ONLY + cs->priv = ldtul_p(mem_buf) & 0x3; + if (cs->priv == PRV_H) { + cs->priv = PRV_S; + } +#endif + return sizeof(target_ulong); + } + return 0; +} + +static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + GString *s = g_string_new(NULL); + riscv_csr_predicate_fn predicate; + int bitsize = 16 << env->misa_mxl_max; + int i; + + g_string_printf(s, "<?xml version=\"1.0\"?>"); + g_string_append_printf(s, "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">"); + g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">"); + + for (i = 0; i < CSR_TABLE_SIZE; i++) { + predicate = csr_ops[i].predicate; + if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) { + if (csr_ops[i].name) { + g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name); + } else { + g_string_append_printf(s, "<reg name=\"csr%03x\"", i); + } + g_string_append_printf(s, " bitsize=\"%d\"", bitsize); + g_string_append_printf(s, " regnum=\"%d\"/>", base_reg + i); + } + } + + g_string_append_printf(s, "</feature>"); + + cpu->dyn_csr_xml = g_string_free(s, false); + return CSR_TABLE_SIZE; +} + +void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + if (env->misa_ext & RVD) { + gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, + 36, "riscv-64bit-fpu.xml", 0); + } else if (env->misa_ext & RVF) { + gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, + 36, "riscv-32bit-fpu.xml", 0); + } +#if defined(TARGET_RISCV32) + 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_virtual, riscv_gdb_set_virtual, + 1, "riscv-64bit-virtual.xml", 0); +#endif + + gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, + riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), + "riscv-csr.xml", 0); +} |