Re: [PATCH 3/4] KVM: x86: Recompute EFER.LMA instead of inheriting the current value on EFER writes

From: Yosry Ahmed

Date: Fri Oct 23 2026 - 11:06:52 EST


On Thu, Oct 22, 2026 at 3:31 PM Sean Christopherson <seanjc@xxxxxxxxxx> wrote:
>
> Recompute EFER.LMA on bare writes to EFER (via WRMSR or KVM_SET_MSRS)
> instead of carrying forward the current EFER.LMA. While it _should_ be
> impossible for EFER.LMA to end up in an inconsistent state on such a write,
> KVM has had a rash of exactly those bugs, mostly because SVM is quite lax
> when it comes to consistenty checks, which in turn bleeds into KVM's nested
> SVM implementation. Retaining the existing EFER is also rather confusing,
> as understanding why keeping EFER.LMA is correct requires a lot of a priori
> knowledge of both x86-64 and KVM.
>
> Keep the core concept of the existing logic as a sanity check: WARN and
> reject the write if the computed EFER.LMA would be toggled, because as
> described above, that _should_ be impossible.
>
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
> ---
> arch/x86/kvm/msrs.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
> index c3cb1575fe66..41f3ec6eb286 100644
> --- a/arch/x86/kvm/msrs.c
> +++ b/arch/x86/kvm/msrs.c
> @@ -638,8 +638,18 @@ static int set_efer(struct kvm_vcpu *vcpu, u64 efer)
> (vcpu->arch.efer & EFER_SVME) && !(efer & EFER_SVME))
> return 1;
>
> - efer &= ~EFER_LMA;
> - efer |= vcpu->arch.efer & EFER_LMA;
> + if ((efer & EFER_LME) && is_paging(vcpu) && is_pae(vcpu))
> + efer |= EFER_LMA;
> + else
> + efer &= ~EFER_LMA;

Does this mean we can effectively revert this patch:
https://lore.kernel.org/kvm/20260902232028.2767071-3-seanjc@xxxxxxxxxx/?

> +
> + /*
> + * Toggling EFER.LMA on a bare write to EFER should be impossible, as
> + * it means KVM allowed architecturally invalid state at some point in
> + * the past, i.e. allowed EFER.LMA=1 && (!CR0.PG || !CR4.PAE).
> + */
> + if (WARN_ON_ONCE((efer & EFER_LMA) != (vcpu->arch.efer & EFER_LMA)))
> + return 1;
>
> r = kvm_x86_call(set_efer)(vcpu, efer);
> if (r) {
> --
> 2.56.0.257.gf7497c7d27-goog
>
>