]> xenbits.xensource.com Git - xen.git/commitdiff
x86/MSI: fix guest unmasking when handling IRQ via event channel
authorJan Beulich <jbeulich@suse.com>
Fri, 10 Jul 2015 10:36:24 +0000 (12:36 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 10 Jul 2015 10:36:24 +0000 (12:36 +0200)
Rather than assuming only PV guests need special treatment (and
dealing with that directly when an IRQ gets set up), keep all guest MSI
IRQs masked until either the (HVM) guest unmasks them via vMSI or the
(PV, PVHVM, or PVH) guest sets up an event channel for it.

To not further clutter the common evtchn_bind_pirq() with x86-specific
code, introduce an arch_evtchn_bind_pirq() hook instead.

Reported-by: Sander Eikelenboom <linux@eikelenboom.it>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Sander Eikelenboom <linux@eikelenboom.it>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/x86/irq.c
xen/arch/x86/msi.c
xen/common/event_channel.c
xen/include/asm-arm/irq.h
xen/include/xen/irq.h

index fe1ee333b870d91b32afc4a21625af09ecd28f96..78e3f2e845699c544772caeae4214c512945acf6 100644 (file)
@@ -2502,6 +2502,25 @@ int unmap_domain_pirq_emuirq(struct domain *d, int pirq)
     return ret;
 }
 
+void arch_evtchn_bind_pirq(struct domain *d, int pirq)
+{
+    int irq = domain_pirq_to_irq(d, pirq);
+    struct irq_desc *desc;
+    unsigned long flags;
+
+    if ( irq <= 0 )
+        return;
+
+    if ( is_hvm_domain(d) )
+        map_domain_emuirq_pirq(d, pirq, IRQ_PT);
+
+    desc = irq_to_desc(irq);
+    spin_lock_irqsave(&desc->lock, flags);
+    if ( desc->msi_desc )
+        guest_mask_msi_irq(desc, 0);
+    spin_unlock_irqrestore(&desc->lock, flags);
+}
+
 bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq)
 {
     return is_hvm_domain(d) && pirq &&
index a8923fcfdbde6880e53b882da2a1fddcece08241..d930f8f0f77d9bffb4a751cc24f2c8a3b1fec378 100644 (file)
@@ -422,10 +422,7 @@ void guest_mask_msi_irq(struct irq_desc *desc, bool_t mask)
 
 static unsigned int startup_msi_irq(struct irq_desc *desc)
 {
-    bool_t guest_masked = (desc->status & IRQ_GUEST) &&
-                          is_hvm_domain(desc->msi_desc->dev->domain);
-
-    msi_set_mask_bit(desc, 0, guest_masked);
+    msi_set_mask_bit(desc, 0, !!(desc->status & IRQ_GUEST));
     return 0;
 }
 
index 679618aa9de7e9f8a08a344b4070ffaa80ee9950..7640e30ef83de1fe53b6df1f1060bc84a53ebfe2 100644 (file)
@@ -503,10 +503,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
 
     bind->port = port;
 
-#ifdef CONFIG_X86
-    if ( is_hvm_domain(d) && domain_pirq_to_irq(d, pirq) > 0 )
-        map_domain_emuirq_pirq(d, pirq, IRQ_PT);
-#endif
+    arch_evtchn_bind_pirq(d, pirq);
 
  out:
     spin_unlock(&d->event_lock);
index 6c00d09ceae1e9adc23d2aeb3d212c65f5d068b8..f33c3315acba64b3af3615274d053a87bf001e76 100644 (file)
@@ -47,6 +47,8 @@ int release_guest_irq(struct domain *d, unsigned int irq);
 
 void arch_move_irqs(struct vcpu *v);
 
+#define arch_evtchn_bind_pirq(d, pirq) ((void)((d) + (pirq)))
+
 /* Set IRQ type for an SPI */
 int irq_set_spi_type(unsigned int spi, unsigned int type);
 
index 9e0155c17620062be83ededf1b13c9d998d28077..0aa817e266b3ac8249969cdc66e42a9fa117bbb1 100644 (file)
@@ -172,4 +172,8 @@ unsigned int set_desc_affinity(struct irq_desc *, const cpumask_t *);
 unsigned int arch_hwdom_irqs(domid_t);
 #endif
 
+#ifndef arch_evtchn_bind_pirq
+void arch_evtchn_bind_pirq(struct domain *, int pirq);
+#endif
+
 #endif /* __XEN_IRQ_H__ */