File 18547-pirq-vector-mapping-fix.patch of Package xen

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1222349872 -3600
# Node ID e1507b441be45d6d1cac25a196b53beff857a083
# Parent  ddf62f69611127319e3c756b9fbc82e29f59ef36
x86: Clean up and fix 18539:31f09a5e24cf8
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>

Index: xen-3.3.1-testing/xen/arch/ia64/xen/irq.c
===================================================================
--- xen-3.3.1-testing.orig/xen/arch/ia64/xen/irq.c
+++ xen-3.3.1-testing/xen/arch/ia64/xen/irq.c
@@ -459,12 +459,12 @@ int pirq_guest_bind(struct vcpu *v, int 
     return rc;
 }
 
-int pirq_guest_unbind(struct domain *d, int irq)
+void pirq_guest_unbind(struct domain *d, int irq)
 {
     irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action;
     unsigned long       flags;
-    int                 i, rc = 0;
+    int                 i;
 
     spin_lock_irqsave(&desc->lock, flags);
 
@@ -472,11 +472,7 @@ int pirq_guest_unbind(struct domain *d, 
 
     for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
         continue;
-    if ( i == action->nr_guests )
-    {
-        rc = -EINVAL;
-        goto out;
-    }
+    BUG_ON(i == action->nr_guests);
     memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
     action->nr_guests--;
 
@@ -496,9 +492,7 @@ int pirq_guest_unbind(struct domain *d, 
         desc->handler->shutdown(irq);
     }
 
- out:
     spin_unlock_irqrestore(&desc->lock, flags);    
-    return rc;
 }
 
 void
Index: xen-3.3.1-testing/xen/arch/x86/irq.c
===================================================================
--- xen-3.3.1-testing.orig/xen/arch/x86/irq.c
+++ xen-3.3.1-testing/xen/arch/x86/irq.c
@@ -510,12 +510,12 @@ int pirq_guest_bind(struct vcpu *v, int 
     irq_guest_action_t *action, *newaction = NULL;
     int                 rc = 0;
     cpumask_t           cpumask = CPU_MASK_NONE;
-    unsigned long       flags;
 
     WARN_ON(!spin_is_locked(&v->domain->evtchn_lock));
+    BUG_ON(!local_irq_is_enabled());
 
  retry:
-    desc = domain_spin_lock_irq_desc(v->domain, irq, &flags);
+    desc = domain_spin_lock_irq_desc(v->domain, irq, NULL);
     if ( desc == NULL )
          return -EINVAL;
 
@@ -535,7 +535,7 @@ int pirq_guest_bind(struct vcpu *v, int 
 
         if ( newaction == NULL )
         {
-            spin_unlock_irqrestore(&desc->lock, flags);
+            spin_unlock_irq(&desc->lock);
             if ( (newaction = xmalloc(irq_guest_action_t)) != NULL )
                 goto retry;
             gdprintk(XENLOG_INFO,
@@ -581,7 +581,7 @@ int pirq_guest_bind(struct vcpu *v, int 
          */
         ASSERT(action->ack_type == ACKTYPE_EOI);
         ASSERT(desc->status & IRQ_DISABLED);
-        spin_unlock_irqrestore(&desc->lock, flags);
+        spin_unlock_irq(&desc->lock);
         cpu_relax();
         goto retry;
     }
@@ -597,45 +597,26 @@ int pirq_guest_bind(struct vcpu *v, int 
     action->guest[action->nr_guests++] = v->domain;
 
  unlock_out:
-    spin_unlock_irqrestore(&desc->lock, flags);
+    spin_unlock_irq(&desc->lock);
  out:
-    if ( newaction != NULL )
-        xfree(newaction);
     return rc;
 }
 
-int pirq_guest_unbind(struct domain *d, int irq)
+static void __pirq_guest_unbind(struct domain *d, int irq, irq_desc_t *desc)
 {
-    int                 vector;
-    irq_desc_t         *desc;
+    unsigned int        vector;
     irq_guest_action_t *action;
     cpumask_t           cpu_eoi_map;
-    int                 i, rc = 0;
-
-    WARN_ON(!spin_is_locked(&d->evtchn_lock));
+    int                 i;
 
-    desc = domain_spin_lock_irq_desc(d, irq, &flags);
-    if ( unlikely(desc == NULL) )
-    {
-        if ( !msi_enable || (vector = -domain_irq_to_vector(d, irq)) == 0 )
-            return -EINVAL;
-        BUG_ON(vector <= 0);
-        desc = &irq_desc[vector];
-        spin_lock_irqsave(&desc->lock, flags);
-        d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
-        goto out;
-    }
+    BUG_ON(!(desc->status & IRQ_GUEST));
 
     action = (irq_guest_action_t *)desc->action;
     vector = desc - irq_desc;
 
     for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
         continue;
-    if ( i == action->nr_guests )
-    {
-        rc = -EINVAL;
-        goto out;
-    }
+    BUG_ON(i == action->nr_guests);
     memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
     action->nr_guests--;
 
@@ -653,7 +634,7 @@ int pirq_guest_unbind(struct domain *d, 
              (action->nr_guests != 0) )
         {
             cpu_eoi_map = action->cpu_eoi_map;
-            spin_unlock_irqrestore(&desc->lock, flags);
+            spin_unlock_irq(&desc->lock);
             on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
             spin_lock_irq(&desc->lock);
         }
@@ -669,7 +650,7 @@ int pirq_guest_unbind(struct domain *d, 
     if ( action->nr_guests != 0 )
     {
         action = NULL;
-        goto out;
+        return;
     }
 
     BUG_ON(action->in_flight != 0);
@@ -690,7 +671,7 @@ int pirq_guest_unbind(struct domain *d, 
     if ( !cpus_empty(cpu_eoi_map) )
     {
         BUG_ON(action->ack_type != ACKTYPE_EOI);
-        spin_unlock_irqrestore(&desc->lock, flags);
+        spin_unlock_irq(&desc->lock);
         on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 1);
         spin_lock_irq(&desc->lock);
     }
@@ -702,10 +683,63 @@ int pirq_guest_unbind(struct domain *d, 
     desc->status &= ~IRQ_INPROGRESS;
     kill_timer(&irq_guest_eoi_timer[vector]);
     desc->handler->shutdown(vector);
+}
+
+void pirq_guest_unbind(struct domain *d, int irq)
+{
+    irq_desc_t *desc;
+    int vector;
+
+    WARN_ON(!spin_is_locked(&d->evtchn_lock));
+
+    BUG_ON(!local_irq_is_enabled());
+    desc = domain_spin_lock_irq_desc(d, irq, NULL);
+
+    if ( desc == NULL )
+    {
+        if ( !msi_enable )
+            return;
+        vector = -domain_irq_to_vector(d, irq);
+        BUG_ON(vector <= 0);
+        desc = &irq_desc[vector];
+        spin_lock_irq(&desc->lock);
+        d->arch.pirq_vector[irq] = d->arch.vector_pirq[vector] = 0;
+    }
+    else
+    {
+        __pirq_guest_unbind(d, irq, desc);
+    }
+
+    spin_unlock_irq(&desc->lock);
+}
+
+int pirq_guest_force_unbind(struct domain *d, int irq)
+{
+    irq_desc_t *desc;
+    irq_guest_action_t *action;
+    int i, bound = 0;
+
+    WARN_ON(!spin_is_locked(&d->evtchn_lock));
+
+    BUG_ON(!local_irq_is_enabled());
+    desc = domain_spin_lock_irq_desc(d, irq, NULL);
+    BUG_ON(desc == NULL);
+
+    if ( !(desc->status & IRQ_GUEST) )
+        goto out;
+
+    action = (irq_guest_action_t *)desc->action;
+    for ( i = 0; (i < action->nr_guests) && (action->guest[i] != d); i++ )
+        continue;
+    if ( i == action->nr_guests )
+        goto out;
+
+    bound = 1;
+    __pirq_guest_unbind(d, irq, desc);
 
  out:
-    spin_unlock_irqrestore(&desc->lock, flags);
-    return rc;
+    spin_unlock_irq(&desc->lock);
+    return bound;
 }
 
 extern void dump_ioapic_irq_info(void);
Index: xen-3.3.1-testing/xen/arch/x86/physdev.c
===================================================================
--- xen-3.3.1-testing.orig/xen/arch/x86/physdev.c
+++ xen-3.3.1-testing/xen/arch/x86/physdev.c
@@ -147,7 +147,7 @@ static int unmap_domain_pirq(struct doma
     {
         unsigned long flags;
         irq_desc_t *desc;
-        bool_t forced_unbind = (pirq_guest_unbind(d, pirq) == 0);
+        bool_t forced_unbind = pirq_guest_force_unbind(d, pirq);
 
         if ( forced_unbind )
             dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
Index: xen-3.3.1-testing/xen/common/event_channel.c
===================================================================
--- xen-3.3.1-testing.orig/xen/common/event_channel.c
+++ xen-3.3.1-testing/xen/common/event_channel.c
@@ -376,8 +376,7 @@ static long __evtchn_close(struct domain
         break;
 
     case ECS_PIRQ:
-        if ( pirq_guest_unbind(d1, chn1->u.pirq) != 0 )
-            BUG();
+        pirq_guest_unbind(d1, chn1->u.pirq);
         d1->pirq_to_evtchn[chn1->u.pirq] = 0;
         break;
 
Index: xen-3.3.1-testing/xen/include/asm-x86/irq.h
===================================================================
--- xen-3.3.1-testing.orig/xen/include/asm-x86/irq.h
+++ xen-3.3.1-testing/xen/include/asm-x86/irq.h
@@ -55,4 +55,6 @@ int pirq_shared(struct domain *d , int i
 #define domain_irq_to_vector(d, irq) (msi_enable ? (d)->arch.pirq_vector[irq] : irq_to_vector(irq))
 #define domain_vector_to_irq(d, vec) (msi_enable ? (d)->arch.vector_pirq[vec] : vector_to_irq(vec))
 
+int pirq_guest_force_unbind(struct domain *d, int irq);
+
 #endif /* _ASM_HW_IRQ_H */
Index: xen-3.3.1-testing/xen/include/xen/irq.h
===================================================================
--- xen-3.3.1-testing.orig/xen/include/xen/irq.h
+++ xen-3.3.1-testing/xen/include/xen/irq.h
@@ -77,7 +77,7 @@ struct vcpu;
 extern int pirq_guest_eoi(struct domain *d, int irq);
 extern int pirq_guest_unmask(struct domain *d);
 extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share);
-extern int pirq_guest_unbind(struct domain *d, int irq);
+extern void pirq_guest_unbind(struct domain *d, int irq);
 
 static inline void set_native_irq_info(int irq, cpumask_t mask)
 {
openSUSE Build Service is sponsored by