diff options
author | Avi Kivity <avi@redhat.com> | 2010-01-24 09:26:40 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:36:06 -0500 |
commit | 81231c698a71af6e1815df72c06685d295e1cc1d (patch) | |
tree | 73c7a47cf05b329a6bcf2650d3c5890a51d69c95 | |
parent | da15bf436bc9586603b47b39244157431fa38b56 (diff) |
KVM: VMX: Pass cr0.mp through to the guest when the fpu is active
When cr0.mp is clear, the guest doesn't expect a #NM in response to
a WAIT instruction. Because we always keep cr0.mp set, it will get
a #NM, and potentially be confused.
Fix by keeping cr0.mp set only when the fpu is inactive, and passing
it through when inactive.
Reported-by: Lorenzo Martignoni <martignlo@gmail.com>
Analyzed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a680d939546f..7a56879a058c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -66,7 +66,7 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO); | |||
66 | #define KVM_GUEST_CR0_MASK \ | 66 | #define KVM_GUEST_CR0_MASK \ |
67 | (KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE) | 67 | (KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE) |
68 | #define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST \ | 68 | #define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST \ |
69 | (X86_CR0_WP | X86_CR0_NE | X86_CR0_MP) | 69 | (X86_CR0_WP | X86_CR0_NE) |
70 | #define KVM_VM_CR0_ALWAYS_ON \ | 70 | #define KVM_VM_CR0_ALWAYS_ON \ |
71 | (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE) | 71 | (KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE) |
72 | #define KVM_CR4_GUEST_OWNED_BITS \ | 72 | #define KVM_CR4_GUEST_OWNED_BITS \ |
@@ -791,12 +791,15 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu) | |||
791 | 791 | ||
792 | static void vmx_fpu_activate(struct kvm_vcpu *vcpu) | 792 | static void vmx_fpu_activate(struct kvm_vcpu *vcpu) |
793 | { | 793 | { |
794 | ulong cr0; | ||
795 | |||
794 | if (vcpu->fpu_active) | 796 | if (vcpu->fpu_active) |
795 | return; | 797 | return; |
796 | vcpu->fpu_active = 1; | 798 | vcpu->fpu_active = 1; |
797 | vmcs_clear_bits(GUEST_CR0, X86_CR0_TS); | 799 | cr0 = vmcs_readl(GUEST_CR0); |
798 | if (kvm_read_cr0_bits(vcpu, X86_CR0_TS)) | 800 | cr0 &= ~(X86_CR0_TS | X86_CR0_MP); |
799 | vmcs_set_bits(GUEST_CR0, X86_CR0_TS); | 801 | cr0 |= kvm_read_cr0_bits(vcpu, X86_CR0_TS | X86_CR0_MP); |
802 | vmcs_writel(GUEST_CR0, cr0); | ||
800 | update_exception_bitmap(vcpu); | 803 | update_exception_bitmap(vcpu); |
801 | vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS; | 804 | vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS; |
802 | vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); | 805 | vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); |
@@ -807,7 +810,7 @@ static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu); | |||
807 | static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu) | 810 | static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu) |
808 | { | 811 | { |
809 | vmx_decache_cr0_guest_bits(vcpu); | 812 | vmx_decache_cr0_guest_bits(vcpu); |
810 | vmcs_set_bits(GUEST_CR0, X86_CR0_TS); | 813 | vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP); |
811 | update_exception_bitmap(vcpu); | 814 | update_exception_bitmap(vcpu); |
812 | vcpu->arch.cr0_guest_owned_bits = 0; | 815 | vcpu->arch.cr0_guest_owned_bits = 0; |
813 | vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); | 816 | vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); |
@@ -1757,7 +1760,7 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
1757 | ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu); | 1760 | ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu); |
1758 | 1761 | ||
1759 | if (!vcpu->fpu_active) | 1762 | if (!vcpu->fpu_active) |
1760 | hw_cr0 |= X86_CR0_TS; | 1763 | hw_cr0 |= X86_CR0_TS | X86_CR0_MP; |
1761 | 1764 | ||
1762 | vmcs_writel(CR0_READ_SHADOW, cr0); | 1765 | vmcs_writel(CR0_READ_SHADOW, cr0); |
1763 | vmcs_writel(GUEST_CR0, hw_cr0); | 1766 | vmcs_writel(GUEST_CR0, hw_cr0); |