This patch tries to expose MSI-X tables to userspace if hardware enables interrupt remapping. This capability can ensure that a given PCI device can only shoot the MSIs assigned for it. That means a userspace driver could never hurt other devices or system by writing to the exposed MSI-X table directly. Signed-off-by: Yongji Xie <xyjxie@xxxxxxxxxxxxxxxxxx> --- drivers/vfio/pci/vfio_pci.c | 17 ++++++++++++++--- drivers/vfio/pci/vfio_pci_rdwr.c | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 188b1ff..6bae388 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -487,8 +487,12 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev, end = pci_resource_len(vdev->pdev, vdev->msix_bar); - /* If MSI-X table is aligned to the start or end, only one area */ - if (((vdev->msix_offset & PAGE_MASK) == 0) || + /* + * If MSI-X table is allowed to mmap because of the capability + * of IRQ remapping or aligned to the start or end, only one area + */ + if ((vdev->pdev->bus->bus_flags & PCI_BUS_FLAGS_MSI_REMAP) || + ((vdev->msix_offset & PAGE_MASK) == 0) || (PAGE_ALIGN(vdev->msix_offset + vdev->msix_size) >= end)) nr_areas = 1; @@ -503,6 +507,12 @@ static int msix_sparse_mmap_cap(struct vfio_pci_device *vdev, struct vfio_region_info_cap_sparse_mmap, header); sparse->nr_areas = nr_areas; + if (vdev->pdev->bus->bus_flags & PCI_BUS_FLAGS_MSI_REMAP) { + sparse->areas[i].offset = 0; + sparse->areas[i].size = end; + return 0; + } + if (vdev->msix_offset & PAGE_MASK) { sparse->areas[i].offset = 0; sparse->areas[i].size = vdev->msix_offset & PAGE_MASK; @@ -1061,7 +1071,8 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) if (phys_len < PAGE_SIZE || req_start + req_len > phys_len) return -EINVAL; - if (index == vdev->msix_bar) { + if (index == vdev->msix_bar && + !(pdev->bus->bus_flags & PCI_BUS_FLAGS_MSI_REMAP)) { /* * Disallow mmaps overlapping the MSI-X table; users don't * get to touch this directly. We could find somewhere diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 5ffd1d9..dbf9cd0 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -164,7 +164,8 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf, } else io = vdev->barmap[bar]; - if (bar == vdev->msix_bar) { + if (bar == vdev->msix_bar && + !(pdev->bus->bus_flags & PCI_BUS_FLAGS_MSI_REMAP)) { x_start = vdev->msix_offset; x_end = vdev->msix_offset + vdev->msix_size; } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html