diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index 1c0818c2e7..a760d8c32f 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -123,19 +123,6 @@ static void modify_decoding(const struct pci_dev *pdev, uint16_t cmd, bool map = cmd & PCI_COMMAND_MEMORY; unsigned int i; - /* - * Make sure there are no mappings in the MSIX MMIO areas, so that accesses - * can be trapped (and emulated) by Xen when the memory decoding bit is - * enabled. - * - * FIXME: punching holes after the p2m has been set up might be racy for - * DomU usage, needs to be revisited. - */ -#ifdef CONFIG_HAS_PCI_MSI - if ( map && !rom_only && vpci_make_msix_hole(pdev) ) - return; -#endif - for ( i = 0; i < ARRAY_SIZE(header->bars); i++ ) { struct vpci_bar *bar = &header->bars[i]; @@ -165,6 +152,19 @@ static void modify_decoding(const struct pci_dev *pdev, uint16_t cmd, bar->enabled = map; } + /* + * Make sure there are no mappings in the MSIX MMIO areas, so that accesses + * can be trapped (and emulated) by Xen when the memory decoding bit is + * enabled. + * + * FIXME: punching holes after the p2m has been set up might be racy for + * DomU usage, needs to be revisited. + */ +#ifdef CONFIG_HAS_PCI_MSI + if ( map && !rom_only && vpci_make_msix_hole(pdev) ) + return; +#endif + if ( !rom_only ) { pci_conf_write16(pdev->sbdf, PCI_COMMAND, cmd); diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c index f87212b46f..bbe4f213ac 100644 --- a/xen/drivers/vpci/msix.c +++ b/xen/drivers/vpci/msix.c @@ -606,6 +606,9 @@ int vpci_make_msix_hole(const struct pci_dev *pdev) unsigned long end = PFN_DOWN(vmsix_table_addr(pdev->vpci, i) + vmsix_table_size(pdev->vpci, i) - 1); + if ( !vmsix_table_bar_valid(pdev->vpci, i) ) + continue; + for ( ; start <= end; start++ ) { p2m_type_t t; diff --git a/xen/drivers/vpci/private.h b/xen/drivers/vpci/private.h index 140092cc52..fdeeca7aa8 100644 --- a/xen/drivers/vpci/private.h +++ b/xen/drivers/vpci/private.h @@ -119,6 +119,12 @@ static inline paddr_t vmsix_table_addr(const struct vpci *vpci, unsigned int nr) (vpci->msix->tables[nr] & ~PCI_MSIX_BIRMASK); } +static inline bool vmsix_table_bar_valid(const struct vpci *vpci, + unsigned int nr) +{ + return vpci->header.bars[vpci->msix->tables[nr] & PCI_MSIX_BIRMASK].enabled; +} + /* * Note regarding the size calculation of the PBA: the spec mentions "The last * QWORD will not necessarily be fully populated", so it implies that the PBA