aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-10-28 12:48:59 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:57 -0500
commit3067714cf59bd4a6dbf788b709485bc62c1ff845 (patch)
tree4cdfba475258886666150e638568e6ad5e8c0e2f
parentc7e75a3db4ecd952e7a5562cea1b27007bf0c01c (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.c36
-rw-r--r--drivers/kvm/svm.c33
-rw-r--r--drivers/kvm/vmx.c29
-rw-r--r--drivers/kvm/x86.h6
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
1350int 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 }
1380out:
1381 mutex_unlock(&vcpu->kvm->lock);
1382 return r;
1383}
1384EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
1385
1350static void free_mmu_pages(struct kvm_vcpu *vcpu) 1386static 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
977static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) 946static 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
88static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, 88int 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
94static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) 90static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
95{ 91{