* [PATCH] KVM: x86: Inject #UD for AMD-compatible SYSEXIT in long mode
@ 2026-10-21 2:11 Hao Zhang
0 siblings, 0 replies; only message in thread
From: Hao Zhang @ 2026-10-21 2:11 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel
From: Hao Zhang <zhanghao1@kylinos.cn>
AMD specifies that SYSEXIT raises #UD in both 64-bit and compatibility
modes. On AMD hosts, KVM intercepts the hardware #UD, but SYSEXIT is
marked EmulateOnUD and em_sysexit() applies Intel semantics without
checking the guest CPU vendor.
For an AMD-compatible guest at CPL0, this can incorrectly complete
the transition to CPL3 or inject #GP, depending on the SYSENTER_CS
value and other operands. At nonzero CPL, the generic Priv check
injects #GP instead of the required #UD.
Inject #UD for AMD-compatible vCPUs when EFER.LMA is set, before
checking CPL or SYSENTER_CS and before modifying architectural state.
Move the CPL check into em_sysexit() and remove the opcode's Priv
flag so that the generic privilege check does not take precedence
over AMD's long-mode #UD. Retain the existing #GP behavior for real
mode, virtual-8086 mode, and nonzero CPL outside the AMD long-mode
case.
See the SYSEXIT instruction description in AMD APM Volume 3.
Fixes: 4668f0507870 ("KVM: x86 emulator: Add sysexit emulation")
Signed-off-by: Hao Zhang <zhanghao1@kylinos.cn>
---
arch/x86/kvm/emulate.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c1b21282187f..2154a2f2fd92 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2457,12 +2457,18 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
const struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
u64 msr_data, rcx, rdx;
+ u64 efer = 0;
int usermode;
u16 cs_sel = 0, ss_sel = 0;
- /* inject #GP if in real mode or Virtual 8086 mode */
+ /* AMD rejects SYSEXIT in both IA-32e submodes, even at CPL3. */
+ ops->get_msr(ctxt, MSR_EFER, &efer);
+ if ((efer & EFER_LMA) && !ops->guest_cpuid_is_intel_compatible(ctxt))
+ return emulate_ud(ctxt);
+
+ /* Check CPL here so that AMD's long-mode #UD takes precedence. */
if (ctxt->mode == X86EMUL_MODE_REAL ||
- ctxt->mode == X86EMUL_MODE_VM86)
+ ctxt->mode == X86EMUL_MODE_VM86 || ops->cpl(ctxt))
return emulate_gp(ctxt, 0);
setup_syscalls_segments(&cs, &ss);
@@ -4390,7 +4396,7 @@ static const struct opcode twobyte_table[256] = {
II(ImplicitOps | Priv, em_rdmsr, rdmsr),
IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc),
I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysenter),
- I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack, em_sysexit),
+ I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysexit),
N, N,
N, N, N, N, N, N, N, N,
/* 0x40 - 0x4F */
base-commit: 6c377d19d4a5116d9bec5203aa3c6c11523e7898
--
2.15.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-21 2:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21 2:11 [PATCH] KVM: x86: Inject #UD for AMD-compatible SYSEXIT in long mode Hao Zhang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®