diff options
author | Avi Kivity <avi@qumranet.com> | 2007-10-28 12:48:59 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:57 -0500 |
commit | 3067714cf59bd4a6dbf788b709485bc62c1ff845 (patch) | |
tree | 4cdfba475258886666150e638568e6ad5e8c0e2f | |
parent | c7e75a3db4ecd952e7a5562cea1b27007bf0c01c (diff) |
KVM: Move page fault processing to common code
The code that dispatches the page fault and emulates if we failed to map
is duplicated across vmx and svm. Merge it to simplify further bugfixing.
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/mmu.c | 36 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 33 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 29 | ||||
-rw-r--r-- | drivers/kvm/x86.h | 6 |
4 files changed, 39 insertions, 65 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index d9c5950cfae1..ace3cb86214b 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
@@ -1347,6 +1347,42 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) | |||
1347 | } | 1347 | } |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code) | ||
1351 | { | ||
1352 | int r; | ||
1353 | enum emulation_result er; | ||
1354 | |||
1355 | mutex_lock(&vcpu->kvm->lock); | ||
1356 | r = vcpu->mmu.page_fault(vcpu, cr2, error_code); | ||
1357 | if (r < 0) | ||
1358 | goto out; | ||
1359 | |||
1360 | if (!r) { | ||
1361 | r = 1; | ||
1362 | goto out; | ||
1363 | } | ||
1364 | |||
1365 | er = emulate_instruction(vcpu, vcpu->run, cr2, error_code, 0); | ||
1366 | mutex_unlock(&vcpu->kvm->lock); | ||
1367 | |||
1368 | switch (er) { | ||
1369 | case EMULATE_DONE: | ||
1370 | return 1; | ||
1371 | case EMULATE_DO_MMIO: | ||
1372 | ++vcpu->stat.mmio_exits; | ||
1373 | return 0; | ||
1374 | case EMULATE_FAIL: | ||
1375 | kvm_report_emulation_failure(vcpu, "pagetable"); | ||
1376 | return 1; | ||
1377 | default: | ||
1378 | BUG(); | ||
1379 | } | ||
1380 | out: | ||
1381 | mutex_unlock(&vcpu->kvm->lock); | ||
1382 | return r; | ||
1383 | } | ||
1384 | EXPORT_SYMBOL_GPL(kvm_mmu_page_fault); | ||
1385 | |||
1350 | static void free_mmu_pages(struct kvm_vcpu *vcpu) | 1386 | static void free_mmu_pages(struct kvm_vcpu *vcpu) |
1351 | { | 1387 | { |
1352 | struct kvm_mmu_page *page; | 1388 | struct kvm_mmu_page *page; |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index fe2a5e8b0524..97863f8fd001 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -933,45 +933,14 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | |||
933 | struct kvm *kvm = svm->vcpu.kvm; | 933 | struct kvm *kvm = svm->vcpu.kvm; |
934 | u64 fault_address; | 934 | u64 fault_address; |
935 | u32 error_code; | 935 | u32 error_code; |
936 | enum emulation_result er; | ||
937 | int r; | ||
938 | 936 | ||
939 | if (!irqchip_in_kernel(kvm) && | 937 | if (!irqchip_in_kernel(kvm) && |
940 | is_external_interrupt(exit_int_info)) | 938 | is_external_interrupt(exit_int_info)) |
941 | push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); | 939 | push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); |
942 | 940 | ||
943 | mutex_lock(&kvm->lock); | ||
944 | |||
945 | fault_address = svm->vmcb->control.exit_info_2; | 941 | fault_address = svm->vmcb->control.exit_info_2; |
946 | error_code = svm->vmcb->control.exit_info_1; | 942 | error_code = svm->vmcb->control.exit_info_1; |
947 | r = kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); | 943 | return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); |
948 | if (r < 0) { | ||
949 | mutex_unlock(&kvm->lock); | ||
950 | return r; | ||
951 | } | ||
952 | if (!r) { | ||
953 | mutex_unlock(&kvm->lock); | ||
954 | return 1; | ||
955 | } | ||
956 | er = emulate_instruction(&svm->vcpu, kvm_run, fault_address, | ||
957 | error_code, 0); | ||
958 | mutex_unlock(&kvm->lock); | ||
959 | |||
960 | switch (er) { | ||
961 | case EMULATE_DONE: | ||
962 | return 1; | ||
963 | case EMULATE_DO_MMIO: | ||
964 | ++svm->vcpu.stat.mmio_exits; | ||
965 | return 0; | ||
966 | case EMULATE_FAIL: | ||
967 | kvm_report_emulation_failure(&svm->vcpu, "pagetable"); | ||
968 | break; | ||
969 | default: | ||
970 | BUG(); | ||
971 | } | ||
972 | |||
973 | kvm_run->exit_reason = KVM_EXIT_UNKNOWN; | ||
974 | return 0; | ||
975 | } | 944 | } |
976 | 945 | ||
977 | static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | 946 | static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 2d7d638d72d0..7fe834cb0d81 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1796,7 +1796,6 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1796 | unsigned long cr2, rip; | 1796 | unsigned long cr2, rip; |
1797 | u32 vect_info; | 1797 | u32 vect_info; |
1798 | enum emulation_result er; | 1798 | enum emulation_result er; |
1799 | int r; | ||
1800 | 1799 | ||
1801 | vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); | 1800 | vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); |
1802 | intr_info = vmcs_read32(VM_EXIT_INTR_INFO); | 1801 | intr_info = vmcs_read32(VM_EXIT_INTR_INFO); |
@@ -1834,33 +1833,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1834 | error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); | 1833 | error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); |
1835 | if (is_page_fault(intr_info)) { | 1834 | if (is_page_fault(intr_info)) { |
1836 | cr2 = vmcs_readl(EXIT_QUALIFICATION); | 1835 | cr2 = vmcs_readl(EXIT_QUALIFICATION); |
1837 | 1836 | return kvm_mmu_page_fault(vcpu, cr2, error_code); | |
1838 | mutex_lock(&vcpu->kvm->lock); | ||
1839 | r = kvm_mmu_page_fault(vcpu, cr2, error_code); | ||
1840 | if (r < 0) { | ||
1841 | mutex_unlock(&vcpu->kvm->lock); | ||
1842 | return r; | ||
1843 | } | ||
1844 | if (!r) { | ||
1845 | mutex_unlock(&vcpu->kvm->lock); | ||
1846 | return 1; | ||
1847 | } | ||
1848 | |||
1849 | er = emulate_instruction(vcpu, kvm_run, cr2, error_code, 0); | ||
1850 | mutex_unlock(&vcpu->kvm->lock); | ||
1851 | |||
1852 | switch (er) { | ||
1853 | case EMULATE_DONE: | ||
1854 | return 1; | ||
1855 | case EMULATE_DO_MMIO: | ||
1856 | ++vcpu->stat.mmio_exits; | ||
1857 | return 0; | ||
1858 | case EMULATE_FAIL: | ||
1859 | kvm_report_emulation_failure(vcpu, "pagetable"); | ||
1860 | break; | ||
1861 | default: | ||
1862 | BUG(); | ||
1863 | } | ||
1864 | } | 1837 | } |
1865 | 1838 | ||
1866 | if (vcpu->rmode.active && | 1839 | if (vcpu->rmode.active && |
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h index 01452b552db3..20da8e9751c0 100644 --- a/drivers/kvm/x86.h +++ b/drivers/kvm/x86.h | |||
@@ -85,11 +85,7 @@ struct kvm_vcpu { | |||
85 | struct x86_emulate_ctxt emulate_ctxt; | 85 | struct x86_emulate_ctxt emulate_ctxt; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, | 88 | int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code); |
89 | u32 error_code) | ||
90 | { | ||
91 | return vcpu->mmu.page_fault(vcpu, gva, error_code); | ||
92 | } | ||
93 | 89 | ||
94 | static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) | 90 | static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) |
95 | { | 91 | { |