From c60750fe5ef287c7324c5d5945b0b5a392ac67ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 17 Feb 2026 08:54:47 +0100 Subject: [PATCH] target/riscv: Extract monitor-related code to monitor.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep riscv-qmp-cmds.c for QMP, use monitor.c for HMP. Reviewed-by: Daniel Henrique Barboza Reviewed-by: Pierrick Bouvier Signed-off-by: Philippe Mathieu-Daudé Message-ID: <20260219191955.83815-7-philmd@linaro.org> --- target/riscv/monitor.c | 148 +++++++++++++++++++++++++++++++++ target/riscv/riscv-qmp-cmds.c | 150 ---------------------------------- 2 files changed, 148 insertions(+), 150 deletions(-) diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index 478fd392ac..ccb7eb44d0 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -19,6 +19,8 @@ */ #include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/qemu-print.h" #include "cpu.h" #include "cpu_bits.h" #include "monitor/monitor.h" @@ -241,3 +243,149 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) mem_info_svxx(mon, env); } + +/* + * We have way too many potential CSRs and regs being added + * regularly to register them in a static array. + * + * Declare an empty array instead, making get_monitor_def() use + * the target_get_monitor_def() API directly. + */ +const MonitorDef monitor_defs[] = { { } }; +const MonitorDef *target_monitor_defs(void) +{ + return monitor_defs; +} + +static bool reg_is_ulong_integer(CPURISCVState *env, const char *name, + target_ulong *val, bool is_gprh) +{ + const char * const *reg_names; + target_ulong *vals; + + if (is_gprh) { + reg_names = riscv_int_regnamesh; + vals = env->gprh; + } else { + reg_names = riscv_int_regnames; + vals = env->gpr; + } + + for (int i = 0; i < 32; i++) { + g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2); + + g_assert(reg_name[0]); + g_assert(reg_name[1]); + + if (g_ascii_strcasecmp(reg_name[0], name) == 0 || + g_ascii_strcasecmp(reg_name[1], name) == 0) { + *val = vals[i]; + return true; + } + } + + return false; +} + +static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val) +{ + if (qemu_tolower(name[0]) != 'f') { + return false; + } + + for (int i = 0; i < 32; i++) { + g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2); + + g_assert(reg_name[0]); + g_assert(reg_name[1]); + + if (g_ascii_strcasecmp(reg_name[0], name) == 0 || + g_ascii_strcasecmp(reg_name[1], name) == 0) { + *val = env->fpr[i]; + return true; + } + } + + return false; +} + +static bool reg_is_vreg(const char *name) +{ + if (qemu_tolower(name[0]) != 'v' || strlen(name) > 3) { + return false; + } + + for (int i = 0; i < 32; i++) { + if (strcasecmp(name, riscv_rvv_regnames[i]) == 0) { + return true; + } + } + + return false; +} + +int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval) +{ + CPURISCVState *env = &RISCV_CPU(cs)->env; + target_ulong val = 0; + uint64_t val64 = 0; + int i; + + if (reg_is_ulong_integer(env, name, &val, false) || + reg_is_ulong_integer(env, name, &val, true)) { + *pval = val; + return 0; + } + + if (reg_is_u64_fpu(env, name, &val64)) { + *pval = val64; + return 0; + } + + if (reg_is_vreg(name)) { + if (!riscv_cpu_cfg(env)->ext_zve32x) { + return -EINVAL; + } + + qemu_printf("Unable to print the value of vector " + "vreg '%s' from this API\n", name); + + /* + * We're returning 0 because returning -EINVAL triggers + * an 'unknown register' message in exp_unary() later, + * which feels ankward after our own error message. + */ + *pval = 0; + return 0; + } + + for (i = 0; i < ARRAY_SIZE(csr_ops); i++) { + RISCVException res; + int csrno = i; + + /* + * Early skip when possible since we're going + * through a lot of NULL entries. + */ + if (csr_ops[csrno].predicate == NULL) { + continue; + } + + if (strcasecmp(csr_ops[csrno].name, name) != 0) { + continue; + } + + res = riscv_csrrw_debug(env, csrno, &val, 0, 0); + + /* + * Rely on the smode, hmode, etc, predicates within csr.c + * to do the filtering of the registers that are present. + */ + if (res == RISCV_EXCP_NONE) { + *pval = val; + return 0; + } + } + + return -EINVAL; +} diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index d5e9bec0f8..8a1856c50e 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -31,10 +31,6 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/visitor.h" #include "qom/qom-qobject.h" -#include "qemu/ctype.h" -#include "qemu/qemu-print.h" -#include "monitor/hmp.h" -#include "monitor/hmp-target.h" #include "system/kvm.h" #include "system/tcg.h" #include "cpu-qom.h" @@ -244,149 +240,3 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, return expansion_info; } - -/* - * We have way too many potential CSRs and regs being added - * regularly to register them in a static array. - * - * Declare an empty array instead, making get_monitor_def() use - * the target_get_monitor_def() API directly. - */ -const MonitorDef monitor_defs[] = { { } }; -const MonitorDef *target_monitor_defs(void) -{ - return monitor_defs; -} - -static bool reg_is_ulong_integer(CPURISCVState *env, const char *name, - target_ulong *val, bool is_gprh) -{ - const char * const *reg_names; - target_ulong *vals; - - if (is_gprh) { - reg_names = riscv_int_regnamesh; - vals = env->gprh; - } else { - reg_names = riscv_int_regnames; - vals = env->gpr; - } - - for (int i = 0; i < 32; i++) { - g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2); - - g_assert(reg_name[0]); - g_assert(reg_name[1]); - - if (g_ascii_strcasecmp(reg_name[0], name) == 0 || - g_ascii_strcasecmp(reg_name[1], name) == 0) { - *val = vals[i]; - return true; - } - } - - return false; -} - -static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val) -{ - if (qemu_tolower(name[0]) != 'f') { - return false; - } - - for (int i = 0; i < 32; i++) { - g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2); - - g_assert(reg_name[0]); - g_assert(reg_name[1]); - - if (g_ascii_strcasecmp(reg_name[0], name) == 0 || - g_ascii_strcasecmp(reg_name[1], name) == 0) { - *val = env->fpr[i]; - return true; - } - } - - return false; -} - -static bool reg_is_vreg(const char *name) -{ - if (qemu_tolower(name[0]) != 'v' || strlen(name) > 3) { - return false; - } - - for (int i = 0; i < 32; i++) { - if (strcasecmp(name, riscv_rvv_regnames[i]) == 0) { - return true; - } - } - - return false; -} - -int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval) -{ - CPURISCVState *env = &RISCV_CPU(cs)->env; - target_ulong val = 0; - uint64_t val64 = 0; - int i; - - if (reg_is_ulong_integer(env, name, &val, false) || - reg_is_ulong_integer(env, name, &val, true)) { - *pval = val; - return 0; - } - - if (reg_is_u64_fpu(env, name, &val64)) { - *pval = val64; - return 0; - } - - if (reg_is_vreg(name)) { - if (!riscv_cpu_cfg(env)->ext_zve32x) { - return -EINVAL; - } - - qemu_printf("Unable to print the value of vector " - "vreg '%s' from this API\n", name); - - /* - * We're returning 0 because returning -EINVAL triggers - * an 'unknown register' message in exp_unary() later, - * which feels ankward after our own error message. - */ - *pval = 0; - return 0; - } - - for (i = 0; i < ARRAY_SIZE(csr_ops); i++) { - RISCVException res; - int csrno = i; - - /* - * Early skip when possible since we're going - * through a lot of NULL entries. - */ - if (csr_ops[csrno].predicate == NULL) { - continue; - } - - if (strcasecmp(csr_ops[csrno].name, name) != 0) { - continue; - } - - res = riscv_csrrw_debug(env, csrno, &val, 0, 0); - - /* - * Rely on the smode, hmode, etc, predicates within csr.c - * to do the filtering of the registers that are present. - */ - if (res == RISCV_EXCP_NONE) { - *pval = val; - return 0; - } - } - - return -EINVAL; -}