KVM: x86: remove code for lazy FPU handling
authorPaolo Bonzini <pbonzini@redhat.com>
Sat, 4 Feb 2017 05:18:52 +0000 (21:18 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 17 Feb 2017 11:28:01 +0000 (12:28 +0100)
The FPU is always active now when running KVM.

Reviewed-by: David Matlack <dmatlack@google.com>
Reviewed-by: Bandan Das <bsd@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/cpuid.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
include/linux/kvm_host.h

index e4f13e714bcfbdde08155bd007b5b6df6e48aa67..74ef58c8ff53301ba1cb798aa4f47922812b53be 100644 (file)
@@ -55,7 +55,6 @@
 #define KVM_REQ_TRIPLE_FAULT      10
 #define KVM_REQ_MMU_SYNC          11
 #define KVM_REQ_CLOCK_UPDATE      12
-#define KVM_REQ_DEACTIVATE_FPU    13
 #define KVM_REQ_EVENT             14
 #define KVM_REQ_APF_HALT          15
 #define KVM_REQ_STEAL_UPDATE      16
@@ -936,8 +935,6 @@ struct kvm_x86_ops {
        unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
        void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
        u32 (*get_pkru)(struct kvm_vcpu *vcpu);
-       void (*fpu_activate)(struct kvm_vcpu *vcpu);
-       void (*fpu_deactivate)(struct kvm_vcpu *vcpu);
 
        void (*tlb_flush)(struct kvm_vcpu *vcpu);
 
index c0e2036217ada0895284c4df8d4629f3bdd73a3c..1d155cc56629a78ac2465c4772170a37a9314ce4 100644 (file)
@@ -123,8 +123,6 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
        if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
                best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
 
-       kvm_x86_ops->fpu_activate(vcpu);
-
        /*
         * The existing code assumes virtual address is 48-bit in the canonical
         * address checks; exit if it is ever changed.
index 4e5905a1ce707f9bc9fcf5428fa87158ac99acfd..d1efe2c62b3f8d0db7392970cdfd8e018dd3ac06 100644 (file)
@@ -1157,7 +1157,6 @@ static void init_vmcb(struct vcpu_svm *svm)
        struct vmcb_control_area *control = &svm->vmcb->control;
        struct vmcb_save_area *save = &svm->vmcb->save;
 
-       svm->vcpu.fpu_active = 1;
        svm->vcpu.arch.hflags = 0;
 
        set_cr_intercept(svm, INTERCEPT_CR0_READ);
@@ -1899,15 +1898,12 @@ static void update_cr0_intercept(struct vcpu_svm *svm)
        ulong gcr0 = svm->vcpu.arch.cr0;
        u64 *hcr0 = &svm->vmcb->save.cr0;
 
-       if (!svm->vcpu.fpu_active)
-               *hcr0 |= SVM_CR0_SELECTIVE_MASK;
-       else
-               *hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
-                       | (gcr0 & SVM_CR0_SELECTIVE_MASK);
+       *hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
+               | (gcr0 & SVM_CR0_SELECTIVE_MASK);
 
        mark_dirty(svm->vmcb, VMCB_CR);
 
-       if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
+       if (gcr0 == *hcr0) {
                clr_cr_intercept(svm, INTERCEPT_CR0_READ);
                clr_cr_intercept(svm, INTERCEPT_CR0_WRITE);
        } else {
@@ -1938,8 +1934,6 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        if (!npt_enabled)
                cr0 |= X86_CR0_PG | X86_CR0_WP;
 
-       if (!vcpu->fpu_active)
-               cr0 |= X86_CR0_TS;
        /*
         * re-enable caching here because the QEMU bios
         * does not do it - this results in some delay at
@@ -2158,22 +2152,6 @@ static int ac_interception(struct vcpu_svm *svm)
        return 1;
 }
 
-static void svm_fpu_activate(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-
-       clr_exception_intercept(svm, NM_VECTOR);
-
-       svm->vcpu.fpu_active = 1;
-       update_cr0_intercept(svm);
-}
-
-static int nm_interception(struct vcpu_svm *svm)
-{
-       svm_fpu_activate(&svm->vcpu);
-       return 1;
-}
-
 static bool is_erratum_383(void)
 {
        int err, i;
@@ -2571,9 +2549,6 @@ static int nested_svm_exit_special(struct vcpu_svm *svm)
                if (!npt_enabled && svm->apf_reason == 0)
                        return NESTED_EXIT_HOST;
                break;
-       case SVM_EXIT_EXCP_BASE + NM_VECTOR:
-               nm_interception(svm);
-               break;
        default:
                break;
        }
@@ -4018,7 +3993,6 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_EXCP_BASE + BP_VECTOR]        = bp_interception,
        [SVM_EXIT_EXCP_BASE + UD_VECTOR]        = ud_interception,
        [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
-       [SVM_EXIT_EXCP_BASE + NM_VECTOR]        = nm_interception,
        [SVM_EXIT_EXCP_BASE + MC_VECTOR]        = mc_interception,
        [SVM_EXIT_EXCP_BASE + AC_VECTOR]        = ac_interception,
        [SVM_EXIT_INTR]                         = intr_interception,
@@ -5072,14 +5046,6 @@ static bool svm_has_wbinvd_exit(void)
        return true;
 }
 
-static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-
-       set_exception_intercept(svm, NM_VECTOR);
-       update_cr0_intercept(svm);
-}
-
 #define PRE_EX(exit)  { .exit_code = (exit), \
                        .stage = X86_ICPT_PRE_EXCEPT, }
 #define POST_EX(exit) { .exit_code = (exit), \
@@ -5340,9 +5306,6 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 
        .get_pkru = svm_get_pkru,
 
-       .fpu_activate = svm_fpu_activate,
-       .fpu_deactivate = svm_fpu_deactivate,
-
        .tlb_flush = svm_flush_tlb,
 
        .run = svm_vcpu_run,
index 0e0b5d09597e2de543f76cd42d5b009e3f8754d5..9856b73a21ad9d8c311431f141745a4200353554 100644 (file)
@@ -1856,7 +1856,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        u32 eb;
 
        eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
-            (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR);
+            (1u << DB_VECTOR) | (1u << AC_VECTOR);
        if ((vcpu->guest_debug &
             (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
            (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
@@ -1865,8 +1865,6 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
                eb = ~0;
        if (enable_ept)
                eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
-       if (vcpu->fpu_active)
-               eb &= ~(1u << NM_VECTOR);
 
        /* When we are running a nested L2 guest and L1 specified for it a
         * certain exception bitmap, we must trap the same exceptions and pass
@@ -2340,25 +2338,6 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
        }
 }
 
-static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
-{
-       ulong cr0;
-
-       if (vcpu->fpu_active)
-               return;
-       vcpu->fpu_active = 1;
-       cr0 = vmcs_readl(GUEST_CR0);
-       cr0 &= ~(X86_CR0_TS | X86_CR0_MP);
-       cr0 |= kvm_read_cr0_bits(vcpu, X86_CR0_TS | X86_CR0_MP);
-       vmcs_writel(GUEST_CR0, cr0);
-       update_exception_bitmap(vcpu);
-       vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
-       if (is_guest_mode(vcpu))
-               vcpu->arch.cr0_guest_owned_bits &=
-                       ~get_vmcs12(vcpu)->cr0_guest_host_mask;
-       vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
-}
-
 static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
 
 /*
@@ -2377,33 +2356,6 @@ static inline unsigned long nested_read_cr4(struct vmcs12 *fields)
                (fields->cr4_read_shadow & fields->cr4_guest_host_mask);
 }
 
-static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
-{
-       /* Note that there is no vcpu->fpu_active = 0 here. The caller must
-        * set this *before* calling this function.
-        */
-       vmx_decache_cr0_guest_bits(vcpu);
-       vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP);
-       update_exception_bitmap(vcpu);
-       vcpu->arch.cr0_guest_owned_bits = 0;
-       vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
-       if (is_guest_mode(vcpu)) {
-               /*
-                * L1's specified read shadow might not contain the TS bit,
-                * so now that we turned on shadowing of this bit, we need to
-                * set this bit of the shadow. Like in nested_vmx_run we need
-                * nested_read_cr0(vmcs12), but vmcs12->guest_cr0 is not yet
-                * up-to-date here because we just decached cr0.TS (and we'll
-                * only update vmcs12->guest_cr0 on nested exit).
-                */
-               struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-               vmcs12->guest_cr0 = (vmcs12->guest_cr0 & ~X86_CR0_TS) |
-                       (vcpu->arch.cr0 & X86_CR0_TS);
-               vmcs_writel(CR0_READ_SHADOW, nested_read_cr0(vmcs12));
-       } else
-               vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
-}
-
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
 {
        unsigned long rflags, save_rflags;
@@ -4232,9 +4184,6 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        if (enable_ept)
                ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
-       if (!vcpu->fpu_active)
-               hw_cr0 |= X86_CR0_TS | X86_CR0_MP;
-
        vmcs_writel(CR0_READ_SHADOW, cr0);
        vmcs_writel(GUEST_CR0, hw_cr0);
        vcpu->arch.cr0 = cr0;
@@ -5321,7 +5270,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        /* 22.2.1, 20.8.1 */
        vm_entry_controls_init(vmx, vmcs_config.vmentry_ctrl);
 
-       vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
+       vmx->vcpu.arch.cr0_guest_owned_bits = X86_CR0_TS;
+       vmcs_writel(CR0_GUEST_HOST_MASK, ~X86_CR0_TS);
+
        set_cr4_guest_host_mask(vmx);
 
        if (vmx_xsaves_supported())
@@ -5425,7 +5376,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        vmx_set_cr0(vcpu, cr0); /* enter rmode */
        vmx_set_cr4(vcpu, 0);
        vmx_set_efer(vcpu, 0);
-       vmx_fpu_activate(vcpu);
+
        update_exception_bitmap(vcpu);
 
        vpid_sync_context(vmx->vpid);
@@ -5698,11 +5649,6 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        if (is_nmi(intr_info))
                return 1;  /* already handled by vmx_vcpu_run() */
 
-       if (is_no_device(intr_info)) {
-               vmx_fpu_activate(vcpu);
-               return 1;
-       }
-
        if (is_invalid_opcode(intr_info)) {
                if (is_guest_mode(vcpu)) {
                        kvm_queue_exception(vcpu, UD_VECTOR);
@@ -5892,22 +5838,6 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
                return kvm_set_cr4(vcpu, val);
 }
 
-/* called to set cr0 as appropriate for clts instruction exit. */
-static void handle_clts(struct kvm_vcpu *vcpu)
-{
-       if (is_guest_mode(vcpu)) {
-               /*
-                * We get here when L2 did CLTS, and L1 didn't shadow CR0.TS
-                * but we did (!fpu_active). We need to keep GUEST_CR0.TS on,
-                * just pretend it's off (also in arch.cr0 for fpu_activate).
-                */
-               vmcs_writel(CR0_READ_SHADOW,
-                       vmcs_readl(CR0_READ_SHADOW) & ~X86_CR0_TS);
-               vcpu->arch.cr0 &= ~X86_CR0_TS;
-       } else
-               vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
-}
-
 static int handle_cr(struct kvm_vcpu *vcpu)
 {
        unsigned long exit_qualification, val;
@@ -5953,9 +5883,9 @@ static int handle_cr(struct kvm_vcpu *vcpu)
                }
                break;
        case 2: /* clts */
-               handle_clts(vcpu);
+               WARN_ONCE(1, "Guest should always own CR0.TS");
+               vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
                trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
-               vmx_fpu_activate(vcpu);
                return kvm_skip_emulated_instruction(vcpu);
        case 1: /*mov from cr*/
                switch (cr) {
@@ -10349,8 +10279,8 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
        }
 
        /*
-        * This sets GUEST_CR0 to vmcs12->guest_cr0, with possibly a modified
-        * TS bit (for lazy fpu) and bits which we consider mandatory enabled.
+        * This sets GUEST_CR0 to vmcs12->guest_cr0, possibly modifying those
+        * bits which we consider mandatory enabled.
         * The CR0_READ_SHADOW is what L2 should have expected to read given
         * the specifications by L1; It's not enough to take
         * vmcs12->cr0_read_shadow because on our cr0_guest_host_mask we we
@@ -10963,24 +10893,15 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
        vmx_set_rflags(vcpu, X86_EFLAGS_FIXED);
        /*
         * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
-        * actually changed, because it depends on the current state of
-        * fpu_active (which may have changed).
-        * Note that vmx_set_cr0 refers to efer set above.
+        * actually changed, because vmx_set_cr0 refers to efer set above.
+        *
+        * CR0_GUEST_HOST_MASK is already set in the original vmcs01
+        * (KVM doesn't change it);
         */
+       vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
        vmx_set_cr0(vcpu, vmcs12->host_cr0);
-       /*
-        * If we did fpu_activate()/fpu_deactivate() during L2's run, we need
-        * to apply the same changes to L1's vmcs. We just set cr0 correctly,
-        * but we also need to update cr0_guest_host_mask and exception_bitmap.
-        */
-       update_exception_bitmap(vcpu);
-       vcpu->arch.cr0_guest_owned_bits = (vcpu->fpu_active ? X86_CR0_TS : 0);
-       vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
 
-       /*
-        * Note that CR4_GUEST_HOST_MASK is already set in the original vmcs01
-        * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask();
-        */
+       /* Same as above - no reason to call set_cr4_guest_host_mask().  */
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        kvm_set_cr4(vcpu, vmcs12->host_cr4);
 
@@ -11609,9 +11530,6 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 
        .get_pkru = vmx_get_pkru,
 
-       .fpu_activate = vmx_fpu_activate,
-       .fpu_deactivate = vmx_fpu_deactivate,
-
        .tlb_flush = vmx_flush_tlb,
 
        .run = vmx_vcpu_run,
index 8d3047c8cce7991684f51f25e18e0bb6b8550465..c48404017e4fb91cf6df49b3b74cd8953446a201 100644 (file)
@@ -6751,10 +6751,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                        r = 0;
                        goto out;
                }
-               if (kvm_check_request(KVM_REQ_DEACTIVATE_FPU, vcpu)) {
-                       vcpu->fpu_active = 0;
-                       kvm_x86_ops->fpu_deactivate(vcpu);
-               }
                if (kvm_check_request(KVM_REQ_APF_HALT, vcpu)) {
                        /* Page is swapped out. Do synthetic halt */
                        vcpu->arch.apf.halted = true;
@@ -6856,8 +6852,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        preempt_disable();
 
        kvm_x86_ops->prepare_guest_switch(vcpu);
-       if (vcpu->fpu_active)
-               kvm_load_guest_fpu(vcpu);
+       kvm_load_guest_fpu(vcpu);
 
        /*
         * Disable IRQs before setting IN_GUEST_MODE.  Posted interrupt
index 2db458ee94b03f385d1c4e2c6d0ec19381528d7c..8d69d51507483871f0da69e6e641c964eb451583 100644 (file)
@@ -221,7 +221,6 @@ struct kvm_vcpu {
        struct mutex mutex;
        struct kvm_run *run;
 
-       int fpu_active;
        int guest_fpu_loaded, guest_xcr0_loaded;
        struct swait_queue_head wq;
        struct pid *pid;