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
