aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/svm.c21
-rw-r--r--drivers/kvm/vmx.c20
-rw-r--r--drivers/kvm/x86.c33
-rw-r--r--drivers/kvm/x86.h13
4 files changed, 86 insertions, 1 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index c75c6b65b651..87072c647f28 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -188,6 +188,25 @@ static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
188 vcpu->shadow_efer = efer; 188 vcpu->shadow_efer = efer;
189} 189}
190 190
191static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
192 bool has_error_code, u32 error_code)
193{
194 struct vcpu_svm *svm = to_svm(vcpu);
195
196 svm->vmcb->control.event_inj = nr
197 | SVM_EVTINJ_VALID
198 | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
199 | SVM_EVTINJ_TYPE_EXEPT;
200 svm->vmcb->control.event_inj_err = error_code;
201}
202
203static bool svm_exception_injected(struct kvm_vcpu *vcpu)
204{
205 struct vcpu_svm *svm = to_svm(vcpu);
206
207 return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
208}
209
191static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) 210static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
192{ 211{
193 struct vcpu_svm *svm = to_svm(vcpu); 212 struct vcpu_svm *svm = to_svm(vcpu);
@@ -1712,6 +1731,8 @@ static struct kvm_x86_ops svm_x86_ops = {
1712 .patch_hypercall = svm_patch_hypercall, 1731 .patch_hypercall = svm_patch_hypercall,
1713 .get_irq = svm_get_irq, 1732 .get_irq = svm_get_irq,
1714 .set_irq = svm_set_irq, 1733 .set_irq = svm_set_irq,
1734 .queue_exception = svm_queue_exception,
1735 .exception_injected = svm_exception_injected,
1715 .inject_pending_irq = svm_intr_assist, 1736 .inject_pending_irq = svm_intr_assist,
1716 .inject_pending_vectors = do_interrupt_requests, 1737 .inject_pending_vectors = do_interrupt_requests,
1717 1738
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index fc5e7c8381ce..f382956f176a 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -595,6 +595,24 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
595 vcpu->interrupt_window_open = 1; 595 vcpu->interrupt_window_open = 1;
596} 596}
597 597
598static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
599 bool has_error_code, u32 error_code)
600{
601 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
602 nr | INTR_TYPE_EXCEPTION
603 | (has_error_code ? INTR_INFO_DELIEVER_CODE_MASK : 0)
604 | INTR_INFO_VALID_MASK);
605 if (has_error_code)
606 vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
607}
608
609static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
610{
611 struct vcpu_vmx *vmx = to_vmx(vcpu);
612
613 return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
614}
615
598static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code) 616static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
599{ 617{
600 printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n", 618 printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
@@ -2641,6 +2659,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
2641 .patch_hypercall = vmx_patch_hypercall, 2659 .patch_hypercall = vmx_patch_hypercall,
2642 .get_irq = vmx_get_irq, 2660 .get_irq = vmx_get_irq,
2643 .set_irq = vmx_inject_irq, 2661 .set_irq = vmx_inject_irq,
2662 .queue_exception = vmx_queue_exception,
2663 .exception_injected = vmx_exception_injected,
2644 .inject_pending_irq = vmx_intr_assist, 2664 .inject_pending_irq = vmx_intr_assist,
2645 .inject_pending_vectors = do_interrupt_requests, 2665 .inject_pending_vectors = do_interrupt_requests,
2646 2666
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index c9e4b67bfb1b..11440d12a2d3 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -133,6 +133,32 @@ static void inject_gp(struct kvm_vcpu *vcpu)
133 kvm_x86_ops->inject_gp(vcpu, 0); 133 kvm_x86_ops->inject_gp(vcpu, 0);
134} 134}
135 135
136void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
137{
138 WARN_ON(vcpu->exception.pending);
139 vcpu->exception.pending = true;
140 vcpu->exception.has_error_code = false;
141 vcpu->exception.nr = nr;
142}
143EXPORT_SYMBOL_GPL(kvm_queue_exception);
144
145void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
146{
147 WARN_ON(vcpu->exception.pending);
148 vcpu->exception.pending = true;
149 vcpu->exception.has_error_code = true;
150 vcpu->exception.nr = nr;
151 vcpu->exception.error_code = error_code;
152}
153EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
154
155static void __queue_exception(struct kvm_vcpu *vcpu)
156{
157 kvm_x86_ops->queue_exception(vcpu, vcpu->exception.nr,
158 vcpu->exception.has_error_code,
159 vcpu->exception.error_code);
160}
161
136/* 162/*
137 * Load the pae pdptrs. Return true is they are all valid. 163 * Load the pae pdptrs. Return true is they are all valid.
138 */ 164 */
@@ -2370,7 +2396,9 @@ again:
2370 goto out; 2396 goto out;
2371 } 2397 }
2372 2398
2373 if (irqchip_in_kernel(vcpu->kvm)) 2399 if (vcpu->exception.pending)
2400 __queue_exception(vcpu);
2401 else if (irqchip_in_kernel(vcpu->kvm))
2374 kvm_x86_ops->inject_pending_irq(vcpu); 2402 kvm_x86_ops->inject_pending_irq(vcpu);
2375 else 2403 else
2376 kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run); 2404 kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
@@ -2409,6 +2437,9 @@ again:
2409 profile_hit(KVM_PROFILING, (void *)vcpu->rip); 2437 profile_hit(KVM_PROFILING, (void *)vcpu->rip);
2410 } 2438 }
2411 2439
2440 if (vcpu->exception.pending && kvm_x86_ops->exception_injected(vcpu))
2441 vcpu->exception.pending = false;
2442
2412 r = kvm_x86_ops->handle_exit(kvm_run, vcpu); 2443 r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
2413 2444
2414 if (r > 0) { 2445 if (r > 0) {
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index eed796402e3b..1e71668694ea 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -139,6 +139,13 @@ struct kvm_vcpu {
139 struct kvm_pio_request pio; 139 struct kvm_pio_request pio;
140 void *pio_data; 140 void *pio_data;
141 141
142 struct kvm_queued_exception {
143 bool pending;
144 bool has_error_code;
145 u8 nr;
146 u32 error_code;
147 } exception;
148
142 struct { 149 struct {
143 int active; 150 int active;
144 u8 save_iopl; 151 u8 save_iopl;
@@ -224,6 +231,9 @@ struct kvm_x86_ops {
224 unsigned char *hypercall_addr); 231 unsigned char *hypercall_addr);
225 int (*get_irq)(struct kvm_vcpu *vcpu); 232 int (*get_irq)(struct kvm_vcpu *vcpu);
226 void (*set_irq)(struct kvm_vcpu *vcpu, int vec); 233 void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
234 void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
235 bool has_error_code, u32 error_code);
236 bool (*exception_injected)(struct kvm_vcpu *vcpu);
227 void (*inject_pending_irq)(struct kvm_vcpu *vcpu); 237 void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
228 void (*inject_pending_vectors)(struct kvm_vcpu *vcpu, 238 void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
229 struct kvm_run *run); 239 struct kvm_run *run);
@@ -294,6 +304,9 @@ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
294int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); 304int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
295int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data); 305int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
296 306
307void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
308void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
309
297void fx_init(struct kvm_vcpu *vcpu); 310void fx_init(struct kvm_vcpu *vcpu);
298 311
299int emulator_read_std(unsigned long addr, 312int emulator_read_std(unsigned long addr,