94 lines
3.2 KiB
Diff
94 lines
3.2 KiB
Diff
|
x86/MSI: fix guest unmasking when handling IRQ via event channel
|
||
|
|
||
|
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>
|
||
|
|
||
|
--- sle12sp1.orig/xen/arch/x86/irq.c 2015-07-08 12:33:47.000000000 +0200
|
||
|
+++ sle12sp1/xen/arch/x86/irq.c 2015-07-07 17:04:08.000000000 +0200
|
||
|
@@ -2502,6 +2502,25 @@ int unmap_domain_pirq_emuirq(struct doma
|
||
|
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 &&
|
||
|
--- sle12sp1.orig/xen/arch/x86/msi.c 2015-07-08 00:00:00.000000000 +0200
|
||
|
+++ sle12sp1/xen/arch/x86/msi.c 2015-07-07 16:50:02.000000000 +0200
|
||
|
@@ -422,10 +422,7 @@ void guest_mask_msi_irq(struct irq_desc
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
--- sle12sp1.orig/xen/common/event_channel.c 2015-07-08 14:04:08.000000000 +0200
|
||
|
+++ sle12sp1/xen/common/event_channel.c 2015-07-07 16:53:47.000000000 +0200
|
||
|
@@ -504,10 +504,7 @@ static long evtchn_bind_pirq(evtchn_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);
|
||
|
--- sle12sp1.orig/xen/include/asm-arm/irq.h 2015-07-08 12:33:47.000000000 +0200
|
||
|
+++ sle12sp1/xen/include/asm-arm/irq.h 2015-07-07 17:02:00.000000000 +0200
|
||
|
@@ -44,6 +44,8 @@ int route_irq_to_guest(struct domain *d,
|
||
|
const char *devname);
|
||
|
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);
|
||
|
|
||
|
--- sle12sp1.orig/xen/include/xen/irq.h 2015-07-08 12:33:47.000000000 +0200
|
||
|
+++ sle12sp1/xen/include/xen/irq.h 2015-07-07 17:02:49.000000000 +0200
|
||
|
@@ -172,4 +172,8 @@ unsigned int set_desc_affinity(struct ir
|
||
|
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__ */
|