aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/svm.c35
-rw-r--r--arch/x86/kvm/vmx.c25
-rw-r--r--arch/x86/kvm/x86.c7
4 files changed, 37 insertions, 31 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 693046a7a12d..93bee7abb71c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -506,6 +506,7 @@ struct kvm_x86_ops {
506 void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); 506 void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
507 unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); 507 unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
508 void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); 508 void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
509 void (*fpu_deactivate)(struct kvm_vcpu *vcpu);
509 510
510 void (*tlb_flush)(struct kvm_vcpu *vcpu); 511 void (*tlb_flush)(struct kvm_vcpu *vcpu);
511 512
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 3899c2d19830..5b336a80f31e 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -984,17 +984,11 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
984 if (npt_enabled) 984 if (npt_enabled)
985 goto set; 985 goto set;
986 986
987 if (kvm_read_cr0_bits(vcpu, X86_CR0_TS) && !(cr0 & X86_CR0_TS)) {
988 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
989 vcpu->fpu_active = 1;
990 }
991
992 vcpu->arch.cr0 = cr0; 987 vcpu->arch.cr0 = cr0;
993 cr0 |= X86_CR0_PG | X86_CR0_WP; 988 cr0 |= X86_CR0_PG | X86_CR0_WP;
994 if (!vcpu->fpu_active) { 989
995 svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR); 990 if (!vcpu->fpu_active)
996 cr0 |= X86_CR0_TS; 991 cr0 |= X86_CR0_TS;
997 }
998set: 992set:
999 /* 993 /*
1000 * re-enable caching here because the QEMU bios 994 * re-enable caching here because the QEMU bios
@@ -1250,6 +1244,8 @@ static int nm_interception(struct vcpu_svm *svm)
1250 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR); 1244 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
1251 if (!kvm_read_cr0_bits(&svm->vcpu, X86_CR0_TS)) 1245 if (!kvm_read_cr0_bits(&svm->vcpu, X86_CR0_TS))
1252 svm->vmcb->save.cr0 &= ~X86_CR0_TS; 1246 svm->vmcb->save.cr0 &= ~X86_CR0_TS;
1247 else
1248 svm->vmcb->save.cr0 |= X86_CR0_TS;
1253 svm->vcpu.fpu_active = 1; 1249 svm->vcpu.fpu_active = 1;
1254 1250
1255 return 1; 1251 return 1;
@@ -2586,6 +2582,8 @@ static void svm_flush_tlb(struct kvm_vcpu *vcpu)
2586 2582
2587static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) 2583static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu)
2588{ 2584{
2585 if (npt_enabled)
2586 vcpu->fpu_active = 1;
2589} 2587}
2590 2588
2591static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu) 2589static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
@@ -2805,12 +2803,6 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
2805 2803
2806 svm->vmcb->save.cr3 = root; 2804 svm->vmcb->save.cr3 = root;
2807 force_new_asid(vcpu); 2805 force_new_asid(vcpu);
2808
2809 if (vcpu->fpu_active) {
2810 svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
2811 svm->vmcb->save.cr0 |= X86_CR0_TS;
2812 vcpu->fpu_active = 0;
2813 }
2814} 2806}
2815 2807
2816static int is_disabled(void) 2808static int is_disabled(void)
@@ -2926,6 +2918,20 @@ static bool svm_rdtscp_supported(void)
2926 return false; 2918 return false;
2927} 2919}
2928 2920
2921static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
2922{
2923 struct vcpu_svm *svm = to_svm(vcpu);
2924
2925 if (npt_enabled) {
2926 /* hack: npt requires active fpu at this time */
2927 vcpu->fpu_active = 1;
2928 return;
2929 }
2930
2931 svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
2932 svm->vmcb->save.cr0 |= X86_CR0_TS;
2933}
2934
2929static struct kvm_x86_ops svm_x86_ops = { 2935static struct kvm_x86_ops svm_x86_ops = {
2930 .cpu_has_kvm_support = has_svm, 2936 .cpu_has_kvm_support = has_svm,
2931 .disabled_by_bios = is_disabled, 2937 .disabled_by_bios = is_disabled,
@@ -2967,6 +2973,7 @@ static struct kvm_x86_ops svm_x86_ops = {
2967 .cache_reg = svm_cache_reg, 2973 .cache_reg = svm_cache_reg,
2968 .get_rflags = svm_get_rflags, 2974 .get_rflags = svm_get_rflags,
2969 .set_rflags = svm_set_rflags, 2975 .set_rflags = svm_set_rflags,
2976 .fpu_deactivate = svm_fpu_deactivate,
2970 2977
2971 .tlb_flush = svm_flush_tlb, 2978 .tlb_flush = svm_flush_tlb,
2972 2979
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index dbcdb55094f7..d11be3fb7c80 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_TS | X86_CR0_MP) 69 (X86_CR0_WP | X86_CR0_NE | X86_CR0_MP)
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 \
@@ -579,9 +579,8 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
579{ 579{
580 u32 eb; 580 u32 eb;
581 581
582 eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR); 582 eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR)
583 if (!vcpu->fpu_active) 583 | (1u << NM_VECTOR);
584 eb |= 1u << NM_VECTOR;
585 /* 584 /*
586 * Unconditionally intercept #DB so we can maintain dr6 without 585 * Unconditionally intercept #DB so we can maintain dr6 without
587 * reading it every exit. 586 * reading it every exit.
@@ -595,6 +594,8 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
595 eb = ~0; 594 eb = ~0;
596 if (enable_ept) 595 if (enable_ept)
597 eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */ 596 eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
597 if (vcpu->fpu_active)
598 eb &= ~(1u << NM_VECTOR);
598 vmcs_write32(EXCEPTION_BITMAP, eb); 599 vmcs_write32(EXCEPTION_BITMAP, eb);
599} 600}
600 601
@@ -806,9 +807,6 @@ static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
806 807
807static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu) 808static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
808{ 809{
809 if (!vcpu->fpu_active)
810 return;
811 vcpu->fpu_active = 0;
812 vmcs_set_bits(GUEST_CR0, X86_CR0_TS); 810 vmcs_set_bits(GUEST_CR0, X86_CR0_TS);
813 update_exception_bitmap(vcpu); 811 update_exception_bitmap(vcpu);
814} 812}
@@ -1737,8 +1735,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
1737 else 1735 else
1738 hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON; 1736 hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON;
1739 1737
1740 vmx_fpu_deactivate(vcpu);
1741
1742 if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE)) 1738 if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE))
1743 enter_pmode(vcpu); 1739 enter_pmode(vcpu);
1744 1740
@@ -1757,12 +1753,12 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
1757 if (enable_ept) 1753 if (enable_ept)
1758 ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu); 1754 ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
1759 1755
1756 if (!vcpu->fpu_active)
1757 hw_cr0 |= X86_CR0_TS;
1758
1760 vmcs_writel(CR0_READ_SHADOW, cr0); 1759 vmcs_writel(CR0_READ_SHADOW, cr0);
1761 vmcs_writel(GUEST_CR0, hw_cr0); 1760 vmcs_writel(GUEST_CR0, hw_cr0);
1762 vcpu->arch.cr0 = cr0; 1761 vcpu->arch.cr0 = cr0;
1763
1764 if (!(cr0 & X86_CR0_TS) || !(cr0 & X86_CR0_PE))
1765 vmx_fpu_activate(vcpu);
1766} 1762}
1767 1763
1768static u64 construct_eptp(unsigned long root_hpa) 1764static u64 construct_eptp(unsigned long root_hpa)
@@ -1793,8 +1789,6 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
1793 1789
1794 vmx_flush_tlb(vcpu); 1790 vmx_flush_tlb(vcpu);
1795 vmcs_writel(GUEST_CR3, guest_cr3); 1791 vmcs_writel(GUEST_CR3, guest_cr3);
1796 if (kvm_read_cr0_bits(vcpu, X86_CR0_PE))
1797 vmx_fpu_deactivate(vcpu);
1798} 1792}
1799 1793
1800static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 1794static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -3002,11 +2996,9 @@ static int handle_cr(struct kvm_vcpu *vcpu)
3002 }; 2996 };
3003 break; 2997 break;
3004 case 2: /* clts */ 2998 case 2: /* clts */
3005 vmx_fpu_deactivate(vcpu);
3006 vcpu->arch.cr0 &= ~X86_CR0_TS; 2999 vcpu->arch.cr0 &= ~X86_CR0_TS;
3007 vmcs_writel(CR0_READ_SHADOW, kvm_read_cr0(vcpu)); 3000 vmcs_writel(CR0_READ_SHADOW, kvm_read_cr0(vcpu));
3008 trace_kvm_cr_write(0, kvm_read_cr0(vcpu)); 3001 trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
3009 vmx_fpu_activate(vcpu);
3010 skip_emulated_instruction(vcpu); 3002 skip_emulated_instruction(vcpu);
3011 return 1; 3003 return 1;
3012 case 1: /*mov from cr*/ 3004 case 1: /*mov from cr*/
@@ -4127,6 +4119,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
4127 .cache_reg = vmx_cache_reg, 4119 .cache_reg = vmx_cache_reg,
4128 .get_rflags = vmx_get_rflags, 4120 .get_rflags = vmx_get_rflags,
4129 .set_rflags = vmx_set_rflags, 4121 .set_rflags = vmx_set_rflags,
4122 .fpu_deactivate = vmx_fpu_deactivate,
4130 4123
4131 .tlb_flush = vmx_flush_tlb, 4124 .tlb_flush = vmx_flush_tlb,
4132 4125
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 748b15d8e46d..1de2ad7a004d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1509,8 +1509,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1509 1509
1510void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) 1510void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
1511{ 1511{
1512 kvm_x86_ops->vcpu_put(vcpu);
1513 kvm_put_guest_fpu(vcpu); 1512 kvm_put_guest_fpu(vcpu);
1513 kvm_x86_ops->vcpu_put(vcpu);
1514} 1514}
1515 1515
1516static int is_efer_nx(void) 1516static int is_efer_nx(void)
@@ -4006,6 +4006,10 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
4006 r = 0; 4006 r = 0;
4007 goto out; 4007 goto out;
4008 } 4008 }
4009 if (test_and_clear_bit(KVM_REQ_DEACTIVATE_FPU, &vcpu->requests)) {
4010 vcpu->fpu_active = 0;
4011 kvm_x86_ops->fpu_deactivate(vcpu);
4012 }
4009 } 4013 }
4010 4014
4011 preempt_disable(); 4015 preempt_disable();
@@ -5075,6 +5079,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
5075 kvm_fx_save(&vcpu->arch.guest_fx_image); 5079 kvm_fx_save(&vcpu->arch.guest_fx_image);
5076 kvm_fx_restore(&vcpu->arch.host_fx_image); 5080 kvm_fx_restore(&vcpu->arch.host_fx_image);
5077 ++vcpu->stat.fpu_reload; 5081 ++vcpu->stat.fpu_reload;
5082 set_bit(KVM_REQ_DEACTIVATE_FPU, &vcpu->requests);
5078} 5083}
5079EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); 5084EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
5080 5085