mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
target/riscv: Extract monitor-related code to monitor.c
Keep riscv-qmp-cmds.c for QMP, use monitor.c for HMP. Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260219191955.83815-7-philmd@linaro.org>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user