diff options
author | Avi Kivity <avi@qumranet.com> | 2007-11-25 07:04:58 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:53:18 -0500 |
commit | c3c91fee5195ba5176a6da5ddc2a2822243eb79f (patch) | |
tree | 1fcccd77e5705d5f885bbb24ecb08bd93cf71c63 /drivers | |
parent | 298101da2f507c13eaf179ee4507a7c0fe3e7b06 (diff) |
KVM: Replace page fault injection by the generalized exception queue
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/mmu.c | 2 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 35 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 32 | ||||
-rw-r--r-- | drivers/kvm/x86.c | 17 | ||||
-rw-r--r-- | drivers/kvm/x86.h | 4 |
5 files changed, 19 insertions, 71 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index 9b9d1b6eb2f8..62a74151f847 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
@@ -1081,7 +1081,7 @@ static void inject_page_fault(struct kvm_vcpu *vcpu, | |||
1081 | u64 addr, | 1081 | u64 addr, |
1082 | u32 err_code) | 1082 | u32 err_code) |
1083 | { | 1083 | { |
1084 | kvm_x86_ops->inject_page_fault(vcpu, addr, err_code); | 1084 | kvm_inject_page_fault(vcpu, addr, err_code); |
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | static void paging_free(struct kvm_vcpu *vcpu) | 1087 | static void paging_free(struct kvm_vcpu *vcpu) |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 87072c647f28..aa8e90b404a0 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -225,12 +225,6 @@ static void inject_ud(struct kvm_vcpu *vcpu) | |||
225 | UD_VECTOR; | 225 | UD_VECTOR; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int is_page_fault(uint32_t info) | ||
229 | { | ||
230 | info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; | ||
231 | return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT); | ||
232 | } | ||
233 | |||
234 | static int is_external_interrupt(u32 info) | 228 | static int is_external_interrupt(u32 info) |
235 | { | 229 | { |
236 | info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; | 230 | info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID; |
@@ -1624,34 +1618,6 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) | |||
1624 | } | 1618 | } |
1625 | } | 1619 | } |
1626 | 1620 | ||
1627 | static void svm_inject_page_fault(struct kvm_vcpu *vcpu, | ||
1628 | unsigned long addr, | ||
1629 | uint32_t err_code) | ||
1630 | { | ||
1631 | struct vcpu_svm *svm = to_svm(vcpu); | ||
1632 | uint32_t exit_int_info = svm->vmcb->control.exit_int_info; | ||
1633 | |||
1634 | ++vcpu->stat.pf_guest; | ||
1635 | |||
1636 | if (is_page_fault(exit_int_info)) { | ||
1637 | |||
1638 | svm->vmcb->control.event_inj_err = 0; | ||
1639 | svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
1640 | SVM_EVTINJ_VALID_ERR | | ||
1641 | SVM_EVTINJ_TYPE_EXEPT | | ||
1642 | DF_VECTOR; | ||
1643 | return; | ||
1644 | } | ||
1645 | vcpu->cr2 = addr; | ||
1646 | svm->vmcb->save.cr2 = addr; | ||
1647 | svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | | ||
1648 | SVM_EVTINJ_VALID_ERR | | ||
1649 | SVM_EVTINJ_TYPE_EXEPT | | ||
1650 | PF_VECTOR; | ||
1651 | svm->vmcb->control.event_inj_err = err_code; | ||
1652 | } | ||
1653 | |||
1654 | |||
1655 | static int is_disabled(void) | 1621 | static int is_disabled(void) |
1656 | { | 1622 | { |
1657 | u64 vm_cr; | 1623 | u64 vm_cr; |
@@ -1721,7 +1687,6 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
1721 | .set_rflags = svm_set_rflags, | 1687 | .set_rflags = svm_set_rflags, |
1722 | 1688 | ||
1723 | .tlb_flush = svm_flush_tlb, | 1689 | .tlb_flush = svm_flush_tlb, |
1724 | .inject_page_fault = svm_inject_page_fault, | ||
1725 | 1690 | ||
1726 | .inject_gp = svm_inject_gp, | 1691 | .inject_gp = svm_inject_gp, |
1727 | 1692 | ||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index f382956f176a..be0b12e709e5 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -2487,37 +2487,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2487 | asm("int $2"); | 2487 | asm("int $2"); |
2488 | } | 2488 | } |
2489 | 2489 | ||
2490 | static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, | ||
2491 | unsigned long addr, | ||
2492 | u32 err_code) | ||
2493 | { | ||
2494 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
2495 | u32 vect_info = vmx->idt_vectoring_info; | ||
2496 | |||
2497 | ++vcpu->stat.pf_guest; | ||
2498 | |||
2499 | if (is_page_fault(vect_info)) { | ||
2500 | printk(KERN_DEBUG "inject_page_fault: " | ||
2501 | "double fault 0x%lx @ 0x%lx\n", | ||
2502 | addr, vmcs_readl(GUEST_RIP)); | ||
2503 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0); | ||
2504 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
2505 | DF_VECTOR | | ||
2506 | INTR_TYPE_EXCEPTION | | ||
2507 | INTR_INFO_DELIEVER_CODE_MASK | | ||
2508 | INTR_INFO_VALID_MASK); | ||
2509 | return; | ||
2510 | } | ||
2511 | vcpu->cr2 = addr; | ||
2512 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code); | ||
2513 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
2514 | PF_VECTOR | | ||
2515 | INTR_TYPE_EXCEPTION | | ||
2516 | INTR_INFO_DELIEVER_CODE_MASK | | ||
2517 | INTR_INFO_VALID_MASK); | ||
2518 | |||
2519 | } | ||
2520 | |||
2521 | static void vmx_free_vmcs(struct kvm_vcpu *vcpu) | 2490 | static void vmx_free_vmcs(struct kvm_vcpu *vcpu) |
2522 | { | 2491 | { |
2523 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 2492 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
@@ -2649,7 +2618,6 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
2649 | .set_rflags = vmx_set_rflags, | 2618 | .set_rflags = vmx_set_rflags, |
2650 | 2619 | ||
2651 | .tlb_flush = vmx_flush_tlb, | 2620 | .tlb_flush = vmx_flush_tlb, |
2652 | .inject_page_fault = vmx_inject_page_fault, | ||
2653 | 2621 | ||
2654 | .inject_gp = vmx_inject_gp, | 2622 | .inject_gp = vmx_inject_gp, |
2655 | 2623 | ||
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c index 11440d12a2d3..dc007a32a883 100644 --- a/drivers/kvm/x86.c +++ b/drivers/kvm/x86.c | |||
@@ -142,6 +142,21 @@ void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr) | |||
142 | } | 142 | } |
143 | EXPORT_SYMBOL_GPL(kvm_queue_exception); | 143 | EXPORT_SYMBOL_GPL(kvm_queue_exception); |
144 | 144 | ||
145 | void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr, | ||
146 | u32 error_code) | ||
147 | { | ||
148 | ++vcpu->stat.pf_guest; | ||
149 | if (vcpu->exception.pending && vcpu->exception.nr == PF_VECTOR) { | ||
150 | printk(KERN_DEBUG "kvm: inject_page_fault:" | ||
151 | " double fault 0x%lx\n", addr); | ||
152 | vcpu->exception.nr = DF_VECTOR; | ||
153 | vcpu->exception.error_code = 0; | ||
154 | return; | ||
155 | } | ||
156 | vcpu->cr2 = addr; | ||
157 | kvm_queue_exception_e(vcpu, PF_VECTOR, error_code); | ||
158 | } | ||
159 | |||
145 | void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) | 160 | void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) |
146 | { | 161 | { |
147 | WARN_ON(vcpu->exception.pending); | 162 | WARN_ON(vcpu->exception.pending); |
@@ -1601,7 +1616,7 @@ static int emulator_write_emulated_onepage(unsigned long addr, | |||
1601 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); | 1616 | gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr); |
1602 | 1617 | ||
1603 | if (gpa == UNMAPPED_GVA) { | 1618 | if (gpa == UNMAPPED_GVA) { |
1604 | kvm_x86_ops->inject_page_fault(vcpu, addr, 2); | 1619 | kvm_inject_page_fault(vcpu, addr, 2); |
1605 | return X86EMUL_PROPAGATE_FAULT; | 1620 | return X86EMUL_PROPAGATE_FAULT; |
1606 | } | 1621 | } |
1607 | 1622 | ||
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h index 1e71668694ea..d3ac4e2b3a41 100644 --- a/drivers/kvm/x86.h +++ b/drivers/kvm/x86.h | |||
@@ -219,8 +219,6 @@ struct kvm_x86_ops { | |||
219 | void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); | 219 | void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); |
220 | 220 | ||
221 | void (*tlb_flush)(struct kvm_vcpu *vcpu); | 221 | void (*tlb_flush)(struct kvm_vcpu *vcpu); |
222 | void (*inject_page_fault)(struct kvm_vcpu *vcpu, | ||
223 | unsigned long addr, u32 err_code); | ||
224 | 222 | ||
225 | void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code); | 223 | void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code); |
226 | 224 | ||
@@ -306,6 +304,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data); | |||
306 | 304 | ||
307 | void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr); | 305 | void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr); |
308 | void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); | 306 | void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); |
307 | void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, | ||
308 | u32 error_code); | ||
309 | 309 | ||
310 | void fx_init(struct kvm_vcpu *vcpu); | 310 | void fx_init(struct kvm_vcpu *vcpu); |
311 | 311 | ||