aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-30 05:40:26 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:35:50 -0500
commit02daab21d94dc4cf01b2fd09863d59a436900322 (patch)
treee7caff282dd9019e1b19cd549609c6b991f29152 /arch/x86/kvm/svm.c
parente8467fda83cdc9de53972fee0cd2e6916cf66f41 (diff)
KVM: Lazify fpu activation and deactivation
Defer fpu deactivation as much as possible - if the guest fpu is loaded, keep it loaded until the next heavyweight exit (where we are forced to unload it). This reduces unnecessary exits. We also defer fpu activation on clts; while clts signals the intent to use the fpu, we can't be sure the guest will actually use it. Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c35
1 files changed, 21 insertions, 14 deletions
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