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>
Philippe Mathieu-Daudé committed
Feb 17, 2026 at 08:54 UTC
c60750fe5ef287c7324c5d5945b0b5a392ac67ee
2 files changed
+148
-150
target/riscv/monitor.c
+148
@@ -19,6 +19,8 @@
19
*/
20
21
#include "qemu/osdep.h"
22
+#include "qemu/ctype.h"
23
+#include "qemu/qemu-print.h"
24
#include "cpu.h"
25
#include "cpu_bits.h"
26
#include "monitor/monitor.h"
@@ -241,3 +243,149 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
243
244
mem_info_svxx(mon, env);
245
}
246
+
247
+/*
248
+ * We have way too many potential CSRs and regs being added
249
+ * regularly to register them in a static array.
250
+ *
251
+ * Declare an empty array instead, making get_monitor_def() use
252
+ * the target_get_monitor_def() API directly.
253
+ */
254
+const MonitorDef monitor_defs[] = { { } };
255
+const MonitorDef *target_monitor_defs(void)
256
+{
257
+ return monitor_defs;
258
+}
259
+
260
+static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
261
+ target_ulong *val, bool is_gprh)
262
+{
263
+ const char * const *reg_names;
264
+ target_ulong *vals;
265
+
266
+ if (is_gprh) {
267
+ reg_names = riscv_int_regnamesh;
268
+ vals = env->gprh;
269
+ } else {
270
+ reg_names = riscv_int_regnames;
271
+ vals = env->gpr;
272
+ }
273
+
274
+ for (int i = 0; i < 32; i++) {
275
+ g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2);
276
+
277
+ g_assert(reg_name[0]);
278
+ g_assert(reg_name[1]);
279
+
280
+ if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
281
+ g_ascii_strcasecmp(reg_name[1], name) == 0) {
282
+ *val = vals[i];
283
+ return true;
284
+ }
285
+ }
286
+
287
+ return false;
288
+}
289
+
290
+static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val)
291
+{
292
+ if (qemu_tolower(name[0]) != 'f') {
293
+ return false;
294
+ }
295
+
296
+ for (int i = 0; i < 32; i++) {
297
+ g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2);
298
+
299
+ g_assert(reg_name[0]);
300
+ g_assert(reg_name[1]);
301
+
302
+ if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
303
+ g_ascii_strcasecmp(reg_name[1], name) == 0) {
304
+ *val = env->fpr[i];
305
+ return true;
306
+ }
307
+ }
308
+
309
+ return false;
310
+}
311
+
312
+static bool reg_is_vreg(const char *name)
313
+{
314
+ if (qemu_tolower(name[0]) != 'v' || strlen(name) > 3) {
315
+ return false;
316
+ }
317
+
318
+ for (int i = 0; i < 32; i++) {
319
+ if (strcasecmp(name, riscv_rvv_regnames[i]) == 0) {
320
+ return true;
321
+ }
322
+ }
323
+
324
+ return false;
325
+}
326
+
327
+int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval)
328
+{
329
+ CPURISCVState *env = &RISCV_CPU(cs)->env;
330
+ target_ulong val = 0;
331
+ uint64_t val64 = 0;
332
+ int i;
333
+
334
+ if (reg_is_ulong_integer(env, name, &val, false) ||
335
+ reg_is_ulong_integer(env, name, &val, true)) {
336
+ *pval = val;
337
+ return 0;
338
+ }
339
+
340
+ if (reg_is_u64_fpu(env, name, &val64)) {
341
+ *pval = val64;
342
+ return 0;
343
+ }
344
+
345
+ if (reg_is_vreg(name)) {
346
+ if (!riscv_cpu_cfg(env)->ext_zve32x) {
347
+ return -EINVAL;
348
+ }
349
+
350
+ qemu_printf("Unable to print the value of vector "
351
+ "vreg '%s' from this API\n", name);
352
+
353
+ /*
354
+ * We're returning 0 because returning -EINVAL triggers
355
+ * an 'unknown register' message in exp_unary() later,
356
+ * which feels ankward after our own error message.
357
+ */
358
+ *pval = 0;
359
+ return 0;
360
+ }
361
+
362
+ for (i = 0; i < ARRAY_SIZE(csr_ops); i++) {
363
+ RISCVException res;
364
+ int csrno = i;
365
+
366
+ /*
367
+ * Early skip when possible since we're going
368
+ * through a lot of NULL entries.
369
+ */
370
+ if (csr_ops[csrno].predicate == NULL) {
371
+ continue;
372
+ }
373
+
374
+ if (strcasecmp(csr_ops[csrno].name, name) != 0) {
375
+ continue;
376
+ }
377
+
378
+ res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
379
+
380
+ /*
381
+ * Rely on the smode, hmode, etc, predicates within csr.c
382
+ * to do the filtering of the registers that are present.
383
+ */
384
+ if (res == RISCV_EXCP_NONE) {
385
+ *pval = val;
386
+ return 0;
387
+ }
388
+ }
389
+
390
+ return -EINVAL;
391
+}
target/riscv/riscv-qmp-cmds.c
-150
@@ -31,10 +31,6 @@
31
#include "qapi/qobject-input-visitor.h"
32
#include "qapi/visitor.h"
33
#include "qom/qom-qobject.h"
34
-#include "qemu/ctype.h"
35
-#include "qemu/qemu-print.h"
36
-#include "monitor/hmp.h"
37
-#include "monitor/hmp-target.h"
34
#include "system/kvm.h"
35
#include "system/tcg.h"
36
#include "cpu-qom.h"
@@ -244,149 +240,3 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
240
241
return expansion_info;
242
}
247
-
248
-/*
249
- * We have way too many potential CSRs and regs being added
250
- * regularly to register them in a static array.
251
- *
252
- * Declare an empty array instead, making get_monitor_def() use
253
- * the target_get_monitor_def() API directly.
254
- */
255
-const MonitorDef monitor_defs[] = { { } };
256
-const MonitorDef *target_monitor_defs(void)
257
-{
258
- return monitor_defs;
259
-}
260
-
261
-static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
262
- target_ulong *val, bool is_gprh)
263
-{
264
- const char * const *reg_names;
265
- target_ulong *vals;
266
-
267
- if (is_gprh) {
268
- reg_names = riscv_int_regnamesh;
269
- vals = env->gprh;
270
- } else {
271
- reg_names = riscv_int_regnames;
272
- vals = env->gpr;
273
- }
274
-
275
- for (int i = 0; i < 32; i++) {
276
- g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2);
277
-
278
- g_assert(reg_name[0]);
279
- g_assert(reg_name[1]);
280
-
281
- if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
282
- g_ascii_strcasecmp(reg_name[1], name) == 0) {
283
- *val = vals[i];
284
- return true;
285
- }
286
- }
287
-
288
- return false;
289
-}
290
-
291
-static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val)
292
-{
293
- if (qemu_tolower(name[0]) != 'f') {
294
- return false;
295
- }
296
-
297
- for (int i = 0; i < 32; i++) {
298
- g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2);
299
-
300
- g_assert(reg_name[0]);
301
- g_assert(reg_name[1]);
302
-
303
- if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
304
- g_ascii_strcasecmp(reg_name[1], name) == 0) {
305
- *val = env->fpr[i];
306
- return true;
307
- }
308
- }
309
-
310
- return false;
311
-}
312
-
313
-static bool reg_is_vreg(const char *name)
314
-{
315
- if (qemu_tolower(name[0]) != 'v' || strlen(name) > 3) {
316
- return false;
317
- }
318
-
319
- for (int i = 0; i < 32; i++) {
320
- if (strcasecmp(name, riscv_rvv_regnames[i]) == 0) {
321
- return true;
322
- }
323
- }
324
-
325
- return false;
326
-}
327
-
328
-int target_get_monitor_def(CPUState *cs, const char *name, uint64_t *pval)
329
-{
330
- CPURISCVState *env = &RISCV_CPU(cs)->env;
331
- target_ulong val = 0;
332
- uint64_t val64 = 0;
333
- int i;
334
-
335
- if (reg_is_ulong_integer(env, name, &val, false) ||
336
- reg_is_ulong_integer(env, name, &val, true)) {
337
- *pval = val;
338
- return 0;
339
- }
340
-
341
- if (reg_is_u64_fpu(env, name, &val64)) {
342
- *pval = val64;
343
- return 0;
344
- }
345
-
346
- if (reg_is_vreg(name)) {
347
- if (!riscv_cpu_cfg(env)->ext_zve32x) {
348
- return -EINVAL;
349
- }
350
-
351
- qemu_printf("Unable to print the value of vector "
352
- "vreg '%s' from this API\n", name);
353
-
354
- /*
355
- * We're returning 0 because returning -EINVAL triggers
356
- * an 'unknown register' message in exp_unary() later,
357
- * which feels ankward after our own error message.
358
- */
359
- *pval = 0;
360
- return 0;
361
- }
362
-
363
- for (i = 0; i < ARRAY_SIZE(csr_ops); i++) {
364
- RISCVException res;
365
- int csrno = i;
366
-
367
- /*
368
- * Early skip when possible since we're going
369
- * through a lot of NULL entries.
370
- */
371
- if (csr_ops[csrno].predicate == NULL) {
372
- continue;
373
- }
374
-
375
- if (strcasecmp(csr_ops[csrno].name, name) != 0) {
376
- continue;
377
- }
378
-
379
- res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
380
-
381
- /*
382
- * Rely on the smode, hmode, etc, predicates within csr.c
383
- * to do the filtering of the registers that are present.
384
- */
385
- if (res == RISCV_EXCP_NONE) {
386
- *pval = val;
387
- return 0;
388
- }
389
- }
390
-
391
- return -EINVAL;
392
-}