diff options
-rw-r--r-- | drivers/kvm/kvm.h | 10 | ||||
-rw-r--r-- | drivers/kvm/mmu.c | 43 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 4 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 4 |
4 files changed, 40 insertions, 21 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 199e1e9bae25..3ec4e26b9bd7 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -544,6 +544,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
544 | const u8 *old, const u8 *new, int bytes); | 544 | const u8 *old, const u8 *new, int bytes); |
545 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); | 545 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); |
546 | void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu); | 546 | void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu); |
547 | int kvm_mmu_load(struct kvm_vcpu *vcpu); | ||
548 | void kvm_mmu_unload(struct kvm_vcpu *vcpu); | ||
547 | 549 | ||
548 | int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run); | 550 | int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run); |
549 | 551 | ||
@@ -555,6 +557,14 @@ static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, | |||
555 | return vcpu->mmu.page_fault(vcpu, gva, error_code); | 557 | return vcpu->mmu.page_fault(vcpu, gva, error_code); |
556 | } | 558 | } |
557 | 559 | ||
560 | static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu) | ||
561 | { | ||
562 | if (likely(vcpu->mmu.root_hpa != INVALID_PAGE)) | ||
563 | return 0; | ||
564 | |||
565 | return kvm_mmu_load(vcpu); | ||
566 | } | ||
567 | |||
558 | static inline int is_long_mode(struct kvm_vcpu *vcpu) | 568 | static inline int is_long_mode(struct kvm_vcpu *vcpu) |
559 | { | 569 | { |
560 | #ifdef CONFIG_X86_64 | 570 | #ifdef CONFIG_X86_64 |
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 | ||
975 | static void inject_page_fault(struct kvm_vcpu *vcpu, | 968 | static 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 | ||
1065 | int kvm_mmu_reset_context(struct kvm_vcpu *vcpu) | 1051 | int kvm_mmu_reset_context(struct kvm_vcpu *vcpu) |
1066 | { | 1052 | { |
1053 | destroy_kvm_mmu(vcpu); | ||
1054 | return init_kvm_mmu(vcpu); | ||
1055 | } | ||
1056 | |||
1057 | int 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); | ||
1074 | out: | 1068 | out: |
1069 | spin_unlock(&vcpu->kvm->lock); | ||
1075 | return r; | 1070 | return r; |
1076 | } | 1071 | } |
1072 | EXPORT_SYMBOL_GPL(kvm_mmu_load); | ||
1073 | |||
1074 | void kvm_mmu_unload(struct kvm_vcpu *vcpu) | ||
1075 | { | ||
1076 | mmu_free_roots(vcpu); | ||
1077 | } | ||
1077 | 1078 | ||
1078 | static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu, | 1079 | static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu, |
1079 | struct kvm_mmu_page *page, | 1080 | struct kvm_mmu_page *page, |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 6cd6a50a0340..ec040e2f8c58 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -1483,6 +1483,10 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1483 | int r; | 1483 | int r; |
1484 | 1484 | ||
1485 | again: | 1485 | again: |
1486 | r = kvm_mmu_reload(vcpu); | ||
1487 | if (unlikely(r)) | ||
1488 | return r; | ||
1489 | |||
1486 | if (!vcpu->mmio_read_completed) | 1490 | if (!vcpu->mmio_read_completed) |
1487 | do_interrupt_requests(vcpu, kvm_run); | 1491 | do_interrupt_requests(vcpu, kvm_run); |
1488 | 1492 | ||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 93e5bb2c40e3..4d255493a57e 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1988,6 +1988,10 @@ again: | |||
1988 | vmx_save_host_state(vcpu); | 1988 | vmx_save_host_state(vcpu); |
1989 | kvm_load_guest_fpu(vcpu); | 1989 | kvm_load_guest_fpu(vcpu); |
1990 | 1990 | ||
1991 | r = kvm_mmu_reload(vcpu); | ||
1992 | if (unlikely(r)) | ||
1993 | goto out; | ||
1994 | |||
1991 | /* | 1995 | /* |
1992 | * Loading guest fpu may have cleared host cr0.ts | 1996 | * Loading guest fpu may have cleared host cr0.ts |
1993 | */ | 1997 | */ |