[PATCH v2 0/6] KVM: x86: More EFER.LMA vs. CR4.PAE fixes
From: Sean Christopherson
Date: Tue Oct 27 2026 - 18:52:00 EST
Revert a change I made years ago to allow userspace to stuff EFER before
configuring guest CPUID, as configuring CPUID and feature MSRs before anything
else is now a hard requirement (though I suspect I was just a bit overzealous
at the time). The biggest problem with that change, other than creating what
should be impossible state, is that it also bypassed this check:
if (is_paging(vcpu) &&
(vcpu->arch.efer & EFER_LME) != (efer & EFER_LME))
return 1;
which was kinda sorta intentional? I assume the idea was that userspace could
stuff CR0 vs. EFER in any order. Except that in doing so, userspace could get
impossible state in CR0+CR4+EFER (in the aggregate, not in any one individual
register). KVM doesn't advertise MSR_EFER as an MSR that needs to be
saved/restored, and AFAICT no VMM manually does that, they all just use
KVM_{G,S}ET_SREGS{,2} (which is what we want).
So, hit the "I'm feeling lucky!" button and simply revert the misguided
commit.
Patch 2 plugs a hole where userspace can get at the "wants_to_run" logic in
svm_set_efer() via KVM_SYNC_X86_SREGS, which is "fine" for now, but would let
a misbehaving userspace trigger the KVM_BUG_ON() added in patch 3.
Patch 3 is more hardening. Rather than pend a triple fault, which is flawed
because (a) KVM still yanks the vCPU out of L2 without going through a normal
nested VM-Exit and (b) there's a window where KVM can do stuff, e.g. init the
MMU, before the triple fault request is handled, immediately synthesize a #GP.
The only reason I didn't go with a #GP the first time around is that I didn't
want to bleed EFER_SVME information into the common set_efer(), KVM effectively
doesn't allow kvm_x86_call(set_efer)() to inject faults, and the vendor version
is used for many flows, whereas set_efer() is strictly used for WRMSR emulation.
Patch 4 is also more hardening, to try and detect+prevent EFER.LMA from going
stale.
Finally, update the EFER selftest to match the new #GP behavior.
v2:
- Disallowing clearing SVME via KVM_SYNC_X86_SREGS if L2 is active. [Sashiko]
v1: https://lore.kernel.org/all/20261022223052.646891-1-seanjc@xxxxxxxxxx
Sean Christopherson (6):
Revert "KVM: x86: Skip EFER vs. guest CPUID checks for host-initiated
writes"
KVM: x86: Reject clearing EFER.SVME via KVM_SYNC_X86_SREGS if L2 is
active
KVM: nSVM: Synthesize #GP instead of SHUTDOWN if L2 attempts to clear
EFER.SVME
KVM: x86: Recompute EFER.LMA instead of inheriting the current value
on EFER writes
KVM: selftests: Update nSVM EFER test to expect #GP when clearing SVME
in L2
KVM: selftests: Expect failure when trying to set EFER that violates
vCPU model
arch/x86/kvm/msrs.c | 53 ++++++-----
arch/x86/kvm/regs.c | 4 +
arch/x86/kvm/svm/svm.c | 15 +--
.../selftests/kvm/x86/svm_nested_efer_test.c | 95 ++++++++++---------
4 files changed, 92 insertions(+), 75 deletions(-)
base-commit: 7e60162b16f9da0d2fa83da5c1723b6853a0ac1d
--
2.56.0.307.g5fe7bd680c-goog