QEMU-Arm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers
@ 2026-09-11 12:27 Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 01/10] hmp: don't crash on invalid register Marc-André Lureau
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Hi,

HMP monitor supports printing $register expression. The lookup
was done via GDB stub registers, and supplementary MonitorDef
HMP-specific tables.

Migrate HMP registers to use the GDB infrastructure and remove the
legacy HMP MonitorDef. Use a "qemu-debug" register group, as they are
aliases or synthetic registers, but gdb doesn't seem to care.

Known behavioural changes on RISC-V: CSR lookup is now case-sensitive
and vector registers now report "unkown register" instead of a
target-specific message ("Unable to print the value of vector vreg 'v0'
from this API")

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
Marc-André Lureau (10):
      hmp: don't crash on invalid register
      gdbstub: fix next register base after register gaps
      gdbstub: set feature->base_reg for dynamic features
      target/i386: expose segment limits via GDB
      monitor/hmp: add CPUClass::get_pc fallback for HMP $pc
      target/m68k: expose system registers via GDB
      target/sparc64: expose system registers via GDB
      target/riscv: bypass smstateen check in debugger mode
      target/riscv: expose register aliases via GDB
      monitor/hmp: remove legacy MonitorDef infrastructure

 configs/targets/i386-softmmu.mak          |   2 +-
 configs/targets/m68k-softmmu.mak          |   2 +-
 configs/targets/riscv32-linux-user.mak    |   2 +-
 configs/targets/riscv32-softmmu.mak       |   2 +-
 configs/targets/riscv64-bsd-user.mak      |   2 +-
 configs/targets/riscv64-linux-user.mak    |   2 +-
 configs/targets/riscv64-softmmu.mak       |   2 +-
 configs/targets/sparc64-softmmu.mak       |   2 +-
 configs/targets/x86_64-softmmu.mak        |   2 +-
 gdbstub/gdb-xml/i386-segments.xml         |  14 +++
 gdbstub/gdb-xml/m68k-system.xml           |  32 +++++++
 gdbstub/gdb-xml/riscv-32bit-alias.xml     | 105 ++++++++++++++++++++++
 gdbstub/gdb-xml/riscv-32bit-fpu-alias.xml |  40 +++++++++
 gdbstub/gdb-xml/riscv-64bit-alias.xml     | 105 ++++++++++++++++++++++
 gdbstub/gdb-xml/riscv-64bit-fpu-alias.xml |  46 ++++++++++
 gdbstub/gdb-xml/sparc64-system.xml        |  22 +++++
 gdbstub/gdbstub.c                         |  14 +--
 include/hw/core/cpu.h                     |   2 +-
 include/hw/core/sysemu-cpu-ops.h          |  16 ----
 include/monitor/hmp.h                     |   6 --
 include/qemu/typedefs.h                   |   1 -
 monitor/hmp.c                             |  52 ++---------
 target/arm/gdbstub.c                      |   8 +-
 target/arm/gdbstub64.c                    |  10 ++-
 target/i386/cpu.c                         |  32 -------
 target/i386/gdbstub.c                     |  24 +++++
 target/m68k/cpu.c                         |  22 -----
 target/m68k/helper.c                      |  47 ++++++++++
 target/ppc/gdbstub.c                      |   2 +-
 target/riscv/cpu.c                        |   1 -
 target/riscv/gdbstub.c                    |  52 ++++++++++-
 target/riscv/internals.h                  |   3 -
 target/riscv/monitor.c                    | 140 ------------------------------
 target/riscv/tcg/csr.c                    |   3 +-
 target/sparc/cpu.c                        |  19 ----
 target/sparc/gdbstub.c                    |  38 ++++++++
 target/xtensa/cpu.c                       |   2 +-
 37 files changed, 562 insertions(+), 314 deletions(-)
---
base-commit: 209b2afaface001c7d4d981e38f186afe7b24a50
change-id: 20260910-query-reg-80cd59cf4707

Best regards,
--  
Marc-André Lureau <marcandre.lureau@redhat.com>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/10] hmp: don't crash on invalid register
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 02/10] gdbstub: fix next register base after register gaps Marc-André Lureau
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

When printing an invalid/denied register, QEMU crashes with:
ERROR:include/qemu/bswap.h:488:ldn_le_p: code should not be reached

(ex: "p $sireg" when siselect=0 on riscv)

Return false instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 monitor/hmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/monitor/hmp.c b/monitor/hmp.c
index 488ec23937df..10e19e417aba 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -424,7 +424,7 @@ static bool gdb_get_register(MonitorHMP *hmp, int64_t *pval, const char *name)
 
         buf = g_byte_array_new();
         reg_size = gdb_read_register(cs, buf, reg->gdb_reg);
