diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 35 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 25 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 7 |
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 | } | ||
998 | set: | 992 | set: |
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 | ||
2587 | static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) | 2583 | static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) |
2588 | { | 2584 | { |
2585 | if (npt_enabled) | ||
2586 | vcpu->fpu_active = 1; | ||
2589 | } | 2587 | } |
2590 | 2588 | ||
2591 | static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu) | 2589 | static 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 | ||
2816 | static int is_disabled(void) | 2808 | static int is_disabled(void) |
@@ -2926,6 +2918,20 @@ static bool svm_rdtscp_supported(void) | |||
2926 | return false; | 2918 | return false; |
2927 | } | 2919 | } |
2928 | 2920 | ||
2921 | static 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 | |||
2929 | static struct kvm_x86_ops svm_x86_ops = { | 2935 | static 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 | ||
807 | static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu) | 808 | static 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 | ||
1768 | static u64 construct_eptp(unsigned long root_hpa) | 1764 | static 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 | ||
1800 | static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | 1794 | static 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 | ||
1510 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 1510 | void 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 | ||
1516 | static int is_efer_nx(void) | 1516 | static 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 | } |
5079 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); | 5084 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); |
5080 | 5085 | ||