aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-25 07:04:58 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:18 -0500
commitc3c91fee5195ba5176a6da5ddc2a2822243eb79f (patch)
tree1fcccd77e5705d5f885bbb24ecb08bd93cf71c63
parent298101da2f507c13eaf179ee4507a7c0fe3e7b06 (diff)
KVM: Replace page fault injection by the generalized exception queue
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/mmu.c2
-rw-r--r--drivers/kvm/svm.c35
-rw-r--r--drivers/kvm/vmx.c32
-rw-r--r--drivers/kvm/x86.c17
-rw-r--r--drivers/kvm/x86.h4
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
1087static void paging_free(struct kvm_vcpu *vcpu) 1087static 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
228static 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
234static int is_external_interrupt(u32 info) 228static 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
1627static 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
1655static int is_disabled(void) 1621static 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
2490static 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
2521static void vmx_free_vmcs(struct kvm_vcpu *vcpu) 2490static 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}
143EXPORT_SYMBOL_GPL(kvm_queue_exception); 143EXPORT_SYMBOL_GPL(kvm_queue_exception);
144 144
145void 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
145void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code) 160void 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
307void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr); 305void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
308void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code); 306void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
307void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2,
308 u32 error_code);
309 309
310void fx_init(struct kvm_vcpu *vcpu); 310void fx_init(struct kvm_vcpu *vcpu);
311 311