diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index a90927aac7..f44f3b957e 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -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); } diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index 40e22452d6..066f64d91e 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -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);