WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-3.1-testing] x86 hvm: Tolerate failure to complete

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.1-testing] x86 hvm: Tolerate failure to complete INTACK cycle on an
From: "Xen patchbot-3.1-testing" <patchbot-3.1-testing@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 11 Jan 2008 03:50:26 -0800
Delivery-date: Fri, 11 Jan 2008 03:51:46 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1199966099 0
# Node ID f4a17a5dc9b03a05a525ffc2b75e80e764cf8924
# Parent  48c800d5a3718a4a8115c02fc0b76d16f85d35f8
x86 hvm: Tolerate failure to complete INTACK cycle on an
interrupt. Failure can occur because we do not hold locks between
detecting a pending interrupt and acknowledging it. Satte can change
between these two points.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/intr.c |   62 +++++++++++++-------------
 xen/arch/x86/hvm/vmx/intr.c |  103 ++++++++++++++++++++++----------------------
 2 files changed, 85 insertions(+), 80 deletions(-)

diff -r 48c800d5a371 -r f4a17a5dc9b0 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Thu Jan 10 11:49:19 2008 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c       Thu Jan 10 11:54:59 2008 +0000
@@ -126,38 +126,40 @@ asmlinkage void svm_intr_assist(void)
     /* Crank the handle on interrupt state and check for new interrrupts. */
     pt_update_irq(v);
     hvm_maybe_deassert_evtchn_irq();
-    if ( !cpu_has_pending_irq(v) )
-        goto out;
 
-    /*
-     * 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 
-         || vmcb->eventinj.fields.v )  
-    {
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
-        HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
-        svm_inject_extint(v, 0x0); /* actual vector doesn't matter */
-        intr_window_enabled = 1;
-        goto out;
-    }
+    do {
+        if ( !cpu_has_pending_irq(v) )
+            goto out;
 
-    /* Okay, we can deliver the interrupt: grab it and update PIC state. */
-    intr_vector = cpu_get_interrupt(v, &intr_type);
-    BUG_ON(intr_vector < 0);
+        /*
+         * 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 
+             || vmcb->eventinj.fields.v )  
+        {
+            vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+            HVMTRACE_2D(INJ_VIRQ, v, 0x0, /*fake=*/ 1);
+            svm_inject_extint(v, 0x0); /* actual vector doesn't matter */
+            intr_window_enabled = 1;
+            goto out;
+        }
+
+        /* Okay, we can deliver the interrupt: grab it and update PIC state. */
+        intr_vector = cpu_get_interrupt(v, &intr_type);
+    } while ( intr_vector < 0 );
 
     HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
     svm_inject_extint(v, intr_vector);
diff -r 48c800d5a371 -r f4a17a5dc9b0 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Thu Jan 10 11:49:19 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/intr.c       Thu Jan 10 11:54:59 2008 +0000
@@ -114,60 +114,63 @@ asmlinkage void vmx_intr_assist(void)
 
     update_tpr_threshold(vcpu_vlapic(v));
 
-    has_ext_irq = cpu_has_pending_irq(v);
+    do {
+        has_ext_irq = cpu_has_pending_irq(v);
 
-    if ( unlikely(v->arch.hvm_vmx.vector_injected) )
-    {
-        v->arch.hvm_vmx.vector_injected = 0;
-        if ( unlikely(has_ext_irq) )
+        if ( unlikely(v->arch.hvm_vmx.vector_injected) )
+        {
+            v->arch.hvm_vmx.vector_injected = 0;
+            if ( unlikely(has_ext_irq) )
+                enable_irq_window(v);
+            return;
+        }
+
+        /* This could be moved earlier in the VMX resume sequence. */
+        idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
+        if ( unlikely(idtv_info_field & INTR_INFO_VALID_MASK) )
+        {
+            __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
+
+            /*
+             * Safe: the length will only be interpreted for software
+             * exceptions and interrupts. If we get here then delivery of some
+             * event caused a fault, and this always results in defined
+             * VM_EXIT_INSTRUCTION_LEN.
+             */
+            inst_len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe */
+            __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
+
+            if ( unlikely(idtv_info_field & 0x800) ) /* valid error code */
+                __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
+                          __vmread(IDT_VECTORING_ERROR_CODE));
+            if ( unlikely(has_ext_irq) )
+                enable_irq_window(v);
+
+            HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
+            return;
+        }
+
+        if ( likely(!has_ext_irq) )
+            return;
+
+        intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+        if ( unlikely(intr_shadow & (VMX_INTR_SHADOW_STI|
+                                     VMX_INTR_SHADOW_MOV_SS)) )
+        {
             enable_irq_window(v);
-        return;
-    }
+            HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
+            return;
+        }
 
-    /* This could be moved earlier in the VMX resume sequence. */
-    idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
-    if ( unlikely(idtv_info_field & INTR_INFO_VALID_MASK) )
-    {
-        __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field);
+        eflags = __vmread(GUEST_RFLAGS);
+        if ( irq_masked(eflags) )
+        {
+            enable_irq_window(v);
+            return;
+        }
 
-        /*
-         * Safe: the length will only be interpreted for software exceptions
-         * and interrupts. If we get here then delivery of some event caused a
-         * fault, and this always results in defined VM_EXIT_INSTRUCTION_LEN.
-         */
-        inst_len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe */
-        __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len);
-
-        if ( unlikely(idtv_info_field & 0x800) ) /* valid error code */
-            __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE,
-                      __vmread(IDT_VECTORING_ERROR_CODE));
-        if ( unlikely(has_ext_irq) )
-            enable_irq_window(v);
-
-        HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
-        return;
-    }
-
-    if ( likely(!has_ext_irq) )
-        return;
-
-    intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
-    if ( unlikely(intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS)) )
-    {
-        enable_irq_window(v);
-        HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
-        return;
-    }
-
-    eflags = __vmread(GUEST_RFLAGS);
-    if ( irq_masked(eflags) )
-    {
-        enable_irq_window(v);
-        return;
-    }
-
-    intr_vector = cpu_get_interrupt(v, &intr_type);
-    BUG_ON(intr_vector < 0);
+        intr_vector = cpu_get_interrupt(v, &intr_type);
+    } while ( intr_vector < 0 );
 
     HVMTRACE_2D(INJ_VIRQ, v, intr_vector, /*fake=*/ 0);
     vmx_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.1-testing] x86 hvm: Tolerate failure to complete INTACK cycle on an, Xen patchbot-3.1-testing <=