diff mbox series

[v2] vfio/pci: Mask buggy SR-IOV VF INTx support

Message ID 153747346143.7344.14634545723456004489.stgit@gimli.home (mailing list archive)
State New, archived
Headers show
Series [v2] vfio/pci: Mask buggy SR-IOV VF INTx support | expand

Commit Message

Alex Williamson Sept. 20, 2018, 8:03 p.m. UTC
The SR-IOV spec requires that VFs must report zero for the INTx pin
register as VFs are precluded from INTx support.  It's much easier for
the host kernel to understand whether a device is a VF and therefore
whether a non-zero pin register value is bogus than it is to do the
same in userspace.  Override the INTx count for such devices and
virtualize the pin register to provide a consistent view of the device
to the user.

As this is clearly a spec violation, warn about it to support hardware
validation, but also provide a known whitelist as it doesn't do much
good to continue complaining if the hardware vendor doesn't plan to
fix it.

Known devices with this issue: 8086:270c

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

v2:
Moved the warning to vfio_config_init(), so it triggers on device open and
no longer depends on the user looking at the number of INTx IRQs available.
Also changed from dev_warn_once() to pci_warn() as this new location seems
sufficiently low frequency to nag repeatedly.  Please test.  Thanks,

Alex

 drivers/vfio/pci/vfio_pci.c        |    8 ++++++--
 drivers/vfio/pci/vfio_pci_config.c |   27 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

Comments

Eads, Gage Sept. 20, 2018, 10:56 p.m. UTC | #1
Hi Alex,

This patch passes testing with the 0x270c device, and (when I comment out its known_bogus_vf_intx_pin entry) the warning is triggered by QEMU.

Thanks,
Gage

> -----Original Message-----
> From: Alex Williamson [mailto:alex.williamson@redhat.com]
> Sent: Thursday, September 20, 2018 3:03 PM
> To: kvm@vger.kernel.org; Raj, Ashok <ashok.raj@intel.com>; Eads, Gage
> <gage.eads@intel.com>
> Cc: gnomes@lxorguk.ukuu.org.uk; linux-kernel@vger.kernel.org
> Subject: [PATCH v2] vfio/pci: Mask buggy SR-IOV VF INTx support
> 
> The SR-IOV spec requires that VFs must report zero for the INTx pin register as
> VFs are precluded from INTx support.  It's much easier for the host kernel to
> understand whether a device is a VF and therefore whether a non-zero pin
> register value is bogus than it is to do the same in userspace.  Override the INTx
> count for such devices and virtualize the pin register to provide a consistent view
> of the device to the user.
> 
> As this is clearly a spec violation, warn about it to support hardware validation,
> but also provide a known whitelist as it doesn't do much good to continue
> complaining if the hardware vendor doesn't plan to fix it.
> 
> Known devices with this issue: 8086:270c
> 
> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

Tested-by: Gage Eads <gage.eads@intel.com>
Ashok Raj Sept. 20, 2018, 10:58 p.m. UTC | #2
On Thu, Sep 20, 2018 at 03:56:41PM -0700, Eads, Gage wrote:
Thanks Gage.


> Hi Alex,
> > 
> > Known devices with this issue: 8086:270c
> > 
> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> 
> Tested-by: Gage Eads <gage.eads@intel.com>

Reviewed-by: Ashok Raj <ashok.raj@intel.com>
Christoph Hellwig Sept. 21, 2018, 5:53 a.m. UTC | #3
> +/*
> + * Nag about hardware bugs, hopefully to have vendors fix them, but at least
> + * to collect a list of dependencies for the VF INTx pin quirk below.
> + */
> +static const struct pci_device_id known_bogus_vf_intx_pin[] = {
> +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) },
> +	{}
> +};

What device is this? We don't have the device ID anywhere, so I guess
it is something match by the class code?
Alex Williamson Sept. 21, 2018, 3:16 p.m. UTC | #4
On Thu, 20 Sep 2018 22:53:04 -0700
Christoph Hellwig <hch@infradead.org> wrote:

> > +/*
> > + * Nag about hardware bugs, hopefully to have vendors fix them, but at least
> > + * to collect a list of dependencies for the VF INTx pin quirk below.
> > + */
> > +static const struct pci_device_id known_bogus_vf_intx_pin[] = {
> > +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) },
> > +	{}
> > +};  
> 
> What device is this? We don't have the device ID anywhere, so I guess
> it is something match by the class code?

Intel hasn't disclosed the device yet, so we don't know that there's an
existing driver at all for it.  Thanks,

Alex
diff mbox series

Patch

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index cddb453a1ba5..50cdedfca9fe 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -434,10 +434,14 @@  static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
 {
 	if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
 		u8 pin;
+
+		if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
+		    vdev->nointx || vdev->pdev->is_virtfn)
+			return 0;
+
 		pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
-		if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin)
-			return 1;
 
+		return pin ? 1 : 0;
 	} else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
 		u8 pos;
 		u16 flags;
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 62023b4a373b..423ea1f98441 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -1611,6 +1611,15 @@  static int vfio_ecap_init(struct vfio_pci_device *vdev)
 	return 0;
 }
 
+/*
+ * Nag about hardware bugs, hopefully to have vendors fix them, but at least
+ * to collect a list of dependencies for the VF INTx pin quirk below.
+ */
+static const struct pci_device_id known_bogus_vf_intx_pin[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) },
+	{}
+};
+
 /*
  * For each device we allocate a pci_config_map that indicates the
  * capability occupying each dword and thus the struct perm_bits we
@@ -1676,6 +1685,24 @@  int vfio_config_init(struct vfio_pci_device *vdev)
 	if (pdev->is_virtfn) {
 		*(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor);
 		*(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device);
+
+		/*
+		 * Per SR-IOV spec rev 1.1, 3.4.1.18 the interrupt pin register
+		 * does not apply to VFs and VFs must implement this register
+		 * as read-only with value zero.  Userspace is not readily able
+		 * to identify whether a device is a VF and thus that the pin
+		 * definition on the device is bogus should it violate this
+		 * requirement.  We already virtualize the pin register for
+		 * other purposes, so we simply need to replace the bogus value
+		 * and consider VFs when we determine INTx IRQ count.
+		 */
+		if (vconfig[PCI_INTERRUPT_PIN] &&
+		    !pci_match_id(known_bogus_vf_intx_pin, pdev))
+			pci_warn(pdev,
+				 "Hardware bug: VF reports bogus INTx pin %d\n",
+				 vconfig[PCI_INTERRUPT_PIN]);
+
+		vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */
 	}
 
 	if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)