-        if (reg_size > sizeof(*pval)) {
+        if (reg_size == 0 || reg_size > sizeof(*pval)) {
             return false;
         }
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/10] gdbstub: fix next register base after register gaps
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 01/10] hmp: don't crash on invalid register Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 15:29   ` Alex Bennée
  2026-09-11 12:27 ` [PATCH 03/10] gdbstub: set feature->base_reg for dynamic features Marc-André Lureau
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Commit b3e88abb200c ("gdbstub: Consider GDBFeature::base_reg in
gdb_register_coprocessor()") identified that register numbers may
have gaps. We also need to adjust the next base_reg correctly
to avoid overlapping registers. Rename the field to be more
explicit about its usage.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 gdbstub/gdbstub.c      | 13 ++++++-------
 include/hw/core/cpu.h  |  2 +-
 target/arm/gdbstub.c   |  8 +++++---
 target/arm/gdbstub64.c | 10 ++++++----
 target/ppc/gdbstub.c   |  2 +-
 target/riscv/gdbstub.c |  9 ++++++---
 target/xtensa/cpu.c    |  2 +-
 7 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 0a328b0dd488..0ce871d74929 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -605,13 +605,13 @@ void gdb_init_cpu(CPUState *cpu)
         gdb_register_feature(cpu, 0,
                              cc->gdb_read_register, cc->gdb_write_register,
                              feature);
-        cpu->gdb_num_regs = cpu->gdb_num_g_regs = feature->num_regs;
+        cpu->gdb_next_base_reg = cpu->gdb_num_g_regs = feature->num_regs;
     } else {
-        cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
+        cpu->gdb_next_base_reg = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
     }
 
     trace_gdbxml_init_cpu(object_get_typename(OBJECT(cpu)), cpu->cpu_index,
-                          cpu->gdb_num_regs, cpu->gdb_num_g_regs,
+                          cpu->gdb_next_base_reg, cpu->gdb_num_g_regs,
                           cc->gdb_num_core_regs);
 }
 
@@ -621,7 +621,7 @@ void gdb_register_coprocessor(CPUState *cpu,
 {
     GDBRegisterState *s;
     guint i;
-    int base_reg = cpu->gdb_num_regs;
+    int base_reg = cpu->gdb_next_base_reg;
 
     for (i = 0; i < cpu->gdb_regs->len; i++) {
         /* Check for duplicates.  */
@@ -639,7 +639,7 @@ void gdb_register_coprocessor(CPUState *cpu,
     gdb_register_feature(cpu, base_reg, get_reg, set_reg, feature);
 
     /* Add to end of list.  */
-    cpu->gdb_num_regs += feature->num_regs;
+    cpu->gdb_next_base_reg = base_reg + feature->num_regs;
 }
 
 void gdb_unregister_coprocessor_all(CPUState *cpu)
@@ -651,7 +651,7 @@ void gdb_unregister_coprocessor_all(CPUState *cpu)
     g_array_free(cpu->gdb_regs, true);
 
     cpu->gdb_regs = NULL;
-    cpu->gdb_num_regs = 0;
+    cpu->gdb_next_base_reg = 0;
     cpu->gdb_num_g_regs = 0;
 }
 
@@ -2522,4 +2522,3 @@ void gdb_create_default_process(GDBState *s)
     process->attached = false;
     process->target_xml = NULL;
 }
-
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 328e30045ce1..02212f555c2e 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -521,7 +521,7 @@ struct CPUState {
     struct CPUJumpCache *tb_jmp_cache;
 
     GArray *gdb_regs;
-    int gdb_num_regs;
+    int gdb_next_base_reg;
     int gdb_num_g_regs;
     QTAILQ_ENTRY(CPUState) node;
 
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index d6e29c4cf467..e5cbe4d951ef 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -555,19 +555,21 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
                                  gdb_find_static_feature("arm-m-profile-mve.xml"));
     }
+    GDBFeature *feature =
+        arm_gen_dynamic_sysreg_feature(cs, cs->gdb_next_base_reg);
     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
-                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs));
+                             feature);
 
 #ifdef CONFIG_TCG
     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
         gdb_register_coprocessor(cs,
             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
-            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs));
+            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_next_base_reg));
 #ifndef CONFIG_USER_ONLY
         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
             gdb_register_coprocessor(cs,
                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
-                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs));
+                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_next_base_reg));
         }
 #endif
     }
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 0c3e5b30bd6a..cf5b95b54641 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -885,7 +885,8 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
     CPUState *cs = CPU(cpu);
     if (isar_feature_aa64_sve(&cpu->isar) ||
         isar_feature_aa64_sme(&cpu->isar)) {
-        GDBFeature *feature = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs);
+        GDBFeature *feature =
+            arm_gen_dynamic_svereg_feature(cs, cs->gdb_next_base_reg);
         gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
                                  aarch64_gdb_set_sve_reg, feature);
     } else {
@@ -896,7 +897,7 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 
     if (isar_feature_aa64_sme(&cpu->isar)) {
         GDBFeature *sme_feature =
-            arm_gen_dynamic_smereg_feature(cs, cs->gdb_num_regs);
+            arm_gen_dynamic_smereg_feature(cs, cs->gdb_next_base_reg);
         gdb_register_coprocessor(cs, aarch64_gdb_get_sme_reg,
                                  aarch64_gdb_set_sme_reg, sme_feature);
         if (isar_feature_aa64_sme2(&cpu->isar)) {
@@ -927,7 +928,8 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
 #endif
 
     /* All AArch64 CPUs have at least TPIDR */
+    GDBFeature *tls_feature =
+        arm_gen_dynamic_tls_feature(cs, cs->gdb_next_base_reg);
     gdb_register_coprocessor(cs, aarch64_gdb_get_tls_reg,
-                             aarch64_gdb_set_tls_reg,
-                             arm_gen_dynamic_tls_feature(cs, cs->gdb_num_regs));
+                             aarch64_gdb_set_tls_reg, tls_feature);
 }
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 4d622c5cad59..ec25c541c685 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -206,7 +206,7 @@ static void gdb_gen_spr_feature(CPUState *cs)
 
     gdb_feature_builder_init(&builder, &pcc->gdb_spr,
                              "org.qemu.power.spr", "power-spr.xml",
-                             cs->gdb_num_regs);
+                             cs->gdb_next_base_reg);
 
     for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
         ppc_spr_t *spr = &env->spr_cb[i];
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 9abbf5bcdf0e..f279f4ab2461 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -348,9 +348,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
                                  gdb_find_static_feature("riscv-32bit-fpu.xml"));
     }
     if (cpu->cfg.ext_zve32x) {
+        GDBFeature *feature =
+            ricsv_gen_dynamic_vector_feature(cs, cs->gdb_next_base_reg);
         gdb_register_coprocessor(cs, riscv_gdb_get_vector,
-                                 riscv_gdb_set_vector,
-                                 ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs));
+                                 riscv_gdb_set_vector, feature);
     }
 
 #ifdef CONFIG_TCG
@@ -373,8 +374,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
     }
 
     if (cpu->cfg.ext_zicsr) {
+        GDBFeature *feature =
+            riscv_gen_dynamic_csr_feature(cs, cs->gdb_next_base_reg);
         gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
-                                 riscv_gen_dynamic_csr_feature(cs, cs->gdb_num_regs));
+                                 feature);
     }
 #endif
 }
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 7c25b9ab707a..48863a1859d4 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -263,7 +263,7 @@ static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
         return;
     }
 
-    cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs;
+    cs->gdb_next_base_reg = xcc->config->gdb_regmap.num_regs;
 
     qemu_init_vcpu(cs);
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/10] gdbstub: set feature->base_reg for dynamic features
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 01/10] hmp: don't crash on invalid register Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 02/10] gdbstub: fix next register base after register gaps Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 04/10] target/i386: expose segment limits via GDB Marc-André Lureau
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

gdb_feature_builder_end() never propagated builder->base_reg into
feature->base_reg, leaving it at 0 for all dynamically-built features.
This made the trace log at gdb_get_register_list() report an incorrect
base_reg for dynamic features.

GDBRegisterState::base_reg was correctly set, so this doesn't fix
an actual issue.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 gdbstub/gdbstub.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index 0ce871d74929..912e31b66744 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -476,6 +476,7 @@ void gdb_feature_builder_end(const GDBFeatureBuilder *builder)
 
     g_ptr_array_free(builder->xml, TRUE);
 
+    builder->feature->base_reg = builder->base_reg;
     builder->feature->num_regs = builder->regs->len;
     builder->feature->regs = (void *)g_ptr_array_free(builder->regs, FALSE);
     trace_gdbxml_feature_builder_header(builder->feature->name,

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/10] target/i386: expose segment limits via GDB
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (2 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 03/10] gdbstub: set feature->base_reg for dynamic features Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 05/10] monitor/hmp: add CPUClass::get_pc fallback for HMP $pc Marc-André Lureau
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Add an i386-segments.xml GDB feature that exposes the six segment
limit registers (cs, ds, es, ss, fs, gs) as read-only system
registers through the GDB coprocessor interface. This makes them
accessible to both GDB and HMP without relying on the legacy
MonitorDef table, which will be removed in a subsequent commit.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 configs/targets/i386-softmmu.mak   |  2 +-
 configs/targets/x86_64-softmmu.mak |  2 +-
 gdbstub/gdb-xml/i386-segments.xml  | 14 ++++++++++++++
 target/i386/gdbstub.c              | 24 ++++++++++++++++++++++++
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
index 38a8f85201f9..89cdaa072ef7 100644
--- a/configs/targets/i386-softmmu.mak
+++ b/configs/targets/i386-softmmu.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=i386
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
-TARGET_XML_FILES= i386-32bit.xml
+TARGET_XML_FILES= i386-32bit.xml i386-segments.xml
 TARGET_LONG_BITS=32
 TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
diff --git a/configs/targets/x86_64-softmmu.mak b/configs/targets/x86_64-softmmu.mak
index c7f8746b4f58..0af699971de0 100644
--- a/configs/targets/x86_64-softmmu.mak
+++ b/configs/targets/x86_64-softmmu.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=x86_64
 TARGET_BASE_ARCH=i386
 TARGET_KVM_HAVE_GUEST_DEBUG=y
 TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
-TARGET_XML_FILES= i386-64bit.xml i386-64bit-apx.xml
+TARGET_XML_FILES= i386-64bit.xml i386-64bit-apx.xml i386-segments.xml
 TARGET_LONG_BITS=64
 TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
diff --git a/gdbstub/gdb-xml/i386-segments.xml b/gdbstub/gdb-xml/i386-segments.xml
new file mode 100644
index 000000000000..6fbf3f91957e
--- /dev/null
+++ b/gdbstub/gdb-xml/i386-segments.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<!-- Segment-cache values are read-only; writes are ignored. -->
+<feature name="org.qemu.gdb.i386.segments">
+  <reg name="cs.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+  <reg name="ds.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+  <reg name="es.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+  <reg name="ss.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+  <reg name="fs.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+  <reg name="gs.limit" bitsize="32" type="uint32" group="qemu-debug" save-restore="no"/>
+</feature>
diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c
index 5c5fa7272163..2729b0f5bc1e 100644
--- a/target/i386/gdbstub.c
+++ b/target/i386/gdbstub.c
@@ -493,6 +493,25 @@ static int i386_cpu_gdb_set_egprs(CPUState *cs, uint8_t *mem_buf, int n)
 }
 #endif
 
+#ifndef CONFIG_USER_ONLY
+static int x86_gdb_read_segment_limit(CPUState *cs, GByteArray *buf, int n)
+{
+    CPUX86State *env = cpu_env(cs);
+    static const int segments[] = { R_CS, R_DS, R_ES, R_SS, R_FS, R_GS };
+
+    if (n < 0 || n >= ARRAY_SIZE(segments)) {
+        return 0;
+    }
+    return gdb_get_reg32(buf, env->segs[segments[n]].limit);
+}
+
+static int x86_gdb_write_segment_limit(CPUState *cs, uint8_t *buf, int n)
+{
+    /* Segment caches are exposed for inspection only. Ignore writes. */
+    return 4;
+}
+#endif
+
 void x86_cpu_gdb_init(CPUState *cs)
 {
 #ifdef TARGET_X86_64
@@ -514,4 +533,9 @@ void x86_cpu_gdb_init(CPUState *cs)
                              gdb_find_static_feature("i386-32bit-linux.xml"));
 #endif
 #endif
+#ifndef CONFIG_USER_ONLY
+    gdb_register_coprocessor(cs, x86_gdb_read_segment_limit,
+                             x86_gdb_write_segment_limit,
+                             gdb_find_static_feature("i386-segments.xml"));
+#endif
 }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/10] monitor/hmp: add CPUClass::get_pc fallback for HMP $pc
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (3 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 04/10] target/i386: expose segment limits via GDB Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 06/10] target/m68k: expose system registers via GDB Marc-André Lureau
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Some targets, including x86, have no GDB register named "pc" (x86
uses eip/rip). When the GDB register lookup fails for "$pc" in
HMP expressions, fall back to CPUClass::get_pc so that "p $pc",
"x $pc" etc. work without relying on the legacy MonitorDef table.

This prepares for the eventual removal of MonitorDef while making
$pc available immediately for all targets that implement get_pc.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 monitor/hmp.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/monitor/hmp.c b/monitor/hmp.c
index 10e19e417aba..0a74247ca66a 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -402,7 +402,7 @@ void hmp_help_cmd(MonitorHMP *mon, const char *name)
  * Set @pval to the value in the register identified by @name.
  * return %true if the register is found, %false otherwise.
  */
-static bool gdb_get_register(MonitorHMP *hmp, int64_t *pval, const char *name)
+static bool get_register(MonitorHMP *hmp, int64_t *pval, const char *name)
 {
     g_autoptr(GArray) regs = NULL;
     CPUState *cs = monitor_hmp_get_cpu(hmp);
@@ -435,6 +435,10 @@ static bool gdb_get_register(MonitorHMP *hmp, int64_t *pval, const char *name)
         }
         return true;
     }
+    if (!strcmp(name, "pc") && cs->cc->get_pc) {
+        *pval = cs->cc->get_pc(cs);
+        return true;
+    }
     return false;
 }
 
@@ -526,7 +530,7 @@ static int64_t expr_unary(MonitorHMP *mon)
                 pch++;
             }
             *q = 0;
-            if (!gdb_get_register(mon, &reg, buf)
+            if (!get_register(mon, &reg, buf)
                 && get_monitor_def(mon, &reg, buf) < 0) {
                 expr_error(mon, "unknown register");
             }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/10] target/m68k: expose system registers via GDB
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (4 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 05/10] monitor/hmp: add CPUClass::get_pc fallback for HMP $pc Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 07/10] target/sparc64: " Marc-André Lureau
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Add an m68k-system.xml GDB feature that exposes supervisor stack
pointers (ssp, usp, isp), function code registers (sfc, dfc), MMU
registers (urp, srp, dttr0/1, ittr0/1, mmusr) as read-only system
registers through the GDB coprocessor interface.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 configs/targets/m68k-softmmu.mak |  2 +-
 gdbstub/gdb-xml/m68k-system.xml  | 32 +++++++++++++++++++++++++++
 target/m68k/helper.c             | 47 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/configs/targets/m68k-softmmu.mak b/configs/targets/m68k-softmmu.mak
index 0bc889f326e3..f3ac9b74c862 100644
--- a/configs/targets/m68k-softmmu.mak
+++ b/configs/targets/m68k-softmmu.mak
@@ -1,4 +1,4 @@
 TARGET_ARCH=m68k
 TARGET_BIG_ENDIAN=y
-TARGET_XML_FILES= cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml
+TARGET_XML_FILES= cf-core.xml cf-fp.xml m68k-core.xml m68k-fp.xml m68k-system.xml
 TARGET_LONG_BITS=32
diff --git a/gdbstub/gdb-xml/m68k-system.xml b/gdbstub/gdb-xml/m68k-system.xml
new file mode 100644
index 000000000000..0a91be0edc00
--- /dev/null
+++ b/gdbstub/gdb-xml/m68k-system.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<!-- System-register values are read-only; writes are ignored. -->
+<feature name="org.qemu.gdb.m68k.system">
+  <reg name="ssp" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="usp" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="isp" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="sfc" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="dfc" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="urp" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="srp" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="dttr0" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="dttr1" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="ittr0" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="ittr1" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="mmusr" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+</feature>
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index 5f91d206f596..f2615d5bcfb8 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -123,6 +123,48 @@ static int m68k_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
     return 0;
 }
 
+#ifndef CONFIG_USER_ONLY
+static int m68k_gdb_read_system_register(CPUState *cs, GByteArray *buf, int n)
+{
+    CPUM68KState *env = cpu_env(cs);
+    static const int stacks[] = { M68K_SSP, M68K_USP, M68K_ISP };
+
+    if (n >= 0 && n < ARRAY_SIZE(stacks)) {
+        int sp = stacks[n];
+
+        return gdb_get_reg32(buf, env->sp[sp]);
+    }
+    switch (n) {
+    case 3:
+        return gdb_get_reg32(buf, env->sfc);
+    case 4:
+        return gdb_get_reg32(buf, env->dfc);
+    case 5:
+        return gdb_get_reg32(buf, env->mmu.urp);
+    case 6:
+        return gdb_get_reg32(buf, env->mmu.srp);
+    case 7:
+        return gdb_get_reg32(buf, env->mmu.ttr[M68K_DTTR0]);
+    case 8:
+        return gdb_get_reg32(buf, env->mmu.ttr[M68K_DTTR1]);
+    case 9:
+        return gdb_get_reg32(buf, env->mmu.ttr[M68K_ITTR0]);
+    case 10:
+        return gdb_get_reg32(buf, env->mmu.ttr[M68K_ITTR1]);
+    case 11:
+        return gdb_get_reg32(buf, env->mmu.mmusr);
+    default:
+        return 0;
+    }
+}
+
+static int m68k_gdb_write_system_register(CPUState *cs, uint8_t *buf, int n)
+{
+    /* These registers are exposed for inspection only. Ignore writes. */
+    return 4;
+}
+#endif
+
 void m68k_cpu_init_gdb(M68kCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
@@ -135,6 +177,11 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
         gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, m68k_fpu_gdb_set_reg,
                                  gdb_find_static_feature("m68k-fp.xml"));
     }
+#ifndef CONFIG_USER_ONLY
+    gdb_register_coprocessor(cs, m68k_gdb_read_system_register,
+                             m68k_gdb_write_system_register,
+                             gdb_find_static_feature("m68k-system.xml"));
+#endif
     /* TODO: Add [E]MAC registers.  */
 }
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/10] target/sparc64: expose system registers via GDB
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (5 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 06/10] target/m68k: expose system registers via GDB Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 08/10] target/riscv: bypass smstateen check in debugger mode Marc-André Lureau
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Add a sparc64-system.xml GDB feature that exposes asi, pstate,
cansave, canrestore, otherwin, wstate, and cleanwin as read-only
system registers through the GDB coprocessor interface.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 configs/targets/sparc64-softmmu.mak |  2 +-
 gdbstub/gdb-xml/sparc64-system.xml  | 22 +++++++++++++++++++++
 target/sparc/gdbstub.c              | 38 +++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/configs/targets/sparc64-softmmu.mak b/configs/targets/sparc64-softmmu.mak
index 4e621fb8e39e..7f2789136653 100644
--- a/configs/targets/sparc64-softmmu.mak
+++ b/configs/targets/sparc64-softmmu.mak
@@ -1,7 +1,7 @@
 TARGET_ARCH=sparc64
 TARGET_BASE_ARCH=sparc
 TARGET_BIG_ENDIAN=y
-TARGET_XML_FILES=sparc64-cpu.xml sparc64-fpu.xml sparc64-cp0.xml
+TARGET_XML_FILES=sparc64-cpu.xml sparc64-fpu.xml sparc64-cp0.xml sparc64-system.xml
 TARGET_LONG_BITS=64
 TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
 TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y
diff --git a/gdbstub/gdb-xml/sparc64-system.xml b/gdbstub/gdb-xml/sparc64-system.xml
new file mode 100644
index 000000000000..e00baedb467e
--- /dev/null
+++ b/gdbstub/gdb-xml/sparc64-system.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<!-- System-register values are read-only; writes are ignored. -->
+<feature name="org.qemu.gdb.sparc.system">
+  <reg name="asi" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="pstate" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="cansave" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="canrestore" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="otherwin" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="wstate" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+  <reg name="cleanwin" bitsize="32" type="uint32"
+       group="qemu-debug" save-restore="no"/>
+</feature>
diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c
index 2874ce1b3501..ca23a4a94532 100644
--- a/target/sparc/gdbstub.c
+++ b/target/sparc/gdbstub.c
@@ -266,6 +266,39 @@ static int sparc_cp0_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 #endif
 }
 
+#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+static int sparc64_gdb_read_system_register(CPUState *cs, GByteArray *buf,
+                                           int n)
+{
+    CPUSPARCState *env = cpu_env(cs);
+
+    switch (n) {
+    case 0:
+        return gdb_get_reg32(buf, env->asi);
+    case 1:
+        return gdb_get_reg32(buf, env->pstate);
+    case 2:
+        return gdb_get_reg32(buf, env->cansave);
+    case 3:
+        return gdb_get_reg32(buf, env->canrestore);
+    case 4:
+        return gdb_get_reg32(buf, env->otherwin);
+    case 5:
+        return gdb_get_reg32(buf, env->wstate);
+    case 6:
+        return gdb_get_reg32(buf, env->cleanwin);
+    default:
+        return 0;
+    }
+}
+
+static int sparc64_gdb_write_system_register(CPUState *cs, uint8_t *buf, int n)
+{
+    /* These registers are exposed for inspection only. Ignore writes. */
+    return 4;
+}
+#endif
+
 void sparc_cpu_register_gdb_regs(CPUState *cs)
 {
 #if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
@@ -282,5 +315,10 @@ void sparc_cpu_register_gdb_regs(CPUState *cs)
     gdb_register_coprocessor(cs, sparc_cp0_gdb_read_register,
                              sparc_cp0_gdb_write_register,
                              gdb_find_static_feature("sparc64-cp0.xml"));
+#ifndef CONFIG_USER_ONLY
+    gdb_register_coprocessor(cs, sparc64_gdb_read_system_register,
+                             sparc64_gdb_write_system_register,
+                             gdb_find_static_feature("sparc64-system.xml"));
+#endif
 #endif
 }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/10] target/riscv: bypass smstateen check in debugger mode
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (6 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 07/10] target/sparc64: " Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 09/10] target/riscv: expose register aliases via GDB Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 10/10] monitor/hmp: remove legacy MonitorDef infrastructure Marc-André Lureau
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Allow to read CSRs gated by Smstateen extension when env->debugger.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 target/riscv/tcg/csr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index bd4b6dc114bc..93a7f419f29f 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -53,7 +53,8 @@ RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit)
 {
     bool virt = env->virt_enabled;
 
-    if (env->priv == PRV_M || !riscv_cpu_cfg(env)->ext_smstateen) {
+    if (env->debugger || env->priv == PRV_M ||
+        !riscv_cpu_cfg(env)->ext_smstateen) {
         return RISCV_EXCP_NONE;
     }
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/10] target/riscv: expose register aliases via GDB
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (7 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 08/10] target/riscv: bypass smstateen check in debugger mode Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  2026-09-11 12:27 ` [PATCH 10/10] monitor/hmp: remove legacy MonitorDef infrastructure Marc-André Lureau
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

