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-unstable] x86: MSI interrupt storm avoidance.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: MSI interrupt storm avoidance.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 04 Jul 2008 08:00:14 -0700
Delivery-date: Fri, 04 Jul 2008 08:00:49 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 1215168719 -3600
# Node ID 1db0b09b290eef393df17f3502ea27324fe403aa
# Parent  6ae87b27cceadaf8339b42b7489f81b66ea03cf1
x86: MSI interrupt storm avoidance.
Signed-off-by: Shan Haitao <Haitao.shan@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vlapic.c    |    5 ++---
 xen/arch/x86/irq.c           |   42 ++++++++++++++++++++++++++++++++++++++----
 xen/common/event_channel.c   |   11 +++++++----
 xen/drivers/passthrough/io.c |   21 +++++++++++++++++----
 xen/include/xen/event.h      |    5 ++---
 5 files changed, 66 insertions(+), 18 deletions(-)

diff -r 6ae87b27ccea -r 1db0b09b290e xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Thu Jul 03 13:39:06 2008 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Fri Jul 04 11:51:59 2008 +0100
@@ -413,9 +413,8 @@ void vlapic_EOI_set(struct vlapic *vlapi
 
     if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) )
         vioapic_update_EOI(vlapic_domain(vlapic), vector);
-       
-    if ( iommu_enabled )
-        hvm_dpci_msi_eoi(current->domain, vector);
+
+    hvm_dpci_msi_eoi(current->domain, vector);
 }
 
 static int vlapic_ipi(
diff -r 6ae87b27ccea -r 1db0b09b290e xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Thu Jul 03 13:39:06 2008 +0100
+++ b/xen/arch/x86/irq.c        Fri Jul 04 11:51:59 2008 +0100
@@ -201,12 +201,25 @@ static DEFINE_PER_CPU(struct pending_eoi
 static DEFINE_PER_CPU(struct pending_eoi, pending_eoi[NR_VECTORS]);
 #define pending_eoi_sp(p) ((p)[NR_VECTORS-1].vector)
 
+static struct timer irq_guest_eoi_timer[NR_IRQS];
+static void irq_guest_eoi_timer_fn(void *data)
+{
+    irq_desc_t *desc = data;
+    unsigned vector = desc - irq_desc;
+    unsigned long flags;
+
+    spin_lock_irqsave(&desc->lock, flags);
+    desc->status &= ~IRQ_INPROGRESS;
+    desc->handler->enable(vector);
+    spin_unlock_irqrestore(&desc->lock, flags);
+}
+
 static void __do_IRQ_guest(int vector)
 {
     irq_desc_t         *desc = &irq_desc[vector];
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     struct domain      *d;
-    int                 i, sp;
+    int                 i, sp, already_pending = 0;
     struct pending_eoi *peoi = this_cpu(pending_eoi);
 
     if ( unlikely(action->nr_guests == 0) )
@@ -237,9 +250,28 @@ static void __do_IRQ_guest(int vector)
         if ( (action->ack_type != ACKTYPE_NONE) &&
              !test_and_set_bit(irq, d->pirq_mask) )
             action->in_flight++;
-        if (!hvm_do_IRQ_dpci(d, irq))
-            send_guest_pirq(d, irq);
-
+        if ( hvm_do_IRQ_dpci(d, irq) )
+        {
+            if ( action->ack_type == ACKTYPE_NONE )
+            {
+                already_pending += !!(desc->status & IRQ_INPROGRESS);
+                desc->status |= IRQ_INPROGRESS; /* cleared during hvm eoi */
+            }
+        }
+        else if ( send_guest_pirq(d, irq) &&
+                  (action->ack_type == ACKTYPE_NONE) )
+        {
+            already_pending++;
+        }
+    }
+
+    if ( already_pending == action->nr_guests )
+    {
+        desc->handler->disable(vector);
+        stop_timer(&irq_guest_eoi_timer[vector]);
+        init_timer(&irq_guest_eoi_timer[vector],
+                   irq_guest_eoi_timer_fn, desc, smp_processor_id());
+        set_timer(&irq_guest_eoi_timer[vector], NOW() + MILLISECS(1));
     }
 }
 
@@ -622,6 +654,8 @@ int pirq_guest_unbind(struct domain *d, 
     desc->action = NULL;
     xfree(action);
     desc->status &= ~IRQ_GUEST;
+    desc->status &= ~IRQ_INPROGRESS;
+    kill_timer(&irq_guest_eoi_timer[vector]);
     desc->handler->shutdown(vector);
 
  out:
diff -r 6ae87b27ccea -r 1db0b09b290e xen/common/event_channel.c
--- a/xen/common/event_channel.c        Thu Jul 03 13:39:06 2008 +0100
+++ b/xen/common/event_channel.c        Fri Jul 04 11:51:59 2008 +0100
@@ -56,6 +56,7 @@
         goto out;                                                   \
     } while ( 0 )
 
+static int evtchn_set_pending(struct vcpu *v, int port);
 
 static int virq_is_global(int virq)
 {
@@ -536,7 +537,7 @@ out:
 }
 
 
-void evtchn_set_pending(struct vcpu *v, int port)
+static int evtchn_set_pending(struct vcpu *v, int port)
 {
     struct domain *d = v->domain;
 
@@ -548,7 +549,7 @@ void evtchn_set_pending(struct vcpu *v, 
      */
 
     if ( test_and_set_bit(port, &shared_info(d, evtchn_pending)) )
-        return;
+        return 1;
 
     if ( !test_bit        (port, &shared_info(d, evtchn_mask)) &&
          !test_and_set_bit(port / BITS_PER_GUEST_LONG(d),
@@ -570,6 +571,8 @@ void evtchn_set_pending(struct vcpu *v, 
             vcpu_unblock(v);
         }
     }
+
+    return 0;
 }
 
 
@@ -610,7 +613,7 @@ void send_guest_global_virq(struct domai
 }
 
 
-void send_guest_pirq(struct domain *d, int pirq)
+int send_guest_pirq(struct domain *d, int pirq)
 {
     int port = d->pirq_to_evtchn[pirq];
     struct evtchn *chn;
@@ -618,7 +621,7 @@ void send_guest_pirq(struct domain *d, i
     ASSERT(port != 0);
 
     chn = evtchn_from_port(d, port);
-    evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
+    return evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
 }
 
 
diff -r 6ae87b27ccea -r 1db0b09b290e xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Thu Jul 03 13:39:06 2008 +0100
+++ b/xen/drivers/passthrough/io.c      Fri Jul 04 11:51:59 2008 +0100
@@ -207,9 +207,9 @@ int hvm_do_IRQ_dpci(struct domain *d, un
      * PIC) and we need to detect that.
      */
     set_bit(mirq, dpci->dirq_mask);
-       if ( !test_bit(_HVM_IRQ_DPCI_MSI, &dpci->mirq[mirq].flags) )
-               set_timer(&dpci->hvm_timer[domain_irq_to_vector(d, mirq)],
-                                 NOW() + PT_IRQ_TIME_OUT);
+    if ( !test_bit(_HVM_IRQ_DPCI_MSI, &dpci->mirq[mirq].flags) )
+        set_timer(&dpci->hvm_timer[domain_irq_to_vector(d, mirq)],
+                  NOW() + PT_IRQ_TIME_OUT);
     vcpu_kick(d->vcpu[0]);
 
     return 1;
@@ -220,15 +220,28 @@ void hvm_dpci_msi_eoi(struct domain *d, 
 {
     struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     int pirq;
+    unsigned long flags;
+    irq_desc_t *desc;
 
     if ( !iommu_enabled || (hvm_irq_dpci == NULL) )
        return;
 
     pirq = hvm_irq_dpci->msi_gvec_pirq[vector];
+
     if ( ( pirq >= 0 ) && (pirq < NR_PIRQS) &&
          (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID) &&
          (hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MSI) )
-         pirq_guest_eoi(d, pirq);
+    {
+        int vec;
+        vec = domain_irq_to_vector(d, pirq);
+        desc = &irq_desc[vec];
+
+        spin_lock_irqsave(&desc->lock, flags);
+        desc->status &= ~IRQ_INPROGRESS;
+        spin_unlock_irqrestore(&desc->lock, flags);
+
+        pirq_guest_eoi(d, pirq);
+    }
 }
 
 void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
diff -r 6ae87b27ccea -r 1db0b09b290e xen/include/xen/event.h
--- a/xen/include/xen/event.h   Thu Jul 03 13:39:06 2008 +0100
+++ b/xen/include/xen/event.h   Fri Jul 04 11:51:59 2008 +0100
@@ -15,8 +15,6 @@
 #include <xen/softirq.h>
 #include <asm/bitops.h>
 #include <asm/event.h>
-
-void evtchn_set_pending(struct vcpu *v, int port);
 
 /*
  * send_guest_vcpu_virq: Notify guest via a per-VCPU VIRQ.
@@ -36,8 +34,9 @@ void send_guest_global_virq(struct domai
  * send_guest_pirq:
  *  @d:        Domain to which physical IRQ should be sent
  *  @pirq:     Physical IRQ number
+ * Returns TRUE if the delivery port was already pending.
  */
-void send_guest_pirq(struct domain *d, int pirq);
+int send_guest_pirq(struct domain *d, int pirq);
 
 /* Send a notification from a local event-channel port. */
 long evtchn_send(unsigned int lport);

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: MSI interrupt storm avoidance., Xen patchbot-unstable <=