aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-05-31 11:41:29 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:46 -0400
commit8f5d549f028056d6ad6044f2d9e27ecf361d955e (patch)
tree86575599cd4427a6d22e051c021f2529a36e2bf7 /arch/x86/kvm/vmx.c
parent2d84e993a8947dbeb6b416555940d97522330846 (diff)
KVM: VMX: Simplify pdptr and cr3 management
Instead of reading the PDPTRs from memory after every exit (which is slow and wrong, as the PDPTRs are stored on the cpu), sync the PDPTRs from memory to the VMCS before entry, and from the VMCS to memory after exit. Do the same for cr3. Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ea0e1d5ebe70..752465f98bfd 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1547,10 +1547,6 @@ static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
1547static void ept_load_pdptrs(struct kvm_vcpu *vcpu) 1547static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
1548{ 1548{
1549 if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) { 1549 if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
1550 if (!load_pdptrs(vcpu, vcpu->arch.cr3)) {
1551 printk(KERN_ERR "EPT: Fail to load pdptrs!\n");
1552 return;
1553 }
1554 vmcs_write64(GUEST_PDPTR0, vcpu->arch.pdptrs[0]); 1550 vmcs_write64(GUEST_PDPTR0, vcpu->arch.pdptrs[0]);
1555 vmcs_write64(GUEST_PDPTR1, vcpu->arch.pdptrs[1]); 1551 vmcs_write64(GUEST_PDPTR1, vcpu->arch.pdptrs[1]);
1556 vmcs_write64(GUEST_PDPTR2, vcpu->arch.pdptrs[2]); 1552 vmcs_write64(GUEST_PDPTR2, vcpu->arch.pdptrs[2]);
@@ -1558,6 +1554,16 @@ static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
1558 } 1554 }
1559} 1555}
1560 1556
1557static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
1558{
1559 if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
1560 vcpu->arch.pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
1561 vcpu->arch.pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
1562 vcpu->arch.pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
1563 vcpu->arch.pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
1564 }
1565}
1566
1561static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); 1567static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
1562 1568
1563static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, 1569static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
@@ -1651,7 +1657,6 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
1651 if (enable_ept) { 1657 if (enable_ept) {
1652 eptp = construct_eptp(cr3); 1658 eptp = construct_eptp(cr3);
1653 vmcs_write64(EPT_POINTER, eptp); 1659 vmcs_write64(EPT_POINTER, eptp);
1654 ept_load_pdptrs(vcpu);
1655 guest_cr3 = is_paging(vcpu) ? vcpu->arch.cr3 : 1660 guest_cr3 = is_paging(vcpu) ? vcpu->arch.cr3 :
1656 VMX_EPT_IDENTITY_PAGETABLE_ADDR; 1661 VMX_EPT_IDENTITY_PAGETABLE_ADDR;
1657 } 1662 }
@@ -3252,7 +3257,7 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
3252 * to sync with guest real CR3. */ 3257 * to sync with guest real CR3. */
3253 if (enable_ept && is_paging(vcpu)) { 3258 if (enable_ept && is_paging(vcpu)) {
3254 vcpu->arch.cr3 = vmcs_readl(GUEST_CR3); 3259 vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
3255 ept_load_pdptrs(vcpu); 3260 ept_save_pdptrs(vcpu);
3256 } 3261 }
3257 3262
3258 if (unlikely(vmx->fail)) { 3263 if (unlikely(vmx->fail)) {
@@ -3437,6 +3442,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3437{ 3442{
3438 struct vcpu_vmx *vmx = to_vmx(vcpu); 3443 struct vcpu_vmx *vmx = to_vmx(vcpu);
3439 3444
3445 if (enable_ept && is_paging(vcpu)) {
3446 vmcs_writel(GUEST_CR3, vcpu->arch.cr3);
3447 ept_load_pdptrs(vcpu);
3448 }
3440 /* Record the guest's net vcpu time for enforced NMI injections. */ 3449 /* Record the guest's net vcpu time for enforced NMI injections. */
3441 if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) 3450 if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
3442 vmx->entry_time = ktime_get(); 3451 vmx->entry_time = ktime_get();