The core GDB XML uses ABI names (zero, ra, sp, fp, ft0, fs0, etc.)
but users also refer to registers by their numeric names (x0-x31,
f0-f31) and the s0 alias for fp. The legacy MonitorDef mechanism
supported both via split "x0/zero" name matching.

Register a feature that maps:
 - x0-x31 and s0 to the corresponding core integer registers
 - x0h-x31h and their ABI aliases (zeroh, rah, ...) to env->gprh[]
 - f0-f31 to the corresponding FPU registers (when FPU is present)

This preserves full HMP $register compatibility after the MonitorDef
removal.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 configs/targets/riscv32-linux-user.mak    |   2 +-
 configs/targets/riscv32-softmmu.mak       |   2 +-
 configs/targets/riscv64-bsd-user.mak      |   2 +-
 configs/targets/riscv64-linux-user.mak    |   2 +-
 configs/targets/riscv64-softmmu.mak       |   2 +-
 gdbstub/gdb-xml/riscv-32bit-alias.xml     | 105 ++++++++++++++++++++++++++++++
 gdbstub/gdb-xml/riscv-32bit-fpu-alias.xml |  40 ++++++++++++
 gdbstub/gdb-xml/riscv-64bit-alias.xml     | 105 ++++++++++++++++++++++++++++++
 gdbstub/gdb-xml/riscv-64bit-fpu-alias.xml |  46 +++++++++++++
 target/riscv/gdbstub.c                    |  43 ++++++++++++
 10 files changed, 344 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv32-linux-user.mak b/configs/targets/riscv32-linux-user.mak
