aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/mmu.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-06-04 08:58:30 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-16 05:05:45 -0400
commit17c3ba9d37dbda490792a2b52953f09d0dee30d6 (patch)
tree44749b8658b61c7aa6cdb38d7823fa061d24b12c /drivers/kvm/mmu.c
parentbd2b2baa5c5fbb08b4b0df7508ff419407f7ece6 (diff)
KVM: Lazy guest cr3 switching
Switch guest paging context may require us to allocate memory, which might fail. Instead of wiring up error paths everywhere, make context switching lazy and actually do the switch before the next guest entry, where we can return an error if allocation fails. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/mmu.c')
-rw-r--r--drivers/kvm/mmu.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 283df031b03d..5915d7a1c4f7 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -949,9 +949,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu)
949 context->free = nonpaging_free; 949 context->free = nonpaging_free;
950 context->root_level = 0; 950 context->root_level = 0;
951 context->shadow_root_level = PT32E_ROOT_LEVEL; 951 context->shadow_root_level = PT32E_ROOT_LEVEL;
952 mmu_alloc_roots(vcpu); 952 context->root_hpa = INVALID_PAGE;
953 ASSERT(VALID_PAGE(context->root_hpa));
954 kvm_arch_ops->set_cr3(vcpu, context->root_hpa);
955 return 0; 953 return 0;
956} 954}
957 955
@@ -965,11 +963,6 @@ static void paging_new_cr3(struct kvm_vcpu *vcpu)
965{ 963{
966 pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->cr3); 964 pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->cr3);
967 mmu_free_roots(vcpu); 965 mmu_free_roots(vcpu);
968 if (unlikely(vcpu->kvm->n_free_mmu_pages < KVM_MIN_FREE_MMU_PAGES))
969 kvm_mmu_free_some_pages(vcpu);
970 mmu_alloc_roots(vcpu);
971 kvm_mmu_flush_tlb(vcpu);
972 kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
973} 966}
974 967
975static void inject_page_fault(struct kvm_vcpu *vcpu, 968static void inject_page_fault(struct kvm_vcpu *vcpu,
@@ -1003,10 +996,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
1003 context->free = paging_free; 996 context->free = paging_free;
1004 context->root_level = level; 997 context->root_level = level;
1005 context->shadow_root_level = level; 998 context->shadow_root_level = level;
1006 mmu_alloc_roots(vcpu); 999 context->root_hpa = INVALID_PAGE;
1007 ASSERT(VALID_PAGE(context->root_hpa));
1008 kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
1009 (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
1010 return 0; 1000 return 0;
1011} 1001}
1012 1002
@@ -1025,10 +1015,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu)
1025 context->free = paging_free; 1015 context->free = paging_free;
1026 context->root_level = PT32_ROOT_LEVEL; 1016 context->root_level = PT32_ROOT_LEVEL;
1027 context->shadow_root_level = PT32E_ROOT_LEVEL; 1017 context->shadow_root_level = PT32E_ROOT_LEVEL;
1028 mmu_alloc_roots(vcpu); 1018 context->root_hpa = INVALID_PAGE;
1029 ASSERT(VALID_PAGE(context->root_hpa));
1030 kvm_arch_ops->set_cr3(vcpu, context->root_hpa |
1031 (vcpu->cr3 & (CR3_PCD_MASK | CR3_WPT_MASK)));
1032 return 0; 1019 return 0;
1033} 1020}
1034 1021
@@ -1042,7 +1029,6 @@ static int init_kvm_mmu(struct kvm_vcpu *vcpu)
1042 ASSERT(vcpu); 1029 ASSERT(vcpu);
1043 ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa)); 1030 ASSERT(!VALID_PAGE(vcpu->mmu.root_hpa));
1044 1031
1045 mmu_topup_memory_caches(vcpu);
1046 if (!is_paging(vcpu)) 1032 if (!is_paging(vcpu))
1047 return nonpaging_init_context(vcpu); 1033 return nonpaging_init_context(vcpu);
1048 else if (is_long_mode(vcpu)) 1034 else if (is_long_mode(vcpu))
@@ -1064,16 +1050,31 @@ static void destroy_kvm_mmu(struct kvm_vcpu *vcpu)
1064 1050
1065int kvm_mmu_reset_context(struct kvm_vcpu *vcpu) 1051int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
1066{ 1052{
1053 destroy_kvm_mmu(vcpu);
1054 return init_kvm_mmu(vcpu);
1055}
1056
1057int kvm_mmu_load(struct kvm_vcpu *vcpu)
1058{
1067 int r; 1059 int r;
1068 1060
1069 destroy_kvm_mmu(vcpu); 1061 spin_lock(&vcpu->kvm->lock);
1070 r = init_kvm_mmu(vcpu);
1071 if (r < 0)
1072 goto out;
1073 r = mmu_topup_memory_caches(vcpu); 1062 r = mmu_topup_memory_caches(vcpu);
1063 if (r)
1064 goto out;
1065 mmu_alloc_roots(vcpu);
1066 kvm_arch_ops->set_cr3(vcpu, vcpu->mmu.root_hpa);
1067 kvm_mmu_flush_tlb(vcpu);
1074out: 1068out:
1069 spin_unlock(&vcpu->kvm->lock);
1075 return r; 1070 return r;
1076} 1071}
1072EXPORT_SYMBOL_GPL(kvm_mmu_load);
1073
1074void kvm_mmu_unload(struct kvm_vcpu *vcpu)
1075{
1076 mmu_free_roots(vcpu);
1077}
1077 1078
1078static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu, 1079static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
1079 struct kvm_mmu_page *page, 1080 struct kvm_mmu_page *page,