diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-07-03 13:39:01 +0100 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-07-03 13:39:01 +0100 |
commit | 88fccdd11ca0c2df915d7d56ab78ea70d4b60e52 (patch) | |
tree | 8971d3b722ab6e62915aea2b9465080f6c64952f /xen/arch/x86/hvm/irq.c | |
parent | 97d39c5fbf23ea2c798b814893ffd2b0239ba44b (diff) | |
download | xen-88fccdd11ca0c2df915d7d56ab78ea70d4b60e52.tar.gz xen-88fccdd11ca0c2df915d7d56ab78ea70d4b60e52.tar.bz2 xen-88fccdd11ca0c2df915d7d56ab78ea70d4b60e52.zip |
xen: event channel remapping for emulated MSIs
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>
Diffstat (limited to 'xen/arch/x86/hvm/irq.c')
-rw-r--r-- | xen/arch/x86/hvm/irq.c | 25 |
1 files changed, 25 insertions, 0 deletions
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); } |