mirror of
https://github.com/qemu/qemu.git
synced 2026-02-04 05:35:39 +00:00
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:
@@ -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
|
||||
|
||||
26
gdb-xml/i386-64bit-apx.xml
Normal file
26
gdb-xml/i386-64bit-apx.xml
Normal 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>
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user