i386/gdbstub: Add APX support for gdbstub

Add i386-64bit-apx.xml from gdb to allow QEMU gdbstub parse APX EGPRs,
and implement the callbacks to allow gdbstub access EGPRs of guest.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20251211070942.3612547-5-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Zhao Liu
2025-12-11 15:09:37 +08:00
committed by Paolo Bonzini
parent 1b1cf88937
commit f46e5073a8
4 changed files with 110 additions and 3 deletions

View File

@@ -2,5 +2,5 @@ TARGET_ARCH=x86_64
TARGET_BASE_ARCH=i386
TARGET_KVM_HAVE_GUEST_DEBUG=y
TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
TARGET_XML_FILES= gdb-xml/i386-64bit.xml
TARGET_XML_FILES= gdb-xml/i386-64bit.xml gdb-xml/i386-64bit-apx.xml
TARGET_LONG_BITS=64

View File

@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2024 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.i386.apx">
<reg name="r16" bitsize="64" type="int64"/>
<reg name="r17" bitsize="64" type="int64"/>
<reg name="r18" bitsize="64" type="int64"/>
<reg name="r19" bitsize="64" type="int64"/>
<reg name="r20" bitsize="64" type="int64"/>
<reg name="r21" bitsize="64" type="int64"/>
<reg name="r22" bitsize="64" type="int64"/>
<reg name="r23" bitsize="64" type="int64"/>
<reg name="r24" bitsize="64" type="int64"/>
<reg name="r25" bitsize="64" type="int64"/>
<reg name="r26" bitsize="64" type="int64"/>
<reg name="r27" bitsize="64" type="int64"/>
<reg name="r28" bitsize="64" type="int64"/>
<reg name="r29" bitsize="64" type="int64"/>
<reg name="r30" bitsize="64" type="int64"/>
<reg name="r31" bitsize="64" type="int64"/>
</feature>

View File

@@ -61,6 +61,22 @@ enum {
R_R13 = 13,
R_R14 = 14,
R_R15 = 15,
R_R16 = 16,
R_R17 = 17,
R_R18 = 18,
R_R19 = 19,
R_R20 = 20,
R_R21 = 21,
R_R22 = 22,
R_R23 = 23,
R_R24 = 24,
R_R25 = 25,
R_R26 = 26,
R_R27 = 27,
R_R28 = 28,
R_R29 = 29,
R_R30 = 30,
R_R31 = 31,
R_AL = 0,
R_CL = 1,

View File

@@ -27,9 +27,11 @@
#endif
#ifdef TARGET_X86_64
static const int gpr_map[16] = {
static const int gpr_map[CPU_NB_EREGS] = {
R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
8, 9, 10, 11, 12, 13, 14, 15
R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15,
R_R16, R_R17, R_R18, R_R19, R_R20, R_R21, R_R22, R_R23,
R_R24, R_R25, R_R26, R_R27, R_R28, R_R29, R_R30, R_R31,
};
#else
#define gpr_map gpr_map32
@@ -444,8 +446,71 @@ static int x86_cpu_gdb_write_linux_register(CPUState *cs, uint8_t *mem_buf,
#endif
#ifdef TARGET_X86_64
static int i386_cpu_gdb_get_egprs(CPUState *cs, GByteArray *mem_buf, int n)
{
CPUX86State *env = &X86_CPU(cs)->env;
if (n >= 0 && n < EGPR_NUM) {
/* EGPRs can be only directly accessible in 64-bit mode. */
if (env->hflags & HF_CS64_MASK) {
return gdb_get_reg64(mem_buf, env->regs[gpr_map[n + CPU_NB_REGS]]);
} else {
return gdb_get_regl(mem_buf, 0);
}
}
return 0;
}
static int i386_cpu_gdb_set_egprs(CPUState *cs, uint8_t *mem_buf, int n)
{
CPUX86State *env = &X86_CPU(cs)->env;
if (n >= 0 && n < EGPR_NUM) {
/*
* EGPRs can be only directly accessible in 64-bit mode, and require
* XCR0[APX_F] (at least for modification in gdbstub) to be enabled.
*/
if (env->hflags & HF_CS64_MASK && env->xcr0 & XSTATE_APX_MASK) {
env->regs[gpr_map[n + CPU_NB_REGS]] = ldtul_p(mem_buf);
/*
* Per SDM Vol 1, "Processor Tracking of XSAVE-Managed State",
* XSTATE_BV[i] *may* be either 0 or 1 if the state component is
* in its initial configuration.
*
* However, it is observed on Diamond Rapids (DMR) that
* XSTATE_BV[APX_F] is set whenever EGPRs are modified, regardless
* of the value written (even if zero).
*
* Since GDB modifies the software register cache directly,
* manually force the bit set to emulate this behavior observed
* on hardware.
*/
if (!(env->xstate_bv & XSTATE_APX_MASK)) {
env->xstate_bv |= XSTATE_APX_MASK;
}
}
return sizeof(target_ulong);
}
return 0;
}
#endif
void x86_cpu_gdb_init(CPUState *cs)
{
#ifdef TARGET_X86_64
CPUX86State *env = &X86_CPU(cs)->env;
if (env->features[FEAT_7_1_EDX] & CPUID_7_1_EDX_APXF) {
gdb_register_coprocessor(cs, i386_cpu_gdb_get_egprs,
i386_cpu_gdb_set_egprs,
gdb_find_static_feature("i386-64bit-apx.xml"),
0);
}
#endif
#ifdef CONFIG_LINUX_USER
gdb_register_coprocessor(cs, x86_cpu_gdb_read_linux_register,
x86_cpu_gdb_write_linux_register,