index d88fdf5e1b2f..8ee14fa14383 100644
--- a/configs/targets/riscv32-linux-user.mak
+++ b/configs/targets/riscv32-linux-user.mak
@@ -1,7 +1,7 @@
 TARGET_ARCH=riscv32
 TARGET_BASE_ARCH=riscv
 TARGET_ABI_DIR=riscv
-TARGET_XML_FILES= riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-virtual.xml
+TARGET_XML_FILES= riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-virtual.xml riscv-32bit-alias.xml riscv-32bit-fpu-alias.xml riscv-64bit-fpu-alias.xml
 CONFIG_SEMIHOSTING=y
 CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
 TARGET_SYSTBL_ABI=32
diff --git a/configs/targets/riscv32-softmmu.mak b/configs/targets/riscv32-softmmu.mak
index 5d5016d00832..c717940344f0 100644
--- a/configs/targets/riscv32-softmmu.mak
+++ b/configs/targets/riscv32-softmmu.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=riscv32
 TARGET_BASE_ARCH=riscv
-TARGET_XML_FILES= riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-virtual.xml
+TARGET_XML_FILES= riscv-32bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-32bit-virtual.xml riscv-32bit-alias.xml riscv-32bit-fpu-alias.xml riscv-64bit-fpu-alias.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_LONG_BITS=32
diff --git a/configs/targets/riscv64-bsd-user.mak b/configs/targets/riscv64-bsd-user.mak
index 5b4e138099fc..1d37e018c871 100644
--- a/configs/targets/riscv64-bsd-user.mak
+++ b/configs/targets/riscv64-bsd-user.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_ABI_DIR=riscv
-TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml
+TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml riscv-64bit-alias.xml riscv-32bit-fpu-alias.xml riscv-64bit-fpu-alias.xml
 TARGET_LONG_BITS=64
 TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y
diff --git a/configs/targets/riscv64-linux-user.mak b/configs/targets/riscv64-linux-user.mak
index 35621520c560..564d15aaca8c 100644
--- a/configs/targets/riscv64-linux-user.mak
+++ b/configs/targets/riscv64-linux-user.mak
@@ -1,7 +1,7 @@
 TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_ABI_DIR=riscv
-TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml
+TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml riscv-64bit-alias.xml riscv-32bit-fpu-alias.xml riscv-64bit-fpu-alias.xml
 CONFIG_SEMIHOSTING=y
 CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
 TARGET_SYSTBL_ABI=64
diff --git a/configs/targets/riscv64-softmmu.mak b/configs/targets/riscv64-softmmu.mak
index a10dc03c04c8..28bfcdc575fb 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -1,7 +1,7 @@
 TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_KVM_HAVE_GUEST_DEBUG=y
-TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml riscv-32bit-cpu.xml riscv-32bit-virtual.xml
+TARGET_XML_FILES= riscv-64bit-cpu.xml riscv-32bit-fpu.xml riscv-64bit-fpu.xml riscv-64bit-virtual.xml riscv-32bit-cpu.xml riscv-32bit-virtual.xml riscv-32bit-alias.xml riscv-64bit-alias.xml riscv-32bit-fpu-alias.xml riscv-64bit-fpu-alias.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
 TARGET_LONG_BITS=64
diff --git a/gdbstub/gdb-xml/riscv-32bit-alias.xml b/gdbstub/gdb-xml/riscv-32bit-alias.xml
new file mode 100644
index 000000000000..a00a86ebdf95
--- /dev/null
+++ b/gdbstub/gdb-xml/riscv-32bit-alias.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.qemu.gdb.riscv.alias">
+  <reg name="x0" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x1" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x2" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x3" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x4" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x5" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x6" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x7" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x8" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x9" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x10" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x11" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x12" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x13" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x14" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x15" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x16" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x17" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x18" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x19" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x20" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x21" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x22" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x23" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x24" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x25" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x26" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x27" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x28" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x29" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x30" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x31" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s0" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x0h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="zeroh" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x1h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="rah" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x2h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="sph" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x3h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="gph" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x4h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="tph" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x5h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t0h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x6h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t1h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x7h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t2h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x8h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s0h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x9h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s1h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x10h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a0h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x11h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a1h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x12h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a2h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x13h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a3h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x14h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a4h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x15h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a5h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x16h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a6h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x17h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="a7h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x18h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s2h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x19h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s3h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x20h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s4h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x21h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s5h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x22h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s6h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x23h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s7h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x24h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s8h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x25h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s9h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x26h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s10h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x27h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="s11h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x28h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t3h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x29h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t4h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x30h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t5h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="x31h" bitsize="32" type="int" group="qemu-debug"/>
+  <reg name="t6h" bitsize="32" type="int" group="qemu-debug"/>
+</feature>
diff --git a/gdbstub/gdb-xml/riscv-32bit-fpu-alias.xml b/gdbstub/gdb-xml/riscv-32bit-fpu-alias.xml
new file mode 100644
index 000000000000..3935f72ea289
--- /dev/null
+++ b/gdbstub/gdb-xml/riscv-32bit-fpu-alias.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.qemu.gdb.riscv.fpu-alias">
+  <reg name="f0" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f1" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f2" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f3" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f4" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f5" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f6" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f7" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f8" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f9" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f10" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f11" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f12" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f13" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f14" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f15" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f16" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f17" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f18" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f19" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f20" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f21" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f22" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f23" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f24" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f25" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f26" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f27" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f28" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f29" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f30" bitsize="32" type="ieee_single" group="qemu-debug"/>
+  <reg name="f31" bitsize="32" type="ieee_single" group="qemu-debug"/>
+</feature>
diff --git a/gdbstub/gdb-xml/riscv-64bit-alias.xml b/gdbstub/gdb-xml/riscv-64bit-alias.xml
new file mode 100644
index 000000000000..28781b230226
--- /dev/null
+++ b/gdbstub/gdb-xml/riscv-64bit-alias.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.qemu.gdb.riscv.alias">
+  <reg name="x0" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x1" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x2" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x3" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x4" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x5" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x6" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x7" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x8" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x9" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x10" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x11" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x12" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x13" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x14" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x15" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x16" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x17" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x18" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x19" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x20" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x21" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x22" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x23" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x24" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x25" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x26" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x27" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x28" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x29" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x30" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x31" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s0" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x0h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="zeroh" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x1h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="rah" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x2h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="sph" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x3h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="gph" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x4h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="tph" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x5h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t0h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x6h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t1h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x7h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t2h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x8h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s0h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x9h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s1h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x10h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a0h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x11h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a1h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x12h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a2h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x13h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a3h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x14h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a4h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x15h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a5h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x16h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a6h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x17h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="a7h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x18h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s2h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x19h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s3h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x20h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s4h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x21h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s5h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x22h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s6h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x23h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s7h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x24h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s8h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x25h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s9h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x26h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s10h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x27h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="s11h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x28h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t3h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x29h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t4h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x30h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t5h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="x31h" bitsize="64" type="int" group="qemu-debug"/>
+  <reg name="t6h" bitsize="64" type="int" group="qemu-debug"/>
+</feature>
diff --git a/gdbstub/gdb-xml/riscv-64bit-fpu-alias.xml b/gdbstub/gdb-xml/riscv-64bit-fpu-alias.xml
new file mode 100644
index 000000000000..13e6b341a0f8
--- /dev/null
+++ b/gdbstub/gdb-xml/riscv-64bit-fpu-alias.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+  SPDX-License-Identifier: GPL-2.0-or-later
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.qemu.gdb.riscv.fpu-alias">
+
+  <union id="riscv_double">
+    <field name="float" type="ieee_single"/>
+    <field name="double" type="ieee_double"/>
+  </union>
+
+  <reg name="f0" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f1" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f2" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f3" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f4" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f5" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f6" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f7" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f8" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f9" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f10" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f11" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f12" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f13" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f14" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f15" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f16" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f17" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f18" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f19" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f20" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f21" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f22" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f23" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f24" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f25" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f26" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f27" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f28" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f29" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f30" bitsize="64" type="riscv_double" group="qemu-debug"/>
+  <reg name="f31" bitsize="64" type="riscv_double" group="qemu-debug"/>
+</feature>
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index f279f4ab2461..6694fa86fd84 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -336,16 +336,59 @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
     return &cpu->dyn_vreg_feature;
 }
 
+/* x0-x31, s0, then pairs of numeric and ABI high-half aliases. */
+static int riscv_gdb_get_alias(CPUState *cs, GByteArray *buf, int n)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    uint64_t val;
+
+    if (n < 33) {
+        return riscv_cpu_gdb_read_register(cs, buf, n == 32 ? 8 : n);
+    }
+
+    val = cpu->env.gprh[(n - 33) / 2];
+    if (riscv_cpu_is_32bit(cpu)) {
+        return gdb_get_reg32(buf, val);
+    }
+    return gdb_get_reg64(buf, val);
+}
+
+static int riscv_gdb_set_alias(CPUState *cs, uint8_t *buf, int n)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    const unsigned regsz = riscv_cpu_is_32bit(cpu) ? 4 : 8;
+
+    if (n < 33) {
+        return riscv_cpu_gdb_write_register(cs, buf, n == 32 ? 8 : n);
+    }
+
+    env->gprh[(n - 33) / 2] = ldn(env, buf, regsz);
+    return regsz;
+}
+
 void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
+
+    gdb_register_coprocessor(cs, riscv_gdb_get_alias, riscv_gdb_set_alias,
+                             gdb_find_static_feature(riscv_cpu_is_32bit(cpu) ?
+                                                     "riscv-32bit-alias.xml" :
+                                                     "riscv-64bit-alias.xml"));
+
     if (env->misa_ext & RVD) {
         gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
                                  gdb_find_static_feature("riscv-64bit-fpu.xml"));
+        gdb_register_coprocessor(cs, riscv_gdb_get_fpu,
+            riscv_gdb_set_fpu,
+            gdb_find_static_feature("riscv-64bit-fpu-alias.xml"));
     } else if (env->misa_ext & RVF) {
         gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
                                  gdb_find_static_feature("riscv-32bit-fpu.xml"));
+        gdb_register_coprocessor(cs, riscv_gdb_get_fpu,
+            riscv_gdb_set_fpu,
+            gdb_find_static_feature("riscv-32bit-fpu-alias.xml"));
     }
     if (cpu->cfg.ext_zve32x) {
         GDBFeature *feature =

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/10] monitor/hmp: remove legacy MonitorDef infrastructure
  2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
                   ` (8 preceding siblings ...)
  2026-09-11 12:27 ` [PATCH 09/10] target/riscv: expose register aliases via GDB Marc-André Lureau
