KVM: VMX: Avoid writing HOST_CR0 every entry
authorAvi Kivity <avi@redhat.com>
Mon, 3 May 2010 13:05:44 +0000 (16:05 +0300)
committerAvi Kivity <avi@redhat.com>
Sun, 1 Aug 2010 07:35:28 +0000 (10:35 +0300)
cr0.ts may change between entries, so we copy cr0 to HOST_CR0 before each
entry.  That is slow, so instead, set HOST_CR0 to have TS set unconditionally
(which is a safe value), and issue a clts() just before exiting vcpu context
if the task indeed owns the fpu.

Saves ~50 cycles/exit.

Signed-off-by: Avi Kivity <avi@redhat.com>
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c

index 6425207..5989317 100644 (file)
@@ -812,6 +812,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
                wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
        }
 #endif
+       if (current_thread_info()->status & TS_USEDFPU)
+               clts();
 }
 
 static void vmx_load_host_state(struct vcpu_vmx *vmx)
@@ -2507,7 +2509,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
        vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
 
-       vmcs_writel(HOST_CR0, read_cr0());  /* 22.2.3 */
+       vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS);  /* 22.2.3 */
        vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
        vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
 
@@ -3859,11 +3861,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
                vmx_set_interrupt_shadow(vcpu, 0);
 
-       /*
-        * Loading guest fpu may have cleared host cr0.ts
-        */
-       vmcs_writel(HOST_CR0, read_cr0());
-
        asm(
                /* Store host registers */
                "push %%"R"dx; push %%"R"bp;"
index 1b270fd..801afc6 100644 (file)
@@ -1731,8 +1731,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
-       kvm_put_guest_fpu(vcpu);
        kvm_x86_ops->vcpu_put(vcpu);
+       kvm_put_guest_fpu(vcpu);
 }
 
 static int is_efer_nx(void)