aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h2
-rw-r--r--drivers/kvm/svm.c35
2 files changed, 33 insertions, 4 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index d1a90c5d76ce..61ff085df7e6 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -63,6 +63,7 @@
63#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN) 63#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
64 64
65#define DE_VECTOR 0 65#define DE_VECTOR 0
66#define NM_VECTOR 7
66#define DF_VECTOR 8 67#define DF_VECTOR 8
67#define TS_VECTOR 10 68#define TS_VECTOR 10
68#define NP_VECTOR 11 69#define NP_VECTOR 11
@@ -301,6 +302,7 @@ struct kvm_vcpu {
301 char fx_buf[FX_BUF_SIZE]; 302 char fx_buf[FX_BUF_SIZE];
302 char *host_fx_image; 303 char *host_fx_image;
303 char *guest_fx_image; 304 char *guest_fx_image;
305 int fpu_active;
304 306
305 int mmio_needed; 307 int mmio_needed;
306 int mmio_read_completed; 308 int mmio_read_completed;
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 644efc5381ad..2a7a0390bfb1 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -587,6 +587,7 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu)
587 init_vmcb(vcpu->svm->vmcb); 587 init_vmcb(vcpu->svm->vmcb);
588 588
589 fx_init(vcpu); 589 fx_init(vcpu);
590 vcpu->fpu_active = 1;
590 vcpu->apic_base = 0xfee00000 | 591 vcpu->apic_base = 0xfee00000 |
591 /*for vcpu 0*/ MSR_IA32_APICBASE_BSP | 592 /*for vcpu 0*/ MSR_IA32_APICBASE_BSP |
592 MSR_IA32_APICBASE_ENABLE; 593 MSR_IA32_APICBASE_ENABLE;
@@ -756,6 +757,11 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
756 } 757 }
757 } 758 }
758#endif 759#endif
760 if ((vcpu->cr0 & CR0_TS_MASK) && !(cr0 & CR0_TS_MASK)) {
761 vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
762 vcpu->fpu_active = 1;
763 }
764
759 vcpu->cr0 = cr0; 765 vcpu->cr0 = cr0;
760 cr0 |= CR0_PG_MASK | CR0_WP_MASK; 766 cr0 |= CR0_PG_MASK | CR0_WP_MASK;
761 cr0 &= ~(CR0_CD_MASK | CR0_NW_MASK); 767 cr0 &= ~(CR0_CD_MASK | CR0_NW_MASK);
@@ -928,6 +934,16 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
928 return 0; 934 return 0;
929} 935}
930 936
937static int nm_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
938{
939 vcpu->svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
940 if (!(vcpu->cr0 & CR0_TS_MASK))
941 vcpu->svm->vmcb->save.cr0 &= ~CR0_TS_MASK;
942 vcpu->fpu_active = 1;
943
944 return 1;
945}
946
931static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 947static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
932{ 948{
933 /* 949 /*
@@ -1292,6 +1308,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu,
1292 [SVM_EXIT_WRITE_DR5] = emulate_on_interception, 1308 [SVM_EXIT_WRITE_DR5] = emulate_on_interception,
1293 [SVM_EXIT_WRITE_DR7] = emulate_on_interception, 1309 [SVM_EXIT_WRITE_DR7] = emulate_on_interception,
1294 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, 1310 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
1311 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
1295 [SVM_EXIT_INTR] = nop_on_interception, 1312 [SVM_EXIT_INTR] = nop_on_interception,
1296 [SVM_EXIT_NMI] = nop_on_interception, 1313 [SVM_EXIT_NMI] = nop_on_interception,
1297 [SVM_EXIT_SMI] = nop_on_interception, 1314 [SVM_EXIT_SMI] = nop_on_interception,
@@ -1481,8 +1498,10 @@ again:
1481 load_db_regs(vcpu->svm->db_regs); 1498 load_db_regs(vcpu->svm->db_regs);
1482 } 1499 }
1483 1500
1484 fx_save(vcpu->host_fx_image); 1501 if (vcpu->fpu_active) {
1485 fx_restore(vcpu->guest_fx_image); 1502 fx_save(vcpu->host_fx_image);
1503 fx_restore(vcpu->guest_fx_image);
1504 }
1486 1505
1487 asm volatile ( 1506 asm volatile (
1488#ifdef CONFIG_X86_64 1507#ifdef CONFIG_X86_64
@@ -1593,8 +1612,10 @@ again:
1593#endif 1612#endif
1594 : "cc", "memory" ); 1613 : "cc", "memory" );
1595 1614
1596 fx_save(vcpu->guest_fx_image); 1615 if (vcpu->fpu_active) {
1597 fx_restore(vcpu->host_fx_image); 1616 fx_save(vcpu->guest_fx_image);
1617 fx_restore(vcpu->host_fx_image);
1618 }
1598 1619
1599 if ((vcpu->svm->vmcb->save.dr7 & 0xff)) 1620 if ((vcpu->svm->vmcb->save.dr7 & 0xff))
1600 load_db_regs(vcpu->svm->host_db_regs); 1621 load_db_regs(vcpu->svm->host_db_regs);
@@ -1664,6 +1685,12 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
1664{ 1685{
1665 vcpu->svm->vmcb->save.cr3 = root; 1686 vcpu->svm->vmcb->save.cr3 = root;
1666 force_new_asid(vcpu); 1687 force_new_asid(vcpu);
1688
1689 if (vcpu->fpu_active) {
1690 vcpu->svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
1691 vcpu->svm->vmcb->save.cr0 |= CR0_TS_MASK;
1692 vcpu->fpu_active = 0;
1693 }
1667} 1694}
1668 1695
1669static void svm_inject_page_fault(struct kvm_vcpu *vcpu, 1696static void svm_inject_page_fault(struct kvm_vcpu *vcpu,