aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/pci
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2018-09-25 15:01:27 -0400
committerAlex Williamson <alex.williamson@redhat.com>2018-09-25 15:01:27 -0400
commitdb04264fe9bc0f2b62e036629f9afb530324b693 (patch)
tree6b80e98b183c9c3c36ff2ae3dcf2c41e906766e1 /drivers/vfio/pci
parent30ea32ab1951c80c6113f300fce2c70cd12659e4 (diff)
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 Tested-by: Gage Eads <gage.eads@intel.com> Reviewed-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio/pci')
-rw-r--r--drivers/vfio/pci/vfio_pci.c8
-rw-r--r--drivers/vfio/pci/vfio_pci_config.c27
2 files changed, 33 insertions, 2 deletions
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)
434{ 434{
435 if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { 435 if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) {
436 u8 pin; 436 u8 pin;
437
438 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) ||
439 vdev->nointx || vdev->pdev->is_virtfn)
440 return 0;
441
437 pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); 442 pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin);
438 if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin)
439 return 1;
440 443
444 return pin ? 1 : 0;
441 } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { 445 } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) {
442 u8 pos; 446 u8 pos;
443 u16 flags; 447 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
@@ -1612,6 +1612,15 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev)
1612} 1612}
1613 1613
1614/* 1614/*
1615 * Nag about hardware bugs, hopefully to have vendors fix them, but at least
1616 * to collect a list of dependencies for the VF INTx pin quirk below.
1617 */
1618static const struct pci_device_id known_bogus_vf_intx_pin[] = {
1619 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) },
1620 {}
1621};
1622
1623/*
1615 * For each device we allocate a pci_config_map that indicates the 1624 * For each device we allocate a pci_config_map that indicates the
1616 * capability occupying each dword and thus the struct perm_bits we 1625 * capability occupying each dword and thus the struct perm_bits we
1617 * use for read and write. We also allocate a virtualized config 1626 * use for read and write. We also allocate a virtualized config
@@ -1676,6 +1685,24 @@ int vfio_config_init(struct vfio_pci_device *vdev)
1676 if (pdev->is_virtfn) { 1685 if (pdev->is_virtfn) {
1677 *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor); 1686 *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor);
1678 *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); 1687 *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device);
1688
1689 /*
1690 * Per SR-IOV spec rev 1.1, 3.4.1.18 the interrupt pin register
1691 * does not apply to VFs and VFs must implement this register
1692 * as read-only with value zero. Userspace is not readily able
1693 * to identify whether a device is a VF and thus that the pin
1694 * definition on the device is bogus should it violate this
1695 * requirement. We already virtualize the pin register for
1696 * other purposes, so we simply need to replace the bogus value
1697 * and consider VFs when we determine INTx IRQ count.
1698 */
1699 if (vconfig[PCI_INTERRUPT_PIN] &&
1700 !pci_match_id(known_bogus_vf_intx_pin, pdev))
1701 pci_warn(pdev,
1702 "Hardware bug: VF reports bogus INTx pin %d\n",
1703 vconfig[PCI_INTERRUPT_PIN]);
1704
1705 vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */
1679 } 1706 }
1680 1707
1681 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) 1708 if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx)