ia64/xen-unstable

changeset 14632:e4e6aab3ec13

[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@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Wed Mar 28 15:02:54 2007 +0000 (2007-03-28)
parents 6ee683d1b61f
children b6eaca0bcee1
files xen/arch/x86/hvm/svm/intr.c
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/intr.c	Wed Mar 28 15:31:17 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Wed Mar 28 15:02:54 2007 +0000
     1.3 @@ -68,20 +68,6 @@ asmlinkage void svm_intr_assist(void)
     1.4      int intr_vector = -1;
     1.5  
     1.6      /*
     1.7 -     * Do not deliver a virtual interrupt (vintr) if an exception is pending.
     1.8 -     * This is because the delivery of the exception can arbitrarily delay
     1.9 -     * the injection of the vintr (for example, if the exception is handled
    1.10 -     * via an interrupt gate, hence zeroing RFLAGS.IF). In the meantime the
    1.11 -     * vTPR can be modified upwards and we can end up delivering the vintr
    1.12 -     * when it is not in fact valid to do so (because we do not re-check the
    1.13 -     * vTPR value). Moreover, the guest will be able to see the updated
    1.14 -     * APIC/PIC state (as if the interrupt had been acknowledged) yet will not
    1.15 -     * have actually received the interrupt. This could confuse the guest!
    1.16 -     */
    1.17 -    if ( vmcb->eventinj.fields.v )
    1.18 -        return;
    1.19 -
    1.20 -    /*
    1.21       * Previous Interrupt delivery caused this intercept?
    1.22       * This will happen if the injection is latched by the processor (hence
    1.23       * clearing vintr.fields.irq) but then subsequently a fault occurs (e.g.,
    1.24 @@ -115,11 +101,23 @@ asmlinkage void svm_intr_assist(void)
    1.25          return;
    1.26  
    1.27      /*
    1.28 -     * Create a 'fake' virtual interrupt on to intercept as soon as the
    1.29 -     * guest _can_ take interrupts.  Do not obtain the next interrupt from
    1.30 -     * the vlapic/pic if unable to inject.
    1.31 +     * If the guest can't take an interrupt right now, create a 'fake'
    1.32 +     * virtual interrupt on to intercept as soon as the guest _can_ take
    1.33 +     * interrupts.  Do not obtain the next interrupt from the vlapic/pic
    1.34 +     * if unable to inject.
    1.35 +     *
    1.36 +     * Also do this if there is an exception pending.  This is because
    1.37 +     * the delivery of the exception can arbitrarily delay the injection
    1.38 +     * of the vintr (for example, if the exception is handled via an
    1.39 +     * interrupt gate, hence zeroing RFLAGS.IF). In the meantime:
    1.40 +     * - the vTPR could be modified upwards, so we need to wait until the
    1.41 +     *   exception is delivered before we can safely decide that an
    1.42 +     *   interrupt is deliverable; and
    1.43 +     * - the guest might look at the APIC/PIC state, so we ought not to have 
    1.44 +     *   cleared the interrupt out of the IRR.
    1.45       */
    1.46 -    if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )  
    1.47 +    if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow 
    1.48 +         || vmcb->eventinj.fields.v )  
    1.49      {
    1.50          vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
    1.51          HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);