summaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorAvi Kivity2009-12-02 11:28:47 +0100
committerAvi Kivity2009-12-03 08:34:20 +0100
commitd5696725b2a4c59503f5e0bc33adeee7f30cd45b (patch)
tree56069b502c198fbfef0eb0d9bd3a2329b3d37cef /arch/x86/kvm/vmx.c
parentKVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c (diff)
downloadkernel-qcow2-linux-d5696725b2a4c59503f5e0bc33adeee7f30cd45b.tar.gz
kernel-qcow2-linux-d5696725b2a4c59503f5e0bc33adeee7f30cd45b.tar.xz
kernel-qcow2-linux-d5696725b2a4c59503f5e0bc33adeee7f30cd45b.zip
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.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ed97c6c7e648..d4918d6fc924 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;
}