x86: Fix unmaskable MSI handling, and also some other EOI-notification issues.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 21 Jan 2009 14:44:43 +0000 (14:44 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 21 Jan 2009 14:44:43 +0000 (14:44 +0000)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/io_apic.c
xen/arch/x86/irq.c
xen/arch/x86/physdev.c
xen/include/asm-x86/irq.h

index 43ca13a2aecd99af60797ff66ffdf106d95d0310..3f2c3426ff100d60c5104ed6e379e09ec6981684 100644 (file)
@@ -1554,11 +1554,14 @@ static unsigned int startup_msi_vector(unsigned int vector)
 
 static void ack_msi_vector(unsigned int vector)
 {
-    ack_APIC_irq();
+    if ( msi_maskable_irq(irq_desc[vector].msi_desc) )
+        ack_APIC_irq(); /* ACKTYPE_NONE */
 }
 
 static void end_msi_vector(unsigned int vector)
 {
+    if ( !msi_maskable_irq(irq_desc[vector].msi_desc) )
+        ack_APIC_irq(); /* ACKTYPE_EOI */
 }
 
 static void shutdown_msi_vector(unsigned int vector)
index d86ae03d32d69003879c1fa96f0cb6de530fc7f1..ffcb0fcdf91986708791581eccaba4960e2605dc 100644 (file)
@@ -705,6 +705,10 @@ static irq_guest_action_t *__pirq_guest_unbind(
             spin_lock_irq(&desc->lock);
         }
         break;
+    case ACKTYPE_NONE:
+        stop_timer(&irq_guest_eoi_timer[vector]);
+        _irq_guest_eoi(desc);
+        break;
     }
 
     /*
@@ -853,10 +857,6 @@ int map_domain_pirq(
     ASSERT(spin_is_locked(&pcidevs_lock));
     ASSERT(spin_is_locked(&d->event_lock));
 
-    /* XXX Until pcidev and msi locking is fixed. */
-    if ( type == MAP_PIRQ_TYPE_MSI )
-        return -EINVAL;
-
     if ( !IS_PRIV(current->domain) )
         return -EPERM;
 
index bb4d08e81b0aa5fc89e7c45a121c8c94abe40416..63ef08893bfc163da5f01ae3509290a0c468ed7f 100644 (file)
@@ -257,8 +257,15 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         if ( (irq < 0) || (irq >= NR_IRQS) )
             break;
         irq_status_query.flags = 0;
-        if ( pirq_acktype(v->domain, irq) != 0 )
-            irq_status_query.flags |= XENIRQSTAT_needs_eoi;
+        /*
+         * Even edge-triggered or message-based IRQs can need masking from
+         * time to time. If teh guest is not dynamically checking for this
+         * via the new pirq_eoi_map mechanism, it must conservatively always
+         * execute the EOI hypercall. In practice, this only really makes a
+         * difference for maskable MSI sources, and if those are supported
+         * then dom0 is probably modern anyway.
+         */
+        irq_status_query.flags |= XENIRQSTAT_needs_eoi;
         if ( pirq_shared(v->domain, irq) )
             irq_status_query.flags |= XENIRQSTAT_shared;
         ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
index 8765f3906178e45765044a19da8d389d8e0dcb53..2f1e59f148aca880717f5d8834455b961663791a 100644 (file)
@@ -52,7 +52,6 @@ extern unsigned long io_apic_irqs;
 extern atomic_t irq_err_count;
 extern atomic_t irq_mis_count;
 
-int pirq_acktype(struct domain *d, int irq);
 int pirq_shared(struct domain *d , int irq);
 
 int map_domain_pirq(struct domain *d, int pirq, int vector, int type,