From a13b64591747e8a4ab2df24540a17fca34de2d34 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 22 Feb 2016 16:02:46 -0700 Subject: vfio/pci: Expose shadow ROM as PCI option ROM Integrated graphics may have their ROM shadowed at 0xc0000 rather than implement a PCI option ROM. Make this ROM appear to the user using the ROM BAR. Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 10 ++++++++-- drivers/vfio/pci/vfio_pci_config.c | 11 ++++++++--- drivers/vfio/pci/vfio_pci_rdwr.c | 9 ++++++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/vfio') diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 74a375297494..1ce1d364308c 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -609,8 +609,14 @@ static long vfio_pci_ioctl(void *device_data, /* Report the BAR size, not the ROM size */ info.size = pci_resource_len(pdev, info.index); - if (!info.size) - break; + if (!info.size) { + /* Shadow ROMs appear as PCI option ROMs */ + if (pdev->resource[PCI_ROM_RESOURCE].flags & + IORESOURCE_ROM_SHADOW) + info.size = 0x20000; + else + break; + } /* Is it really there? */ io = pci_map_rom(pdev, &size); diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 88dc646c0144..142c533efec7 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -475,14 +475,19 @@ static void vfio_bar_fixup(struct vfio_pci_device *vdev) bar = (__le32 *)&vdev->vconfig[PCI_ROM_ADDRESS]; /* - * NB. we expose the actual BAR size here, regardless of whether - * we can read it. When we report the REGION_INFO for the ROM - * we report what PCI tells us is the actual ROM size. + * NB. REGION_INFO will have reported zero size if we weren't able + * to read the ROM, but we still return the actual BAR size here if + * it exists (or the shadow ROM space). */ if (pci_resource_start(pdev, PCI_ROM_RESOURCE)) { mask = ~(pci_resource_len(pdev, PCI_ROM_RESOURCE) - 1); mask |= PCI_ROM_ADDRESS_ENABLE; *bar &= cpu_to_le32((u32)mask); + } else if (pdev->resource[PCI_ROM_RESOURCE].flags & + IORESOURCE_ROM_SHADOW) { + mask = ~(0x20000 - 1); + mask |= PCI_ROM_ADDRESS_ENABLE; + *bar &= cpu_to_le32((u32)mask); } else *bar = 0; diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 210db24d2204..5ffd1d9ad4bd 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -124,11 +124,14 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf, void __iomem *io; ssize_t done; - if (!pci_resource_start(pdev, bar)) + if (pci_resource_start(pdev, bar)) + end = pci_resource_len(pdev, bar); + else if (bar == PCI_ROM_RESOURCE && + pdev->resource[bar].flags & IORESOURCE_ROM_SHADOW) + end = 0x20000; + else return -EINVAL; - end = pci_resource_len(pdev, bar); - if (pos >= end) return -EINVAL; -- cgit v1.2.3-59-g8ed1b