xen: event channel remapping for emulated MSIs
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Tue, 3 Jul 2012 12:39:01 +0000 (13:39 +0100)
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>
Tue, 3 Jul 2012 12:39:01 +0000 (13:39 +0100)
Linux PV on HVM guests remap all the MSIs onto event channels,
including MSIs corresponding to QEMU's emulated devices.  This patch
makes sure that we handle correctly the case of emulated MSI that have
been remapped, sending a pirq to the guest instead.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Tested-by: Deep Debroy <ddebroy@gmail.com>
Committed-by: Keir Fraser <keir@xen.org>
xen/arch/x86/hvm/irq.c
xen/include/asm-x86/irq.h

index a90927aac79547e24807d788557321447907ee81..f44f3b957ee898a6ff7aad42262170f6a5f429a2 100644 (file)
@@ -281,6 +281,31 @@ void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
         >> MSI_DATA_TRIGGER_SHIFT;
     uint8_t vector = data & MSI_DATA_VECTOR_MASK;
 
+    if ( !vector )
+    {
+        int pirq = ((addr >> 32) & 0xffffff00) | ((addr >> 12) & 0xff);
+        if ( pirq > 0 )
+        {
+            struct pirq *info = pirq_info(d, pirq);
+
+            /* if it is the first time, allocate the pirq */
+            if (info->arch.hvm.emuirq == IRQ_UNBOUND)
+            {
+                spin_lock(&d->event_lock);
+                map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
+                spin_unlock(&d->event_lock);
+            } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
+            {
+                printk("%s: pirq %d does not correspond to an emulated MSI\n", __func__, pirq);
+                return;
+            }
+            send_guest_pirq(d, info);
+            return;
+        } else {
+            printk("%s: error getting pirq from MSI: pirq = %d\n", __func__, pirq);
+        }
+    }
+
     vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
 }
 
index 40e22452d62c9fb036eb0e30080f49ce234703db..066f64d91e9195298dd48953285516faaf2969b7 100644 (file)
@@ -188,6 +188,7 @@ void cleanup_domain_irq_mapping(struct domain *);
 })
 #define IRQ_UNBOUND -1
 #define IRQ_PT -2
+#define IRQ_MSI_EMU -3
 
 bool_t cpu_has_pending_apic_eoi(void);