summaryrefslogtreecommitdiffstats
path: root/hw/xen/xen_pt_msi.c
diff options
context:
space:
mode:
authorRoger Pau Monne2017-08-24 17:07:03 +0200
committerStefano Stabellini2017-09-21 04:05:27 +0200
commita8036336609d2e184fc3543a4c439c0ba7d7f3a2 (patch)
tree7d7d312ebc27ee49c12cc0411ac22e4034c74db4 /hw/xen/xen_pt_msi.c
parentxen-disk: use g_new0 to fix build (diff)
downloadqemu-a8036336609d2e184fc3543a4c439c0ba7d7f3a2.tar.gz
qemu-a8036336609d2e184fc3543a4c439c0ba7d7f3a2.tar.xz
qemu-a8036336609d2e184fc3543a4c439c0ba7d7f3a2.zip
xen/pt: allow QEMU to request MSI unmasking at bind time
When a MSI interrupt is bound to a guest using xc_domain_update_msi_irq (XEN_DOMCTL_bind_pt_irq) the interrupt is left masked by default. This causes problems with guests that first configure interrupts and clean the per-entry MSIX table mask bit and afterwards enable MSIX globally. In such scenario the Xen internal msixtbl handlers would not detect the unmasking of MSIX entries because vectors are not yet registered since MSIX is not enabled, and vectors would be left masked. Introduce a new flag in the gflags field to signal Xen whether a MSI interrupt should be unmasked after being bound. This also requires to track the mask register for MSI interrupts, so QEMU can also notify to Xen whether the MSI interrupt should be bound masked or unmasked Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Reported-by: Andreas Kinzler <hfp@posteo.de> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
Diffstat (limited to 'hw/xen/xen_pt_msi.c')
-rw-r--r--hw/xen/xen_pt_msi.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c
index ff9a79f5d2..6d1e3bdeb4 100644
--- a/hw/xen/xen_pt_msi.c
+++ b/hw/xen/xen_pt_msi.c
@@ -24,6 +24,7 @@
#define XEN_PT_GFLAGS_SHIFT_DM 9
#define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12
#define XEN_PT_GFLAGSSHIFT_TRG_MODE 15
+#define XEN_PT_GFLAGSSHIFT_UNMASKED 16
#define latch(fld) latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)]
@@ -155,7 +156,8 @@ static int msi_msix_update(XenPCIPassthroughState *s,
int pirq,
bool is_msix,
int msix_entry,
- int *old_pirq)
+ int *old_pirq,
+ bool masked)
{
PCIDevice *d = &s->dev;
uint8_t gvec = msi_vector(data);
@@ -171,6 +173,8 @@ static int msi_msix_update(XenPCIPassthroughState *s,
table_addr = s->msix->mmio_base_addr;
}
+ gflags |= masked ? 0 : (1u << XEN_PT_GFLAGSSHIFT_UNMASKED);
+
rc = xc_domain_update_msi_irq(xen_xc, xen_domid, gvec,
pirq, gflags, table_addr);
@@ -273,8 +277,10 @@ int xen_pt_msi_setup(XenPCIPassthroughState *s)
int xen_pt_msi_update(XenPCIPassthroughState *s)
{
XenPTMSI *msi = s->msi;
+
+ /* Current MSI emulation in QEMU only supports 1 vector */
return msi_msix_update(s, msi_addr64(msi), msi->data, msi->pirq,
- false, 0, &msi->pirq);
+ false, 0, &msi->pirq, msi->mask & 1);
}
void xen_pt_msi_disable(XenPCIPassthroughState *s)
@@ -355,7 +361,8 @@ static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr,
}
rc = msi_msix_update(s, entry->addr, entry->data, pirq, true,
- entry_nr, &entry->pirq);
+ entry_nr, &entry->pirq,
+ vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT);
if (!rc) {
entry->updated = false;