PCI: Treat "external-facing" devices themselves as internal
authorRajat Jain <rajatja@google.com>
Tue, 7 Jul 2020 22:46:03 +0000 (15:46 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 10 Jul 2020 19:03:13 +0000 (14:03 -0500)
"External-facing" devices are internal devices that expose PCIe hierarchies
such as Thunderbolt outside the platform [1].  Previously these internal
devices were marked as "untrusted" the same as devices downstream from
them.

Use the ACPI or DT information to identify external-facing devices, but
only mark the devices *downstream* from them as "untrusted" [2].  The
external-facing device itself is no longer marked as untrusted.

[1] https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports#identifying-externally-exposed-pcie-root-ports
[2] https://lore.kernel.org/linux-pci/20200610230906.GA1528594@bjorn-Precision-5520/
Link: https://lore.kernel.org/r/20200707224604.3737893-3-rajatja@google.com
Signed-off-by: Rajat Jain <rajatja@google.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/iommu/intel/iommu.c
drivers/pci/of.c
drivers/pci/pci-acpi.c
drivers/pci/probe.c
include/linux/pci.h

index 9129663..d23ce26 100644 (file)
@@ -4730,12 +4730,12 @@ const struct attribute_group *intel_iommu_groups[] = {
        NULL,
 };
 
-static inline bool has_untrusted_dev(void)
+static inline bool has_external_pci(void)
 {
        struct pci_dev *pdev = NULL;
 
        for_each_pci_dev(pdev)
-               if (pdev->untrusted)
+               if (pdev->external_facing)
                        return true;
 
        return false;
@@ -4743,7 +4743,7 @@ static inline bool has_untrusted_dev(void)
 
 static int __init platform_optin_force_iommu(void)
 {
-       if (!dmar_platform_optin() || no_platform_optin || !has_untrusted_dev())
+       if (!dmar_platform_optin() || no_platform_optin || !has_external_pci())
                return 0;
 
        if (no_iommu || dmar_disabled)
index 27839cd..22727fc 100644 (file)
@@ -42,7 +42,7 @@ void pci_set_bus_of_node(struct pci_bus *bus)
        } else {
                node = of_node_get(bus->self->dev.of_node);
                if (node && of_property_read_bool(node, "external-facing"))
-                       bus->self->untrusted = true;
+                       bus->self->external_facing = true;
        }
 
        bus->dev.of_node = node;
index 7224b1e..54520d3 100644 (file)
@@ -1213,7 +1213,7 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
        ACPI_FREE(obj);
 }
 
-static void pci_acpi_set_untrusted(struct pci_dev *dev)
+static void pci_acpi_set_external_facing(struct pci_dev *dev)
 {
        u8 val;
 
@@ -1224,11 +1224,10 @@ static void pci_acpi_set_untrusted(struct pci_dev *dev)
 
        /*
         * These root ports expose PCIe (including DMA) outside of the
-        * system so make sure we treat them and everything behind as
-        * untrusted.
+        * system.  Everything downstream from them is external.
         */
        if (val)
-               dev->untrusted = 1;
+               dev->external_facing = 1;
 }
 
 static void pci_acpi_setup(struct device *dev)
@@ -1240,7 +1239,7 @@ static void pci_acpi_setup(struct device *dev)
                return;
 
        pci_acpi_optimize_delay(pci_dev, adev->handle);
-       pci_acpi_set_untrusted(pci_dev);
+       pci_acpi_set_external_facing(pci_dev);
        pci_acpi_add_edr_notifier(pci_dev);
 
        pci_acpi_add_pm_notifier(adev, pci_dev);
index 6d87066..8c40c00 100644 (file)
@@ -1552,7 +1552,7 @@ static void set_pcie_untrusted(struct pci_dev *dev)
         * untrusted as well.
         */
        parent = pci_upstream_bridge(dev);
-       if (parent && parent->untrusted)
+       if (parent && (parent->untrusted || parent->external_facing))
                dev->untrusted = true;
 }
 
index a26be53..7a40cd5 100644 (file)
@@ -432,6 +432,12 @@ struct pci_dev {
         * mappings to make sure they cannot access arbitrary memory.
         */
        unsigned int    untrusted:1;
+       /*
+        * Info from the platform, e.g., ACPI or device tree, may mark a
+        * device as "external-facing".  An external-facing device is
+        * itself internal but devices downstream from it are external.
+        */
+       unsigned int    external_facing:1;
        unsigned int    broken_intx_masking:1;  /* INTx masking can't be used */
        unsigned int    io_window_1k:1;         /* Intel bridge 1K I/O windows */
        unsigned int    irq_managed:1;