diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-02 12:28:47 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 09:34:20 +0200 |
commit | d5696725b2a4c59503f5e0bc33adeee7f30cd45b (patch) | |
tree | 56069b502c198fbfef0eb0d9bd3a2329b3d37cef /arch/x86/kvm/vmx.c | |
parent | f50146bd7bdb75435638e60d4960edd9bcdf88b8 (diff) | |
download | op-kernel-dev-d5696725b2a4c59503f5e0bc33adeee7f30cd45b.zip op-kernel-dev-d5696725b2a4c59503f5e0bc33adeee7f30cd45b.tar.gz |
KVM: VMX: Fix comparison of guest efer with stale host value
update_transition_efer() masks out some efer bits when deciding whether
to switch the msr during guest entry; for example, NX is emulated using the
mmu so we don't need to disable it, and LMA/LME are handled by the hardware.
However, with shared msrs, the comparison is made against a stale value;
at the time of the guest switch we may be running with another guest's efer.
Fix by deferring the mask/compare to the actual point of guest entry.
Noted by Marcelo.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ed97c6c..d4918d6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -89,6 +89,7 @@ struct vmcs { struct shared_msr_entry { unsigned index; u64 data; + u64 mask; }; struct vcpu_vmx { @@ -601,12 +602,10 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) if (guest_efer & EFER_LMA) ignore_bits &= ~(u64)EFER_SCE; #endif - if ((guest_efer & ~ignore_bits) == (host_efer & ~ignore_bits)) - return false; - 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; return true; } @@ -657,7 +656,8 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) #endif for (i = 0; i < vmx->save_nmsrs; ++i) kvm_set_shared_msr(vmx->guest_msrs[i].index, - vmx->guest_msrs[i].data); + vmx->guest_msrs[i].data, + vmx->guest_msrs[i].mask); } static void __vmx_load_host_state(struct vcpu_vmx *vmx) @@ -2394,6 +2394,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) data = data_low | ((u64)data_high << 32); vmx->guest_msrs[j].index = i; vmx->guest_msrs[j].data = 0; + vmx->guest_msrs[j].mask = -1ull; ++vmx->nmsrs; } |