diff mbox

KVM: VMX: Fix comparison of guest efer with stale host value

Message ID 1259750043-19706-1-git-send-email-avi@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Avi Kivity Dec. 2, 2009, 10:34 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 06e0856..4f865e8 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -812,6 +812,6 @@  int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 
 void kvm_define_shared_msr(unsigned index, u32 msr);
-void kvm_set_shared_msr(unsigned index, u64 val);
+void kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
 
 #endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 1092e8a..9a0a2cf 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)
@@ -2393,6 +2393,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;
 	}
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index fdfff4c..dd15d7a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -185,11 +185,11 @@  static void kvm_shared_msr_cpu_online(void)
 		locals->current_value[i] = shared_msrs_global.msrs[i].value;
 }
 
-void kvm_set_shared_msr(unsigned slot, u64 value)
+void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
 {
 	struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
 
-	if (value == smsr->current_value[slot])
+	if (((value ^ smsr->current_value[slot]) & mask) == 0)
 		return;
 	smsr->current_value[slot] = value;
 	wrmsrl(shared_msrs_global.msrs[slot].msr, value);