aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/irq.c
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-07-03 13:39:01 +0100
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-07-03 13:39:01 +0100
commit88fccdd11ca0c2df915d7d56ab78ea70d4b60e52 (patch)
tree8971d3b722ab6e62915aea2b9465080f6c64952f /xen/arch/x86/hvm/irq.c
parent97d39c5fbf23ea2c798b814893ffd2b0239ba44b (diff)
downloadxen-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.c25
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);
}