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 <[email protected]>
---
 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


Reply via email to