From: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Cc: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Subject: [PATCH 1/7] KVM: Generalize exception injection mechanism
Date: Tue, 4 Dec 2007 11:44:08 +0200 [thread overview]
Message-ID: <11967614543701-git-send-email-avi@qumranet.com> (raw)
In-Reply-To: <11967614542283-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Instead of each subarch doing its own thing, add an API for queuing an
injection, and manage failed exception injection centerally (i.e., if
an inject failed due to a shadow page fault, we need to requeue it).
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 21 +++++++++++++++++++++
drivers/kvm/vmx.c | 20 ++++++++++++++++++++
drivers/kvm/x86.c | 33 ++++++++++++++++++++++++++++++++-
drivers/kvm/x86.h | 13 +++++++++++++
4 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 04e6b39..f4c61c8 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)
vcpu->shadow_efer = efer;
}
+static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ svm->vmcb->control.event_inj = nr
+ | SVM_EVTINJ_VALID
+ | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
+ | SVM_EVTINJ_TYPE_EXEPT;
+ svm->vmcb->control.event_inj_err = error_code;
+}
+
+static bool svm_exception_injected(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
+}
+
static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -1712,6 +1731,8 @@ static struct kvm_x86_ops svm_x86_ops = {
.patch_hypercall = svm_patch_hypercall,
.get_irq = svm_get_irq,
.set_irq = svm_set_irq,
+ .queue_exception = svm_queue_exception,
+ .exception_injected = svm_exception_injected,
.inject_pending_irq = svm_intr_assist,
.inject_pending_vectors = do_interrupt_requests,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 8e43feb..1ec1c28 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -595,6 +595,24 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
vcpu->interrupt_window_open = 1;
}
+static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code)
+{
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ nr | INTR_TYPE_EXCEPTION
+ | (has_error_code ? INTR_INFO_DELIEVER_CODE_MASK : 0)
+ | INTR_INFO_VALID_MASK);
+ if (has_error_code)
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+}
+
+static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+}
+
static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
{
printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
@@ -2641,6 +2659,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.patch_hypercall = vmx_patch_hypercall,
.get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
+ .queue_exception = vmx_queue_exception,
+ .exception_injected = vmx_exception_injected,
.inject_pending_irq = vmx_intr_assist,
.inject_pending_vectors = do_interrupt_requests,
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index c9e4b67..11440d1 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -133,6 +133,32 @@ static void inject_gp(struct kvm_vcpu *vcpu)
kvm_x86_ops->inject_gp(vcpu, 0);
}
+void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
+{
+ WARN_ON(vcpu->exception.pending);
+ vcpu->exception.pending = true;
+ vcpu->exception.has_error_code = false;
+ vcpu->exception.nr = nr;
+}
+EXPORT_SYMBOL_GPL(kvm_queue_exception);
+
+void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
+{
+ WARN_ON(vcpu->exception.pending);
+ vcpu->exception.pending = true;
+ vcpu->exception.has_error_code = true;
+ vcpu->exception.nr = nr;
+ vcpu->exception.error_code = error_code;
+}
+EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
+
+static void __queue_exception(struct kvm_vcpu *vcpu)
+{
+ kvm_x86_ops->queue_exception(vcpu, vcpu->exception.nr,
+ vcpu->exception.has_error_code,
+ vcpu->exception.error_code);
+}
+
/*
* Load the pae pdptrs. Return true is they are all valid.
*/
@@ -2370,7 +2396,9 @@ again:
goto out;
}
- if (irqchip_in_kernel(vcpu->kvm))
+ if (vcpu->exception.pending)
+ __queue_exception(vcpu);
+ else if (irqchip_in_kernel(vcpu->kvm))
kvm_x86_ops->inject_pending_irq(vcpu);
else
kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
@@ -2409,6 +2437,9 @@ again:
profile_hit(KVM_PROFILING, (void *)vcpu->rip);
}
+ if (vcpu->exception.pending && kvm_x86_ops->exception_injected(vcpu))
+ vcpu->exception.pending = false;
+
r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
if (r > 0) {
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index 78ab1e1..7510e31 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -136,6 +136,13 @@ struct kvm_vcpu {
struct kvm_pio_request pio;
void *pio_data;
+ struct kvm_queued_exception {
+ bool pending;
+ bool has_error_code;
+ u8 nr;
+ u32 error_code;
+ } exception;
+
struct {
int active;
u8 save_iopl;
@@ -216,6 +223,9 @@ struct kvm_x86_ops {
unsigned char *hypercall_addr);
int (*get_irq)(struct kvm_vcpu *vcpu);
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
+ void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code);
+ bool (*exception_injected)(struct kvm_vcpu *vcpu);
void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
struct kvm_run *run);
@@ -286,6 +296,9 @@ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
+void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
+void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
+
void fx_init(struct kvm_vcpu *vcpu);
int emulator_read_std(unsigned long addr,
--
1.5.3
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
next prev parent reply other threads:[~2007-12-04 9:44 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-04 9:44 [PATCH 0/7] Rework irq injection infrastructure Avi Kivity
[not found] ` <11967614542283-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-12-04 9:44 ` Avi Kivity [this message]
2007-12-04 9:44 ` [PATCH 2/7] KVM: Replace page fault injection by the generalized exception queue Avi Kivity
2007-12-04 9:44 ` [PATCH 3/7] KVM: Replace #GP " Avi Kivity
2007-12-04 9:44 ` [PATCH 4/7] KVM: Use generalized exception queue for injecting #UD Avi Kivity
2007-12-04 9:44 ` [PATCH 5/7] KVM: Add explicit acks to interrupt controller model Avi Kivity
2007-12-04 9:44 ` [PATCH 6/7] KVM: Move tpr threshold calculation into common code Avi Kivity
2007-12-04 9:44 ` [PATCH 7/7] KVM: Ack interrupts only after they have successfully been injected Avi Kivity
2007-12-04 16:51 ` [PATCH 0/7] Rework irq injection infrastructure Joerg Roedel
[not found] ` <20071204165101.GA23093-5C7GfCeVMHo@public.gmane.org>
2007-12-04 16:56 ` Avi Kivity
2007-12-06 7:50 ` Dong, Eddie
[not found] ` <10EA09EFD8728347A513008B6B0DA77A0279CC10-wq7ZOvIWXbNpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-12-06 8:28 ` Avi Kivity
[not found] ` <4757B2C3.3000402-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-12-06 9:33 ` Dong, Eddie
[not found] ` <10EA09EFD8728347A513008B6B0DA77A0279CCE0-wq7ZOvIWXbNpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-12-06 10:10 ` Avi Kivity
[not found] ` <4757CA93.1090704-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-12-06 10:26 ` Dong, Eddie
[not found] ` <10EA09EFD8728347A513008B6B0DA77A0279CCF2-wq7ZOvIWXbNpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-12-06 13:24 ` Dong, Eddie
[not found] ` <10EA09EFD8728347A513008B6B0DA77A0279CD1C-wq7ZOvIWXbNpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-12-06 14:19 ` Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11967614543701-git-send-email-avi@qumranet.com \
--to=avi-atkuwr5tajbwk0htik3j/w@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox