On 25/10/19 10:37, speck for Joerg Roedel wrote: > I fixed it with this diff: > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index e7970a2e8eae..6e9380a0ca41 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -997,7 +997,7 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) > * On CPUs that support "load IA32_EFER", always switch EFER > * atomically, since it's faster than switching it manually. > */ > - if (cpu_has_load_ia32_efer() || > + if ((cpu_has_load_ia32_efer() && (guest_efer & EFER_NX)) || > (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) { > if (!(guest_efer & EFER_LMA)) > guest_efer &= ~EFER_LME; > What about this instead (completely untested): diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e7970a2e8eae..1f923dee99e5 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -992,6 +992,9 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) ignore_bits &= ~(u64)EFER_SCE; #endif + guest_efer &= ~ignore_bits; + guest_efer |= host_efer & ignore_bits; + /* * On EPT, we can't emulate NX, so we must switch EFER atomically. * On CPUs that support "load IA32_EFER", always switch EFER @@ -1010,9 +1013,6 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) } else { clear_atomic_switch_msr(vmx, MSR_EFER); - guest_efer &= ~ignore_bits; - guest_efer |= host_efer & ignore_bits; - vmx->guest_msrs[efer_offset].data = guest_efer; vmx->guest_msrs[efer_offset].mask = ~ignore_bits;