From 8effc395c2097e258fcedfc02ed4a66d45fb4238 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 21 Apr 2018 15:23:09 -0500 Subject: PCI/IOV: Add pci_sriov_configure_simple() SR-IOV (Single Root I/O Virtualization) is an optional PCIe capability (see PCIe r4.0, sec 9). A PCIe Function with the SR-IOV capability is referred to as a PF (Physical Function). If SR-IOV is enabled on the PF, several VFs (Virtual Functions) may be created. The VFs can be individually assigned to virtual machines, which allows them to share a single hardware device while being isolated from each other. Some SR-IOV devices have resources such as queues and interrupts that must be set up in the PF before enabling the VFs, so they require a PF driver to do that. Other SR-IOV devices don't require any PF setup before enabling VFs. Add a pci_sriov_configure_simple() interface so PF drivers for such devices can use it without repeating the VF-enabling code. Tested-by: Mark Rustad Signed-off-by: Alexander Duyck [bhelgaas: changelog, comment] Signed-off-by: Bjorn Helgaas Reviewed-by: Greg Rose Reviewed-by: Christoph Hellwig :wq --- drivers/pci/iov.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 8adf4a64f291..192b82898a38 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -833,3 +833,39 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev) return dev->sriov->total_VFs; } EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs); + +/** + * pci_sriov_configure_simple - helper to configure SR-IOV + * @dev: the PCI device + * @nr_virtfn: number of virtual functions to enable, 0 to disable + * + * Enable or disable SR-IOV for devices that don't require any PF setup + * before enabling SR-IOV. Return value is negative on error, or number of + * VFs allocated on success. + */ +int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn) +{ + int rc; + + might_sleep(); + + if (!dev->is_physfn) + return -ENODEV; + + if (pci_vfs_assigned(dev)) { + pci_warn(dev, "Cannot modify SR-IOV while VFs are assigned\n"); + return -EPERM; + } + + if (nr_virtfn == 0) { + sriov_disable(dev); + return 0; + } + + rc = sriov_enable(dev, nr_virtfn); + if (rc < 0) + return rc; + + return nr_virtfn; +} +EXPORT_SYMBOL_GPL(pci_sriov_configure_simple); -- cgit v1.2.3 From a8ccf8a666639ca9184e8b23d515d9fbe722a27d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 24 Apr 2018 16:47:16 -0500 Subject: PCI/IOV: Add pci-pf-stub driver for PFs that only enable VFs Some SR-IOV PF devices provide no functionality other than acting as a means of enabling VFs. For these devices, we want to enable the VFs and assign them to guest virtual machines, but there's no need to have a driver for the PF itself. Add a new pci-pf-stub driver to claim those PF devices and provide the generic VF enable functionality. An administrator can use the sysfs "sriov_numvfs" file to enable VFs, then assign them to guests. For now I only have one example ID provided by Amazon in terms of devices that require this functionality. The general idea is that in the future we will see other devices added as vendors come up with devices where the PF is more or less just a lightweight shim used to allocate VFs. Signed-off-by: Alexander Duyck [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas Reviewed-by: Greg Rose Reviewed-by: Christoph Hellwig --- drivers/pci/Kconfig | 12 +++++++++++ drivers/pci/Makefile | 1 + drivers/pci/pci-pf-stub.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 2 ++ 4 files changed, 69 insertions(+) create mode 100644 drivers/pci/pci-pf-stub.c (limited to 'drivers/pci') diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 34b56a8f8480..cdef2a2a9bc5 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -71,6 +71,18 @@ config PCI_STUB When in doubt, say N. +config PCI_PF_STUB + tristate "PCI PF Stub driver" + depends on PCI + depends on PCI_IOV + help + Say Y or M here if you want to enable support for devices that + require SR-IOV support, while at the same time the PF itself is + not providing any actual services on the host itself such as + storage or networking. + + When in doubt, say N. + config XEN_PCIDEV_FRONTEND tristate "Xen PCI Frontend" depends on PCI && X86 && XEN diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 952addc7bacf..84c9eef6b1c3 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_PCI_LABEL) += pci-label.o obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o obj-$(CONFIG_PCI_SYSCALL) += syscall.o obj-$(CONFIG_PCI_STUB) += pci-stub.o +obj-$(CONFIG_PCI_PF_STUB) += pci-pf-stub.o obj-$(CONFIG_PCI_ECAM) += ecam.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o diff --git a/drivers/pci/pci-pf-stub.c b/drivers/pci/pci-pf-stub.c new file mode 100644 index 000000000000..9795649fc6f9 --- /dev/null +++ b/drivers/pci/pci-pf-stub.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* pci-pf-stub - simple stub driver for PCI SR-IOV PF device + * + * This driver is meant to act as a "whitelist" for devices that provde + * SR-IOV functionality while at the same time not actually needing a + * driver of their own. + */ + +#include +#include + +/** + * pci_pf_stub_whitelist - White list of devices to bind pci-pf-stub onto + * + * This table provides the list of IDs this driver is supposed to bind + * onto. You could think of this as a list of "quirked" devices where we + * are adding support for SR-IOV here since there are no other drivers + * that they would be running under. + */ +static const struct pci_device_id pci_pf_stub_whitelist[] = { + { PCI_VDEVICE(AMAZON, 0x0053) }, + /* required last entry */ + { 0 } +}; +MODULE_DEVICE_TABLE(pci, pci_pf_stub_whitelist); + +static int pci_pf_stub_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + pci_info(dev, "claimed by pci-pf-stub\n"); + return 0; +} + +static struct pci_driver pf_stub_driver = { + .name = "pci-pf-stub", + .id_table = pci_pf_stub_whitelist, + .probe = pci_pf_stub_probe, + .sriov_configure = pci_sriov_configure_simple, +}; + +static int __init pci_pf_stub_init(void) +{ + return pci_register_driver(&pf_stub_driver); +} + +static void __exit pci_pf_stub_exit(void) +{ + pci_unregister_driver(&pf_stub_driver); +} + +module_init(pci_pf_stub_init); +module_exit(pci_pf_stub_exit); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index cc608fc55334..411c12287dda 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2552,6 +2552,8 @@ #define PCI_VENDOR_ID_CIRCUITCO 0x1cc8 #define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001 +#define PCI_VENDOR_ID_AMAZON 0x1d0f + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- cgit v1.2.3 From e8440f4bfedc623bee40c84797ac78d9303d0db6 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 25 Apr 2018 14:27:37 -0600 Subject: PCI: Add ACS quirk for Intel 7th & 8th Gen mobile The specification update indicates these have the same errata for implementing non-standard ACS capabilities. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org --- drivers/pci/quirks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2990ad1e7c99..6d0dee40dbe5 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4230,11 +4230,24 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) * 0xa290-0xa29f PCI Express Root port #{0-16} * 0xa2e7-0xa2ee PCI Express Root port #{17-24} * + * Mobile chipsets are also affected, 7th & 8th Generation + * Specification update confirms ACS errata 22, status no fix: (7th Generation + * Intel Processor Family I/O for U/Y Platforms and 8th Generation Intel + * Processor Family I/O for U Quad Core Platforms Specification Update, + * August 2017, Revision 002, Document#: 334660-002)[6] + * Device IDs from I/O datasheet: (7th Generation Intel Processor Family I/O + * for U/Y Platforms and 8th Generation Intel ® Processor Family I/O for U + * Quad Core Platforms, Vol 1 of 2, August 2017, Document#: 334658-003)[7] + * + * 0x9d10-0x9d1b PCI Express Root port #{1-12} + * * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html * [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html * [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html + * [6] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-spec-update.html + * [7] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-datasheet-vol-1.html */ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) { @@ -4244,6 +4257,7 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) switch (dev->device) { case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ + case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ return true; } -- cgit v1.2.3 From f154a718e6cc0d834f5ac4dc4c3b174e65f3659e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 27 Apr 2018 13:06:30 -0500 Subject: PCI: Add ACS quirk for Intel 300 series Intel 300 series chipset still has the same ACS issue as the previous generations so extend the ACS quirk to cover it as well. Signed-off-by: Mika Westerberg Signed-off-by: Bjorn Helgaas CC: stable@vger.kernel.org --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 6d0dee40dbe5..785a29ba4f51 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4241,6 +4241,11 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) * * 0x9d10-0x9d1b PCI Express Root port #{1-12} * + * The 300 series chipset suffers from the same bug so include those root + * ports here as well. + * + * 0xa32c-0xa343 PCI Express Root port #{0-24} + * * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html @@ -4258,6 +4263,7 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ + case 0xa32c ... 0xa343: /* 300 series */ return true; } -- cgit v1.2.3 From cef74409ea79b0a37af6889e7abf7a2a9c47979b Mon Sep 17 00:00:00 2001 From: Gil Kupfer Date: Thu, 10 May 2018 17:56:02 -0500 Subject: PCI: Add "pci=noats" boot parameter Adds a "pci=noats" boot parameter. When supplied, all ATS related functions fail immediately and the IOMMU is configured to not use device-IOTLB. Any function that checks for ATS capabilities directly against the devices should also check this flag. Currently, such functions exist only in IOMMU drivers, and they are covered by this patch. The motivation behind this patch is the existence of malicious devices. Lots of research has been done about how to use the IOMMU as protection from such devices. When ATS is supported, any I/O device can access any physical address by faking device-IOTLB entries. Adding the ability to ignore these entries lets sysadmins enhance system security. Signed-off-by: Gil Kupfer Signed-off-by: Bjorn Helgaas Acked-by: Joerg Roedel --- Documentation/admin-guide/kernel-parameters.txt | 2 ++ drivers/iommu/amd_iommu.c | 11 ++++++++--- drivers/iommu/intel-iommu.c | 3 ++- drivers/pci/ats.c | 3 +++ drivers/pci/pci.c | 11 +++++++++++ include/linux/pci.h | 2 ++ 6 files changed, 28 insertions(+), 4 deletions(-) (limited to 'drivers/pci') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 11fc28ecdb6d..a19ccac3b4c7 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3147,6 +3147,8 @@ on: Turn realloc on realloc same as realloc=on noari do not use PCIe ARI. + noats [PCIE, Intel-IOMMU, AMD-IOMMU] + do not use PCIe ATS (and IOMMU device IOTLB). pcie_scan_all Scan all possible PCIe devices. Otherwise we only look for one device below a PCIe downstream port. diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2a99f0f14795..56da1c6121d3 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -355,6 +355,9 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev) }; int i, pos; + if (pci_ats_disabled()) + return false; + for (i = 0; i < 3; ++i) { pos = pci_find_ext_capability(pdev, caps[i]); if (pos == 0) @@ -3524,9 +3527,11 @@ int amd_iommu_device_info(struct pci_dev *pdev, memset(info, 0, sizeof(*info)); - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); - if (pos) - info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; + if (!pci_ats_disabled()) { + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); + if (pos) + info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; + } pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); if (pos) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 749d8f235346..772b404a6604 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2459,7 +2459,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, if (dev && dev_is_pci(dev)) { struct pci_dev *pdev = to_pci_dev(info->dev); - if (ecap_dev_iotlb_support(iommu->ecap) && + if (!pci_ats_disabled() && + ecap_dev_iotlb_support(iommu->ecap) && pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) && dmar_find_matched_atsr_unit(pdev)) info->ats_supported = 1; diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 89305b569d3d..4923a2a8e14b 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -20,6 +20,9 @@ void pci_ats_init(struct pci_dev *dev) { int pos; + if (pci_ats_disabled()) + return; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); if (!pos) return; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e597655a5643..789ce36be341 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -112,6 +112,14 @@ unsigned int pcibios_max_latency = 255; /* If set, the PCIe ARI capability will not be used. */ static bool pcie_ari_disabled; +/* If set, the PCIe ATS capability will not be used. */ +static bool pcie_ats_disabled; + +bool pci_ats_disabled(void) +{ + return pcie_ats_disabled; +} + /* Disable bridge_d3 for all PCIe ports */ static bool pci_bridge_d3_disable; /* Force bridge_d3 for all PCIe ports */ @@ -5793,6 +5801,9 @@ static int __init pci_setup(char *str) if (*str && (str = pcibios_setup(str)) && *str) { if (!strcmp(str, "nomsi")) { pci_no_msi(); + } else if (!strncmp(str, "noats", 5)) { + pr_info("PCIe: ATS is disabled\n"); + pcie_ats_disabled = true; } else if (!strcmp(str, "noaer")) { pci_no_aer(); } else if (!strncmp(str, "realloc=", 8)) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 911f9098a466..aa9c27e129d4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1479,6 +1479,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } static inline void pcie_ecrc_get_policy(char *str) { } #endif +bool pci_ats_disabled(void); + #ifdef CONFIG_PCI_ATS /* Address Translation Service */ void pci_ats_init(struct pci_dev *dev); -- cgit v1.2.3 From 8d85a7a4f2c935013a01964b7e81d5a105bd7a4c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 25 May 2018 08:18:34 -0500 Subject: PCI/IOV: Allow PF drivers to limit total_VFs to 0 Some SR-IOV PF drivers implement .sriov_configure(), which allows user-space to enable VFs by writing the desired number of VFs to the sysfs "sriov_numvfs" file (see sriov_numvfs_store()). The PCI core limits the number of VFs to the TotalVFs advertised by the device in its SR-IOV capability. The PF driver can limit the number of VFs to even fewer (it may have pre-allocated data structures or knowledge of device limitations) by calling pci_sriov_set_totalvfs(), but previously it could not limit the VFs to 0. Change pci_sriov_get_totalvfs() so it always respects the VF limit imposed by the PF driver, even if the limit is 0. This sequence: pci_sriov_set_totalvfs(dev, 0); x = pci_sriov_get_totalvfs(dev); previously set "x" to TotalVFs from the SR-IOV capability. Now it will set "x" to 0. Signed-off-by: Jakub Kicinski [bhelgaas: split to separate patch] Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 192b82898a38..d0d73dbbd5ca 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -469,6 +469,7 @@ found: iov->nres = nres; iov->ctrl = ctrl; iov->total_VFs = total; + iov->driver_max_VFs = total; pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device); iov->pgsz = pgsz; iov->self = dev; @@ -827,10 +828,7 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev) if (!dev->is_physfn) return 0; - if (dev->sriov->driver_max_VFs) - return dev->sriov->driver_max_VFs; - - return dev->sriov->total_VFs; + return dev->sriov->driver_max_VFs; } EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs); -- cgit v1.2.3