diff options
| author | Anthony Liguori <aliguori@us.ibm.com> | 2007-04-23 10:17:21 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@qumranet.com> | 2007-05-03 03:52:31 -0400 |
| commit | 7807fa6ca5af2e5660a0eb3cd90276ca0c5bdfc8 (patch) | |
| tree | 8f97af3538acc40a6a72af29f31351d8f0f69296 /drivers/kvm | |
| parent | 4c690a1e8667a84b61a6114a4ad293681f32cb11 (diff) | |
KVM: Lazy FPU support for SVM
Avoid saving and restoring the guest fpu state on every exit. This
shaves ~100 cycles off the guest/host switch.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm')
| -rw-r--r-- | drivers/kvm/kvm.h | 2 | ||||
| -rw-r--r-- | drivers/kvm/svm.c | 35 |
2 files changed, 33 insertions, 4 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index d1a90c5d76..61ff085df7 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 644efc5381..2a7a0390bf 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 | ||
| 937 | static 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 | |||
| 931 | static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 947 | static 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 | ||
| 1669 | static void svm_inject_page_fault(struct kvm_vcpu *vcpu, | 1696 | static void svm_inject_page_fault(struct kvm_vcpu *vcpu, |
