x86/MSI-X: track host and guest mask-all requests separately Host uses of the bits will be added subsequently, and must not be overridden by guests (including Dom0, namely when acting on behalf of a guest). Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- sle12sp1.orig/xen/arch/x86/msi.c 2015-06-22 09:06:30.000000000 +0200 +++ sle12sp1/xen/arch/x86/msi.c 2015-06-22 09:23:08.000000000 +0200 @@ -843,6 +843,12 @@ static int msix_capability_init(struct p if ( !msix->used_entries ) { + msix->host_maskall = 0; + if ( !msix->guest_maskall ) + control &= ~PCI_MSIX_FLAGS_MASKALL; + else + control |= PCI_MSIX_FLAGS_MASKALL; + if ( rangeset_add_range(mmio_ro_ranges, msix->table.first, msix->table.last) ) WARN(); @@ -1111,6 +1117,34 @@ void pci_cleanup_msi(struct pci_dev *pde int pci_msi_conf_write_intercept(struct pci_dev *pdev, unsigned int reg, unsigned int size, uint32_t *data) { + u16 seg = pdev->seg; + u8 bus = pdev->bus; + u8 slot = PCI_SLOT(pdev->devfn); + u8 func = PCI_FUNC(pdev->devfn); + struct msi_desc *entry; + unsigned int pos; + + if ( pdev->msix ) + { + entry = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX); + pos = entry ? entry->msi_attrib.pos + : pci_find_cap_offset(seg, bus, slot, func, + PCI_CAP_ID_MSIX); + ASSERT(pos); + + if ( reg < pos || reg >= msix_pba_offset_reg(pos) + 4 ) + return 0; + + if ( reg != msix_control_reg(pos) || size != 2 ) + return -EACCES; + + pdev->msix->guest_maskall = !!(*data & PCI_MSIX_FLAGS_MASKALL); + if ( pdev->msix->host_maskall ) + *data |= PCI_MSIX_FLAGS_MASKALL; + + return 1; + } + return 0; } --- sle12sp1.orig/xen/include/asm-x86/msi.h 2015-07-08 00:00:00.000000000 +0200 +++ sle12sp1/xen/include/asm-x86/msi.h 2015-06-19 09:32:02.000000000 +0200 @@ -228,6 +228,7 @@ struct arch_msix { int table_refcnt[MAX_MSIX_TABLE_PAGES]; int table_idx[MAX_MSIX_TABLE_PAGES]; spinlock_t table_lock; + bool_t host_maskall, guest_maskall; domid_t warned; };