# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1175094174 0
# Node ID e4e6aab3ec135595349d68217084a712823ee56c
# Parent 6ee683d1b61fe16739152b8a74a7f0569e27d442
[SVM] Inject a "fake" interrupt if we delay an interrupt for an exception
(instead of just waiting for the next vmexit to inject the pending
interrupt, since that could be some arbitrary number of instructions later).
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
xen/arch/x86/hvm/svm/intr.c | 34 ++++++++++++++++------------------
1 files changed, 16 insertions(+), 18 deletions(-)
diff -r 6ee683d1b61f -r e4e6aab3ec13 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c Wed Mar 28 15:31:17 2007 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c Wed Mar 28 15:02:54 2007 +0000
@@ -68,20 +68,6 @@ asmlinkage void svm_intr_assist(void)
int intr_vector = -1;
- * Do not deliver a virtual interrupt (vintr) if an exception is pending.
- * This is because the delivery of the exception can arbitrarily delay
- * the injection of the vintr (for example, if the exception is handled
- * via an interrupt gate, hence zeroing RFLAGS.IF). In the meantime the
- * vTPR can be modified upwards and we can end up delivering the vintr
- * when it is not in fact valid to do so (because we do not re-check the
- * vTPR value). Moreover, the guest will be able to see the updated
- * APIC/PIC state (as if the interrupt had been acknowledged) yet will not
- * have actually received the interrupt. This could confuse the guest!
- if ( vmcb->eventinj.fields.v )
* Previous Interrupt delivery caused this intercept?
* This will happen if the injection is latched by the processor (hence
* clearing vintr.fields.irq) but then subsequently a fault occurs (e.g.,
@@ -115,11 +101,23 @@ asmlinkage void svm_intr_assist(void)
- * Create a 'fake' virtual interrupt on to intercept as soon as the
- * guest _can_ take interrupts. Do not obtain the next interrupt from
- * the vlapic/pic if unable to inject.
+ * If the guest can't take an interrupt right now, create a 'fake'
+ * virtual interrupt on to intercept as soon as the guest _can_ take
+ * interrupts. Do not obtain the next interrupt from the vlapic/pic
+ * if unable to inject.
+ * Also do this if there is an exception pending. This is because
+ * the delivery of the exception can arbitrarily delay the injection
+ * of the vintr (for example, if the exception is handled via an
+ * interrupt gate, hence zeroing RFLAGS.IF). In the meantime:
+ * - the vTPR could be modified upwards, so we need to wait until the
+ * exception is delivered before we can safely decide that an
+ * interrupt is deliverable; and
+ * - the guest might look at the APIC/PIC state, so we ought not to have
+ * cleared the interrupt out of the IRR.
- if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )
+ if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow
+ || vmcb->eventinj.fields.v )
vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
Xen-changelog mailing list