@ 2026-09-11 12:27 ` Marc-André Lureau
  9 siblings, 0 replies; 12+ messages in thread
From: Marc-André Lureau @ 2026-09-11 12:27 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr. David Alan Gilbert, Alex Bennée,
	Philippe Mathieu-Daudé, Zhao Liu, Peter Maydell,
	Chinmay Rath, Nicholas Piggin, Glenn Miles, Harsh Prateek Bora,
	Palmer Dabbelt, Alistair Francis, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Max Filippov,
	qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini, Laurent Vivier,
	Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans, Marc-André Lureau

Now that all targets expose their system registers via GDB register
descriptions (i386 segment limits, m68k, sparc64) and $pc is handled by
the CPUClass::get_pc fallback, the legacy MonitorDef table and
SysemuCPUOps::monitor_get_register callback are no longer needed.

Remove MonitorDef struct, the per-target monitor_defs arrays (i386,
m68k, sparc64), riscv_monitor_get_register_legacy(), and the
get_monitor_def() fallback in expr_unary(). HMP $register expressions
now use gdb_get_register_list() exclusively.

For RISC-V, the legacy callback provided case-insensitive register name
matching (e.g. $Mstatus) and a special message for vector
registers ("Unable to print the value of vector vreg"). The GDB-based
lookup is case-sensitive (consistent with all other targets) and reports
oversized registers as "unknown register" instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/hw/core/sysemu-cpu-ops.h |  16 -----
 include/monitor/hmp.h            |   6 --
 include/qemu/typedefs.h          |   1 -
 monitor/hmp.c                    |  44 +-----------
 target/i386/cpu.c                |  32 ---------
 target/m68k/cpu.c                |  22 ------
 target/riscv/cpu.c               |   1 -
 target/riscv/internals.h         |   3 -
 target/riscv/monitor.c           | 140 ---------------------------------------
 target/sparc/cpu.c               |  19 ------
 10 files changed, 2 insertions(+), 282 deletions(-)

diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
index e56eea18b785..3a85aa47e243 100644
--- a/include/hw/core/sysemu-cpu-ops.h
+++ b/include/hw/core/sysemu-cpu-ops.h
@@ -101,22 +101,6 @@ typedef struct SysemuCPUOps {
      */
     bool (*internal_is_big_endian)(CPUState *cpu);
 
-    /**
-     * @monitor_get_register: Callback to fill @pval with register @name value.
-     *                        This field is legacy, use @gdb_core_xml_file
-     *                        to dump registers instead.
-     * Returns: 0 on success or negative errno on failure.
-     */
-    int (*monitor_get_register)(CPUState *cs, const char *name, int64_t *pval);
-
-#ifdef CONFIG_HMP
-    /**
-     * @monitor_defs: Array of MonitorDef entries. This field is legacy,
-     *                use @gdb_core_xml_file to dump registers instead.
-     */
-    const MonitorDef *monitor_defs;
-#endif
-
     /**
      * @legacy_vmsd: Legacy state for migration.
      *               Do not use in new targets, use #DeviceClass::vmsd instead.
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index ef53e87f7608..950dd931d452 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -31,12 +31,6 @@ MonitorHMP *monitor_cur_hmp(void);
         g_assert_not_reached(); \
     }
 
-struct MonitorDef {
-    const char *name;
-    int offset;
-    int64_t (*get_value)(MonitorHMP *hmp, const MonitorDef *md, int offset);
-};
-
 void monitor_new_hmp(const char *id, const char *chardev_id,
                      bool use_readline, Error **errp);
 
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 2344c92182ea..5580e1fc4aba 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -72,7 +72,6 @@ typedef struct MemoryRegionSection MemoryRegionSection;
 typedef struct MigrationIncomingState MigrationIncomingState;
 typedef struct MigrationState MigrationState;
 typedef struct Monitor Monitor;
-typedef struct MonitorDef MonitorDef;
 typedef struct MSIMessage MSIMessage;
 typedef struct NetClientState NetClientState;
 typedef struct NetFilterState NetFilterState;
diff --git a/monitor/hmp.c b/monitor/hmp.c
index 0a74247ca66a..f9621ce90aaf 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -24,8 +24,8 @@
 
 #include "qemu/osdep.h"
 #include <dirent.h>
+#include "hw/core/cpu.h"
 #include "hw/core/qdev.h"
-#include "hw/core/sysemu-cpu-ops.h"
 #include "monitor-internal.h"
 #include "monitor-hmp-internal.h"
 #include "monitor/hmp.h"
@@ -447,8 +447,6 @@ static bool get_register(MonitorHMP *hmp, int64_t *pval, const char *name)
 static const char *pch;
 static sigjmp_buf expr_env;
 
-static int get_monitor_def(MonitorHMP *mon, int64_t *pval, const char *name);
-
 static G_NORETURN G_GNUC_PRINTF(2, 3)
 void expr_error(MonitorHMP *mon, const char *fmt, ...)
 {
@@ -530,8 +528,7 @@ static int64_t expr_unary(MonitorHMP *mon)
                 pch++;
             }
             *q = 0;
-            if (!get_register(mon, &reg, buf)
-                && get_monitor_def(mon, &reg, buf) < 0) {
+            if (!get_register(mon, &reg, buf)) {
                 expr_error(mon, "unknown register");
             }
             n = reg;
@@ -1723,43 +1720,6 @@ void monitor_register_hmp_info_hrt(const char *name,
     g_assert_not_reached();
 }
 
-/*
- * Set @pval to the value in the register identified by @name.
- * return 0 if OK, -1 if not found
- */
-static int get_monitor_def(MonitorHMP *hmp, int64_t *pval, const char *name)
-{
-    CPUState *cs = monitor_hmp_get_cpu(hmp);
-    const MonitorDef *md = NULL;
-    void *ptr;
-
-    if (cs == NULL) {
-        return -1;
-    }
-    md = cs->cc->sysemu_ops->monitor_defs;
-    if (md == NULL) {
-        return -1;
-    }
-
-    for (; md->name != NULL; md++) {
-        if (hmp_compare_cmd(name, md->name)) {
-            if (md->get_value) {
-                *pval = md->get_value(hmp, md, md->offset);
-            } else {
-                CPUArchState *env = monitor_hmp_get_cpu_env(hmp);
-                ptr = (uint8_t *)env + md->offset;
-                *pval = *(int32_t *)ptr;
-            }
-            return 0;
-        }
-    }
-
-    if (!cs->cc->sysemu_ops->monitor_get_register) {
-        return -1;
-    }
-    return cs->cc->sysemu_ops->monitor_get_register(cs, name, pval);
-}
-
 int monitor_hmp_vprintf(MonitorHMP *hmp, const char *fmt, va_list ap)
 {
     g_autofree char *buf = g_strdup_vprintf(fmt, ap);
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b97f144aea5a..3218eae62854 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -42,7 +42,6 @@
 #include "exec/watchpoint.h"
 #ifndef CONFIG_USER_ONLY
 #include "confidential-guest.h"
-#include "monitor/hmp.h"
 #include "system/reset.h"
 #include "qapi/qapi-commands-machine.h"
 #include "system/address-spaces.h"
@@ -10852,34 +10851,6 @@ static const Property x86_cpu_properties[] = {
 
 #ifndef CONFIG_USER_ONLY
 
-#ifdef CONFIG_HMP
-static int64_t monitor_get_pc(MonitorHMP *hmp, const struct MonitorDef *md,
-                              int offset)
-{
-    CPUArchState *env = monitor_hmp_get_cpu_env(hmp);
-    int64_t ret = env->eip + env->segs[R_CS].base;
-
-    if (!(env->hflags & HF_CS64_MASK)) {
-        ret = (int32_t)ret;
-    }
-    return ret;
-}
-
-static const MonitorDef x86_monitor_defs[] = {
-#define SEG(name, seg) \
-    { name ".limit", offsetof(CPUX86State, segs[seg].limit) },
-    SEG("cs", R_CS)
-    SEG("ds", R_DS)
-    SEG("es", R_ES)
-    SEG("ss", R_SS)
-    SEG("fs", R_FS)
-    SEG("gs", R_GS)
-    { "pc", 0, monitor_get_pc, },
-    { NULL },
-#undef SEG
-};
-#endif
-
 #include "hw/core/sysemu-cpu-ops.h"
 
 static const struct SysemuCPUOps i386_sysemu_ops = {
@@ -10893,9 +10864,6 @@ static const struct SysemuCPUOps i386_sysemu_ops = {
     .write_elf64_note = x86_cpu_write_elf64_note,
     .write_elf32_qemunote = x86_cpu_write_elf32_qemunote,
     .write_elf64_qemunote = x86_cpu_write_elf64_qemunote,
-#ifdef CONFIG_HMP
-    .monitor_defs = x86_monitor_defs,
-#endif
     .legacy_vmsd = &vmstate_x86_cpu,
 };
 #endif
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 9b52ad5fc234..ad7303305848 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -25,7 +25,6 @@
 #include "disas/capstone.h"
 #ifndef CONFIG_USER_ONLY
 #include "migration/vmstate.h"
-#include "monitor/hmp.h"
 #endif
 
 #include "cpu.h"
@@ -666,32 +665,11 @@ static const VMStateDescription vmstate_m68k_cpu = {
     },
 };
 
-#ifdef CONFIG_HMP
-static const MonitorDef m68k_monitor_defs[] = {
-    { "ssp", offsetof(CPUM68KState, sp[0]) },
-    { "usp", offsetof(CPUM68KState, sp[1]) },
-    { "isp", offsetof(CPUM68KState, sp[2]) },
-    { "sfc", offsetof(CPUM68KState, sfc) },
-    { "dfc", offsetof(CPUM68KState, dfc) },
-    { "urp", offsetof(CPUM68KState, mmu.urp) },
-    { "srp", offsetof(CPUM68KState, mmu.srp) },
-    { "dttr0", offsetof(CPUM68KState, mmu.ttr[M68K_DTTR0]) },
-    { "dttr1", offsetof(CPUM68KState, mmu.ttr[M68K_DTTR1]) },
-    { "ittr0", offsetof(CPUM68KState, mmu.ttr[M68K_ITTR0]) },
-    { "ittr1", offsetof(CPUM68KState, mmu.ttr[M68K_ITTR1]) },
-    { "mmusr", offsetof(CPUM68KState, mmu.mmusr) },
-    { NULL },
-};
-#endif
-
 #include "hw/core/sysemu-cpu-ops.h"
 
 static const struct SysemuCPUOps m68k_sysemu_ops = {
     .has_work = m68k_cpu_has_work,
     .get_phys_addr_debug = m68k_cpu_get_phys_addr_debug,
-#ifdef CONFIG_HMP
-    .monitor_defs = m68k_monitor_defs,
-#endif
 };
 #endif /* !CONFIG_USER_ONLY */
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5fff9d745e9b..9a57873ea5d3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -3015,7 +3015,6 @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
     .legacy_vmsd = &vmstate_riscv_cpu,
 #ifdef CONFIG_TCG
     .translate_for_debug = riscv_cpu_translate_for_debug,
-    .monitor_get_register = riscv_monitor_get_register_legacy,
 #endif
 };
 #endif
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 5d84e4de960a..09aa2701197e 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -263,7 +263,4 @@ static inline int insn_len(uint16_t first_word)
     return (first_word & 3) == 3 ? 4 : 2;
 }
 
-int riscv_monitor_get_register_legacy(CPUState *cs, const char *name,
-                                      int64_t *pval);
-
 #endif
diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c
index 7e61ae2a4717..20f3ba57ae57 100644
--- a/target/riscv/monitor.c
+++ b/target/riscv/monitor.c
@@ -19,10 +19,7 @@
  */
 
 #include "qemu/osdep.h"
-#include "qemu/ctype.h"
-#include "qemu/qemu-print.h"
 #include "cpu.h"
-#include "target/riscv/tcg/csr.h"
 #include "cpu_bits.h"
 #include "monitor/monitor.h"
 #include "monitor/hmp.h"
@@ -247,140 +244,3 @@ void hmp_info_mem(MonitorHMP *hmp, const QDict *qdict)
     mem_info_svxx(hmp, env);
 }
 #endif /* CONFIG_HMP */
-
-#ifdef CONFIG_TCG
-static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
-                                 target_ulong *val, bool is_gprh)
-{
-    const char * const *reg_names;
-    uint64_t *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 (g_ascii_strcasecmp(name, riscv_rvv_regnames[i]) == 0) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-int riscv_monitor_get_register_legacy(CPUState *cs, const char *name,
-                                      int64_t *pval)
-{
-    RISCVCPU *hart = RISCV_CPU(cs);
-    CPURISCVState *env = cpu_env(cs);
-    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 = riscv_cpu_is_32bit(hart) ? (int32_t)val : 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 (g_ascii_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 = riscv_cpu_is_32bit(hart) ? (int32_t)val : val;
-            return 0;
-        }
-    }
-
-    return -EINVAL;
-}
-#endif
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index ae9bdca9df82..89dfb091ca87 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -995,31 +995,12 @@ static const Property sparc_cpu_properties[] = {
 
 #ifndef CONFIG_USER_ONLY
 
-#ifdef TARGET_SPARC64
-#include "monitor/hmp.h"
-#ifdef CONFIG_HMP
-static const MonitorDef sparc64_monitor_defs[] = {
-    { "asi", offsetof(CPUSPARCState, asi) },
-    { "pstate", offsetof(CPUSPARCState, pstate) },
-    { "cansave", offsetof(CPUSPARCState, cansave) },
-    { "canrestore", offsetof(CPUSPARCState, canrestore) },
-    { "otherwin", offsetof(CPUSPARCState, otherwin) },
-    { "wstate", offsetof(CPUSPARCState, wstate) },
-    { "cleanwin", offsetof(CPUSPARCState, cleanwin) },
-    { NULL },
-};
-#endif
-#endif
-
 #include "hw/core/sysemu-cpu-ops.h"
 
 static const struct SysemuCPUOps sparc_sysemu_ops = {
     .has_work = sparc_cpu_has_work,
     .get_phys_addr_debug = sparc_cpu_get_phys_addr_debug,
     .legacy_vmsd = &vmstate_sparc_cpu,
-#if defined(TARGET_SPARC64) && defined(CONFIG_HMP)
-    .monitor_defs = sparc64_monitor_defs,
-#endif
 };
 #endif
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 02/10] gdbstub: fix next register base after register gaps
  2026-09-11 12:27 ` [PATCH 02/10] gdbstub: fix next register base after register gaps Marc-André Lureau
@ 2026-09-11 15:29   ` Alex Bennée
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Bennée @ 2026-09-11 15:29 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Dr. David Alan Gilbert, Philippe Mathieu-Daudé,
	Zhao Liu, Peter Maydell, Chinmay Rath, Nicholas Piggin,
	Glenn Miles, Harsh Prateek Bora, Palmer Dabbelt, Alistair Francis,
	Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, Chao Liu,
	Max Filippov, qemu-arm, qemu-ppc, qemu-riscv, Paolo Bonzini,
	Laurent Vivier, Mark Cave-Ayland, Artyom Tarasenko, Helge Deller,
	Pierrick Bouvier, Warner Losh, Kyle Evans

Marc-André Lureau <marcandre.lureau@redhat.com> writes:

> Commit b3e88abb200c ("gdbstub: Consider GDBFeature::base_reg in
> gdb_register_coprocessor()") identified that register numbers may
> have gaps. We also need to adjust the next base_reg correctly
> to avoid overlapping registers. Rename the field to be more
> explicit about its usage.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Acked-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  gdbstub/gdbstub.c      | 13 ++++++-------
>  include/hw/core/cpu.h  |  2 +-
>  target/arm/gdbstub.c   |  8 +++++---
>  target/arm/gdbstub64.c | 10 ++++++----
>  target/ppc/gdbstub.c   |  2 +-
>  target/riscv/gdbstub.c |  9 ++++++---
>  target/xtensa/cpu.c    |  2 +-
>  7 files changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
> index 0a328b0dd488..0ce871d74929 100644
> --- a/gdbstub/gdbstub.c
> +++ b/gdbstub/gdbstub.c
> @@ -605,13 +605,13 @@ void gdb_init_cpu(CPUState *cpu)
>          gdb_register_feature(cpu, 0,
>                               cc->gdb_read_register, cc->gdb_write_register,
>                               feature);
> -        cpu->gdb_num_regs = cpu->gdb_num_g_regs = feature->num_regs;
> +        cpu->gdb_next_base_reg = cpu->gdb_num_g_regs = feature->num_regs;
>      } else {
> -        cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
> +        cpu->gdb_next_base_reg = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
>      }
>  
>      trace_gdbxml_init_cpu(object_get_typename(OBJECT(cpu)), cpu->cpu_index,
> -                          cpu->gdb_num_regs, cpu->gdb_num_g_regs,
> +                          cpu->gdb_next_base_reg, cpu->gdb_num_g_regs,
>                            cc->gdb_num_core_regs);
>  }
>  
> @@ -621,7 +621,7 @@ void gdb_register_coprocessor(CPUState *cpu,
>  {
>      GDBRegisterState *s;
>      guint i;
> -    int base_reg = cpu->gdb_num_regs;
> +    int base_reg = cpu->gdb_next_base_reg;
>  
>      for (i = 0; i < cpu->gdb_regs->len; i++) {
>          /* Check for duplicates.  */
> @@ -639,7 +639,7 @@ void gdb_register_coprocessor(CPUState *cpu,
>      gdb_register_feature(cpu, base_reg, get_reg, set_reg, feature);
>  
>      /* Add to end of list.  */
> -    cpu->gdb_num_regs += feature->num_regs;
> +    cpu->gdb_next_base_reg = base_reg + feature->num_regs;
>  }
>  
>  void gdb_unregister_coprocessor_all(CPUState *cpu)
> @@ -651,7 +651,7 @@ void gdb_unregister_coprocessor_all(CPUState *cpu)
>      g_array_free(cpu->gdb_regs, true);
>  
>      cpu->gdb_regs = NULL;
> -    cpu->gdb_num_regs = 0;
> +    cpu->gdb_next_base_reg = 0;
>      cpu->gdb_num_g_regs = 0;
>  }
>  
> @@ -2522,4 +2522,3 @@ void gdb_create_default_process(GDBState *s)
>      process->attached = false;
>      process->target_xml = NULL;
>  }
> -
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index 328e30045ce1..02212f555c2e 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -521,7 +521,7 @@ struct CPUState {
>      struct CPUJumpCache *tb_jmp_cache;
>  
>      GArray *gdb_regs;
> -    int gdb_num_regs;
> +    int gdb_next_base_reg;
>      int gdb_num_g_regs;
>      QTAILQ_ENTRY(CPUState) node;
>  
> diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
> index d6e29c4cf467..e5cbe4d951ef 100644
> --- a/target/arm/gdbstub.c
> +++ b/target/arm/gdbstub.c
> @@ -555,19 +555,21 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>          gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
>                                   gdb_find_static_feature("arm-m-profile-mve.xml"));
>      }
> +    GDBFeature *feature =
> +        arm_gen_dynamic_sysreg_feature(cs, cs->gdb_next_base_reg);
>      gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
> -                             arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs));
> +                             feature);
>  
>  #ifdef CONFIG_TCG
>      if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
>          gdb_register_coprocessor(cs,
>              arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
> -            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs));
> +            arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_next_base_reg));
>  #ifndef CONFIG_USER_ONLY
>          if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
>              gdb_register_coprocessor(cs,
>                  arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
> -                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs));
> +                arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_next_base_reg));
>          }
>  #endif
>      }
> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> index 0c3e5b30bd6a..cf5b95b54641 100644
> --- a/target/arm/gdbstub64.c
> +++ b/target/arm/gdbstub64.c
> @@ -885,7 +885,8 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>      CPUState *cs = CPU(cpu);
>      if (isar_feature_aa64_sve(&cpu->isar) ||
>          isar_feature_aa64_sme(&cpu->isar)) {
> -        GDBFeature *feature = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs);
> +        GDBFeature *feature =
> +            arm_gen_dynamic_svereg_feature(cs, cs->gdb_next_base_reg);
>          gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
>                                   aarch64_gdb_set_sve_reg, feature);
>      } else {
> @@ -896,7 +897,7 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>  
>      if (isar_feature_aa64_sme(&cpu->isar)) {
>          GDBFeature *sme_feature =
> -            arm_gen_dynamic_smereg_feature(cs, cs->gdb_num_regs);
> +            arm_gen_dynamic_smereg_feature(cs, cs->gdb_next_base_reg);
>          gdb_register_coprocessor(cs, aarch64_gdb_get_sme_reg,
>                                   aarch64_gdb_set_sme_reg, sme_feature);
>          if (isar_feature_aa64_sme2(&cpu->isar)) {
> @@ -927,7 +928,8 @@ void aarch64_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
>  #endif
>  
>      /* All AArch64 CPUs have at least TPIDR */
> +    GDBFeature *tls_feature =
> +        arm_gen_dynamic_tls_feature(cs, cs->gdb_next_base_reg);
>      gdb_register_coprocessor(cs, aarch64_gdb_get_tls_reg,
> -                             aarch64_gdb_set_tls_reg,
> -                             arm_gen_dynamic_tls_feature(cs, cs->gdb_num_regs));
> +                             aarch64_gdb_set_tls_reg, tls_feature);
>  }
> diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
> index 4d622c5cad59..ec25c541c685 100644
> --- a/target/ppc/gdbstub.c
> +++ b/target/ppc/gdbstub.c
> @@ -206,7 +206,7 @@ static void gdb_gen_spr_feature(CPUState *cs)
>  
>      gdb_feature_builder_init(&builder, &pcc->gdb_spr,
>                               "org.qemu.power.spr", "power-spr.xml",
> -                             cs->gdb_num_regs);
> +                             cs->gdb_next_base_reg);
>  
>      for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
>          ppc_spr_t *spr = &env->spr_cb[i];
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index 9abbf5bcdf0e..f279f4ab2461 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -348,9 +348,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
>                                   gdb_find_static_feature("riscv-32bit-fpu.xml"));
>      }
>      if (cpu->cfg.ext_zve32x) {
> +        GDBFeature *feature =
> +            ricsv_gen_dynamic_vector_feature(cs, cs->gdb_next_base_reg);
>          gdb_register_coprocessor(cs, riscv_gdb_get_vector,
> -                                 riscv_gdb_set_vector,
> -                                 ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs));
> +                                 riscv_gdb_set_vector, feature);
>      }
>  
>  #ifdef CONFIG_TCG
> @@ -373,8 +374,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
>      }
>  
>      if (cpu->cfg.ext_zicsr) {
> +        GDBFeature *feature =
> +            riscv_gen_dynamic_csr_feature(cs, cs->gdb_next_base_reg);
>          gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> -                                 riscv_gen_dynamic_csr_feature(cs, cs->gdb_num_regs));
> +                                 feature);
>      }
>  #endif
>  }
> diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
> index 7c25b9ab707a..48863a1859d4 100644
> --- a/target/xtensa/cpu.c
> +++ b/target/xtensa/cpu.c
> @@ -263,7 +263,7 @@ static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> -    cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs;
> +    cs->gdb_next_base_reg = xcc->config->gdb_regmap.num_regs;
>  
>      qemu_init_vcpu(cs);

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-09-11 15:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 12:27 [PATCH 00/10] monitor/hmp: replace MonitorDef with GDB registers Marc-André Lureau
2026-09-11 12:27 ` [PATCH 01/10] hmp: don't crash on invalid register Marc-André Lureau
2026-09-11 12:27 ` [PATCH 02/10] gdbstub: fix next register base after register gaps Marc-André Lureau
2026-09-11 15:29   ` Alex Bennée
2026-09-11 12:27 ` [PATCH 03/10] gdbstub: set feature->base_reg for dynamic features Marc-André Lureau
2026-09-11 12:27 ` [PATCH 04/10] target/i386: expose segment limits via GDB Marc-André Lureau
2026-09-11 12:27 ` [PATCH 05/10] monitor/hmp: add CPUClass::get_pc fallback for HMP $pc Marc-André Lureau
2026-09-11 12:27 ` [PATCH 06/10] target/m68k: expose system registers via GDB Marc-André Lureau
2026-09-11 12:27 ` [PATCH 07/10] target/sparc64: " Marc-André Lureau
2026-09-11 12:27 ` [PATCH 08/10] target/riscv: bypass smstateen check in debugger mode Marc-André Lureau
2026-09-11 12:27 ` [PATCH 09/10] target/riscv: expose register aliases via GDB Marc-André Lureau
2026-09-11 12:27 ` [PATCH 10/10] monitor/hmp: remove legacy MonitorDef infrastructure Marc-André Lureau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox