Make sure the MSIX MMIO regions don't have p2m entries setup, so that accesses to them trap into the hypervisor and can be handled by vpci.
This is a side-effect of commit 042678762 for PVH Dom0, which added mappings for all the reserved regions into the Dom0 p2m. Signed-off-by: Roger Pau Monné <roger....@citrix.com> --- Cc: Andrew Cooper <andrew.coop...@citrix.com> Cc: George Dunlap <george.dun...@eu.citrix.com> Cc: Ian Jackson <ian.jack...@eu.citrix.com> Cc: Jan Beulich <jbeul...@suse.com> Cc: Julien Grall <julien.gr...@arm.com> Cc: Konrad Rzeszutek Wilk <konrad.w...@oracle.com> Cc: Stefano Stabellini <sstabell...@kernel.org> Cc: Tim Deegan <t...@xen.org> Cc: Wei Liu <wei.l...@citrix.com> --- xen/drivers/vpci/header.c | 8 ++++++++ xen/drivers/vpci/msix.c | 40 +++++++++++++++++++++++++++++++++++++++ xen/include/xen/vpci.h | 3 +++ 3 files changed, 51 insertions(+) diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index 4af85d3c02..455dd4fc90 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -88,6 +88,14 @@ static void modify_decoding(const struct pci_dev *pdev, bool map, bool rom_only) uint16_t cmd; 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. + */ + if ( map && !rom_only && vpci_make_msix_hole(pdev) ) + return; + for ( i = 0; i < ARRAY_SIZE(header->bars); i++ ) { if ( !MAPPABLE_BAR(&header->bars[i]) ) diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c index 1960dae123..5759551724 100644 --- a/xen/drivers/vpci/msix.c +++ b/xen/drivers/vpci/msix.c @@ -21,6 +21,7 @@ #include <xen/vpci.h> #include <asm/msi.h> +#include <asm/p2m.h> #define VMSIX_SIZE(num) offsetof(struct vpci_msix, entries[num]) @@ -395,6 +396,45 @@ static const struct hvm_mmio_ops vpci_msix_table_ops = { .write = msix_write, }; +int vpci_make_msix_hole(const struct pci_dev *pdev) +{ + struct domain *d = pdev->domain; + unsigned int i; + + if ( !pdev->vpci->msix ) + return 0; + + /* Make sure there's a hole for the MSIX table/PBA in the p2m. */ + for ( i = 0; i < ARRAY_SIZE(pdev->vpci->msix->tables); i++ ) + { + unsigned long start = PFN_DOWN(vmsix_table_addr(pdev->vpci, i)); + unsigned long end = PFN_DOWN(vmsix_table_addr(pdev->vpci, i) + + vmsix_table_size(pdev->vpci, i) - 1); + + for ( ; start <= end; start++ ) + { + p2m_type_t t; + mfn_t mfn = get_gfn_query(d, start, &t); + + if ( t == p2m_mmio_direct && mfn_x(mfn) == start ) + clear_identity_p2m_entry(d, start); + else if ( t != p2m_mmio_dm ) + { + put_gfn(d, start); + gprintk(XENLOG_WARNING, + "%04x:%02x:%02x.%u: existing mapping (mfn: %" PRI_mfn + "type: %d) at %#lx clobbers MSIX MMIO area\n", + pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), mfn_x(mfn), t, start); + return -EEXIST; + } + put_gfn(d, start); + } + } + + return 0; +} + static int init_msix(struct pci_dev *pdev) { struct domain *d = pdev->domain; diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index f97c48a8f1..e0c22ad81c 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -151,6 +151,9 @@ struct vpci_vcpu { #ifdef __XEN__ void vpci_dump_msi(void); +/* Make sure there's a hole in the p2m for the MSIX mmio areas. */ +int vpci_make_msix_hole(const struct pci_dev *pdev); + /* Arch-specific vPCI MSI helpers. */ void vpci_msi_arch_mask(struct vpci_msi *msi, const struct pci_dev *pdev, unsigned int entry, bool mask); -- 2.19.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel