Skip to contentSkip to conversation

soc: ti: Add and use PVU on K3-AM65 for DMA isolation

PATCH Superseded Jan Kiszka 2 participants 14 messages Aug 28, 2024 – Sep 5, 2024

Subsystems (5)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

v3 cover soc: ti: Add and use PVU on K3-AM65 for DMA isolation

Changes in v3:
- fix ti,am654-pvu.yaml according to review comments
- address review comments on ti,am65-pci-host.yaml
- differentiate between different compatibles in ti,am65-pci-host.yaml
- move pvu nodes to k3-am65-main.dtsi
- reorder patch series, pulling bindings and generic DT bits to the front

Changes in v2:
- fix dt_bindings_check issues (patch 1)
- address first review comments (patch 2)
- extend ti,am65-pci-host bindings for PVU (new patch 3)

Only few of the K3 SoCs have an IOMMU and, thus, can isolate the system against DMA-based attacks of external PCI devices. The AM65 is without an IOMMU, but it comes with something close to it: the Peripheral Virtualization Unit (PVU).

The PVU was originally designed to establish static compartments via a hypervisor, isolate those DMA-wise against each other and the host and even allow remapping of guest-physical addresses. But it only provides a static translation region, not page-granular mappings. Thus, it cannot be handled transparently like an IOMMU.

Now, to use the PVU for the purpose of isolated PCI devices from the Linux host, this series takes a different approach. It defines a restricted-dma-pool for the PCI host, using swiotlb to map all DMA buffers from a static memory carve-out. And to enforce that the devices actually follow this, a special PVU soc driver is introduced. The driver permits access to the GIC ITS and otherwise waits for other drivers that detect devices with constrained DMA to register pools with the PVU.

For the AM65, the first (and possibly only) driver where this is introduced is the pci-keystone host controller. Finally, this series configures the IOT2050 devices (all have MiniPCIe or M.2 extension slots) to make use of this protection scheme.

Due to the cross-cutting nature of these changes, multiple subsystems are affected. However, I wanted to present the whole thing in one series to allow everyone to review with the complete picture in hands. If preferred, I can also split the series up, of course.

Jan

CC Bjorn Helgaas <[email protected]>
CC "Krzysztof Wilczyński" <[email protected]>
CC Lorenzo Pieralisi <[email protected]>

Jan Kiszka (7):
dt-bindings: soc: ti: Add AM65 peripheral virtualization unit
dt-bindings: PCI: ti,am65: Extend for use with PVU
arm64: dts: ti: k3-am65-main: Add PVU nodes
arm64: dts: ti: k3-am65-main: Add VMAP registers to PCI root complexes
soc: ti: Add IOMPU-like PVU driver
PCI: keystone: Add supported for PVU-based DMA isolation on AM654
arm64: dts: ti: iot2050: Enforce DMA isolation for devices behind PCI
RC

 .../bindings/pci/ti,am65-pci-host.yaml        |  52 +-
 .../bindings/soc/ti/ti,am654-pvu.yaml         |  51 ++
 .../boot/dts/ti/k3-am65-iot2050-common.dtsi   |  15 +
 arch/arm64/boot/dts/ti/k3-am65-main.dtsi      |  38 +-
 drivers/pci/controller/dwc/pci-keystone.c     | 101 ++++
 drivers/soc/ti/Kconfig                        |   4 +
 drivers/soc/ti/Makefile                       |   1 +
 drivers/soc/ti/ti-pvu.c                       | 487 ++++++++++++++++++
 include/linux/ti-pvu.h                        |  16 +
 9 files changed, 749 insertions(+), 16 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,am654-pvu.yaml
 create mode 100644 drivers/soc/ti/ti-pvu.c
 create mode 100644 include/linux/ti-pvu.h
Signature · 1 line
2.43.0
author
#1 lore raw

PATCH v3 1/7 dt-bindings: soc: ti: Add AM65 peripheral virtualization unit

From: Jan Kiszka <[email protected]>

The PVU allows to define a limited set of mappings for incoming DMA requests to the system memory. It is not a real IOMMU, thus hooked up under the TI SoC bindings.

---
 .../bindings/soc/ti/ti,am654-pvu.yaml         | 51 +++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,am654-pvu.yaml
Documentation/devicetree/bindings/soc/ti/ti,am654-pvu.yaml new file +51 -0
new file mode 100644
index 000000000000..e4a5fc47d674
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (c) Siemens AG, 2024
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/ti/ti,am654-pvu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI AM654 Peripheral Virtualization Unit
+
+maintainers:
+  - Jan Kiszka <[email protected]>
+
+properties:
+  compatible:
+    enum:
+      - ti,am654-pvu
+
+  reg:
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: cfg
+      - const: tlbif
+
+  interrupts:
+    items:
+      - description: fault interrupt
+
+  interrupt-names:
+    items:
+      - const: pvu
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-names
+
+additionalProperties: false
+
+examples:
+  - |
+    iommu@30f80000 {
+        compatible = "ti,am654-pvu";
+        reg = <0x30f80000 0x1000>,
+              <0x36000000 0x100000>;
+        reg-names = "cfg", "tlbif";
+        interrupts-extended = <&intr_main_navss 390>;
+        interrupt-names = "pvu";
+    };
Signature · 1 line
2.43.0
Reviewed-by on v3 1/7
#2 lore raw

Re: [PATCH v3 1/7] dt-bindings: soc: ti: Add AM65 peripheral virtualization unit

Quoted 8 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

The PVU allows to define a limited set of mappings for incoming DMA requests to the system memory. It is not a real IOMMU, thus hooked up under the TI SoC bindings.

---

Best regards,
Krzysztof

author
#3 lore raw

PATCH v3 2/7 dt-bindings: PCI: ti,am65: Extend for use with PVU

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

The PVU on the AM65 SoC is capable of restricting DMA from PCIe devices to specific regions of host memory. Add the optional property "memory-regions" to point to such regions of memory when PVU is used.

Since the PVU deals with system physical addresses, utilizing the PVU with PCIe devices also requires setting up the VMAP registers to map the Requester ID of the PCIe device to the CBA Virtual ID, which in turn is mapped to the system physical address. Hence, describe the VMAP registers which are optionally unless the PVU shall used for PCIe.

---
CC: Lorenzo Pieralisi <[email protected]>
CC: "Krzysztof Wilczyński" <[email protected]>
CC: Bjorn Helgaas <[email protected]>
CC: [email protected]

---
 .../bindings/pci/ti,am65-pci-host.yaml        | 52 ++++++++++++++-----
 1 file changed, 40 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +40 -12
index 0a9d10532cc8..d8182bad92de 100644
@@ -19,16 +19,6 @@ properties:
       - ti,am654-pcie-rc
       - ti,keystone-pcie
 
-  reg:
-    maxItems: 4
-
-  reg-names:
-    items:
-      - const: app
-      - const: dbics
-      - const: config
-      - const: atu
-
   interrupts:
     maxItems: 1
 
@@ -84,12 +74,48 @@ if:
       enum:
         - ti,am654-pcie-rc
 then:
+  properties:
+    reg:
+      minItems: 4
+      maxItems: 6
+
+    reg-names:
+      minItems: 4
+      items:
+        - const: app
+        - const: dbics
+        - const: config
+        - const: atu
+        - const: vmap_lp
+        - const: vmap_hp
+
+    memory-region:
+      minItems: 1
+      description: |
+        phandle to one or more restricted DMA pools to be used for all devices
+        behind this controller. The regions should be defined according to
+        reserved-memory/shared-dma-pool.yaml.
+      items:
+        maxItems: 1
+
   required:
     - dma-coherent
     - power-domains
     - msi-map
     - num-viewport
 
+else:
+  properties:
+    reg:
+      maxItems: 4
+
+    reg-names:
+      items:
+        - const: app
+        - const: dbics
+        - const: config
+        - const: atu
+
 unevaluatedProperties: false
 
 examples:
@@ -104,8 +130,10 @@ examples:
         reg =  <0x5500000 0x1000>,
                <0x5501000 0x1000>,
                <0x10000000 0x2000>,
-               <0x5506000 0x1000>;
-        reg-names = "app", "dbics", "config", "atu";
+               <0x5506000 0x1000>,
+               <0x2900000 0x1000>,
+               <0x2908000 0x1000>;
+        reg-names = "app", "dbics", "config", "atu", "vmap_lp", "vmap_hp";
         power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
         #address-cells = <3>;
         #size-cells = <2>;
Signature · 1 line
2.43.0
#4 lore raw

Re: [PATCH v3 2/7] dt-bindings: PCI: ti,am65: Extend for use with PVU

Quoted 30 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

The PVU on the AM65 SoC is capable of restricting DMA from PCIe devices to specific regions of host memory. Add the optional property "memory-regions" to point to such regions of memory when PVU is used.

Since the PVU deals with system physical addresses, utilizing the PVU with PCIe devices also requires setting up the VMAP registers to map the Requester ID of the PCIe device to the CBA Virtual ID, which in turn is mapped to the system physical address. Hence, describe the VMAP registers which are optionally unless the PVU shall used for PCIe.

---
CC: Lorenzo Pieralisi <[email protected]>
CC: "Krzysztof Wilczyński" <[email protected]>
CC: Bjorn Helgaas <[email protected]>
CC: [email protected]

---
 .../bindings/pci/ti,am65-pci-host.yaml        | 52 ++++++++++++++-----
 1 file changed, 40 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -0
index 0a9d10532cc8..d8182bad92de 100644
@@ -19,16 +19,6 @@ properties:
       - ti,am654-pcie-rc
       - ti,keystone-pcie
 

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml properties: · line 31

Quoted 10 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -10
-  reg:
-    maxItems: 4
-
-  reg-names:
-    items:
-      - const: app
-      - const: dbics
-      - const: config
-      - const: atu
-

Properties must be defined in top-level.

https://elixir.bootlin.com/linux/v6.8/source/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml

Quoted 11 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +4 -0
   interrupts:
     maxItems: 1
 
@@ -84,12 +74,48 @@ if:
       enum:
         - ti,am654-pcie-rc
 then:
+  properties:
+    reg:
+      minItems: 4
+      maxItems: 6

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml if: · line 90

Quoted 10 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +10 -0
+
+    reg-names:
+      minItems: 4
+      items:
+        - const: app
+        - const: dbics
+        - const: config
+        - const: atu
+        - const: vmap_lp
+        - const: vmap_hp

This as well goes to the top.

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml if: · line 93

Quoted 3 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +3 -0
+
+    memory-region:
+      minItems: 1

Missing maxItems and this must be defined in top-level.

Best regards,
Krzysztof

author
#5 lore raw

Re: [PATCH v3 2/7] dt-bindings: PCI: ti,am65: Extend for use with PVU

Quoted 44 lines · Krzysztof Kozlowski
Quoted 30 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

The PVU on the AM65 SoC is capable of restricting DMA from PCIe devices to specific regions of host memory. Add the optional property "memory-regions" to point to such regions of memory when PVU is used.

Since the PVU deals with system physical addresses, utilizing the PVU with PCIe devices also requires setting up the VMAP registers to map the Requester ID of the PCIe device to the CBA Virtual ID, which in turn is mapped to the system physical address. Hence, describe the VMAP registers which are optionally unless the PVU shall used for PCIe.

---
CC: Lorenzo Pieralisi <[email protected]>
CC: "Krzysztof Wilczyński" <[email protected]>
CC: Bjorn Helgaas <[email protected]>
CC: [email protected]

---
 .../bindings/pci/ti,am65-pci-host.yaml        | 52 ++++++++++++++-----
 1 file changed, 40 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -0
index 0a9d10532cc8..d8182bad92de 100644
@@ -19,16 +19,6 @@ properties:
       - ti,am654-pcie-rc
       - ti,keystone-pcie
 

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml properties: · line 31

Quoted 10 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -10
-  reg:
-    maxItems: 4
-
-  reg-names:
-    items:
-      - const: app
-      - const: dbics
-      - const: config
-      - const: atu
-

Properties must be defined in top-level.

Quoted 2 lines

https://elixir.bootlin.com/linux/v6.8/source/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml

Tried that already, moving the else: part to top-level, but dtschema (2024.5) checks fail then. Could you explain why?

Quoted 24 lines
Quoted 11 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +4 -0
   interrupts:
     maxItems: 1
 
@@ -84,12 +74,48 @@ if:
       enum:
         - ti,am654-pcie-rc
 then:
+  properties:
+    reg:
+      minItems: 4
+      maxItems: 6

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml if: · line 90

Quoted 10 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +10 -0
+
+    reg-names:
+      minItems: 4
+      items:
+        - const: app
+        - const: dbics
+        - const: config
+        - const: atu
+        - const: vmap_lp
+        - const: vmap_hp

This as well goes to the top.

Quoted 6 lines

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml if: · line 93

Quoted 3 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +3 -0
+
+    memory-region:
+      minItems: 1

Missing maxItems and this must be defined in top-level.

As explained (and documented), there is no maximum. And this does not apply to ti,keystone-pcie because only the AM65 supports the PVU.

Jan

Signature · 2 lines
Siemens AG, Technology
Linux Expert Center
#6 lore raw

Re: [PATCH v3 2/7] dt-bindings: PCI: ti,am65: Extend for use with PVU

Quoted 45 lines · Jan Kiszka
Quoted 44 lines · Krzysztof Kozlowski
Quoted 30 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

The PVU on the AM65 SoC is capable of restricting DMA from PCIe devices to specific regions of host memory. Add the optional property "memory-regions" to point to such regions of memory when PVU is used.

Since the PVU deals with system physical addresses, utilizing the PVU with PCIe devices also requires setting up the VMAP registers to map the Requester ID of the PCIe device to the CBA Virtual ID, which in turn is mapped to the system physical address. Hence, describe the VMAP registers which are optionally unless the PVU shall used for PCIe.

---
CC: Lorenzo Pieralisi <[email protected]>
CC: "Krzysztof Wilczyński" <[email protected]>
CC: Bjorn Helgaas <[email protected]>
CC: [email protected]

---
 .../bindings/pci/ti,am65-pci-host.yaml        | 52 ++++++++++++++-----
 1 file changed, 40 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -0
index 0a9d10532cc8..d8182bad92de 100644
@@ -19,16 +19,6 @@ properties:
       - ti,am654-pcie-rc
       - ti,keystone-pcie
 

Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml properties: · line 31

Quoted 10 lines
Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml +0 -10
-  reg:
-    maxItems: 4
-
-  reg-names:
-    items:
-      - const: app
-      - const: dbics
-      - const: config
-      - const: atu
-

Properties must be defined in top-level.

Quoted 5 lines
Quoted 2 lines

https://elixir.bootlin.com/linux/v6.8/source/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml

Tried that already, moving the else: part to top-level, but dtschema (2024.5) checks fail then. Could you explain why?

The example does not "move the else to top-level", so why would you do it? I gave you the code to copy&paste. I don't know how to write it simpler.

Best regards,
Krzysztof

author
#7 lore raw

PATCH v3 3/7 arm64: dts: ti: k3-am65-main: Add PVU nodes

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Add nodes for the two PVUs of the AM65. Keep them disabled, though, because the board has to additionally define DMA pools and the devices to be isolated.

---
 arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
arch/arm64/boot/dts/ti/k3-am65-main.dtsi +20 -0
index a8664b246795..08ce765828a4 100644
@@ -833,6 +833,26 @@ main_cpts_mux: refclk-mux {
 				assigned-clock-parents = <&k3_clks 118 5>;
 			};
 		};
+
+		ti_pvu0: iommu@30f80000 {
+			compatible = "ti,am654-pvu";
+			reg = <0 0x30f80000 0 0x1000>,
+			<0 0x36000000 0 0x100000>;
+			reg-names = "cfg", "tlbif";
+			interrupts-extended = <&intr_main_navss 390>;
+			interrupt-names = "pvu";
+			status = "disabled";
+		};
+
+		ti_pvu1: iommu@30f81000 {
+			compatible = "ti,am654-pvu";
+			reg = <0 0x30f81000 0 0x1000>,
+			<0 0x36100000 0 0x100000>;
+			reg-names = "cfg", "tlbif";
+			interrupts-extended = <&intr_main_navss 389>;
+			interrupt-names = "pvu";
+			status = "disabled";
+		};
 	};
 
 	main_gpio0: gpio@600000 {
Signature · 1 line
2.43.0
author
#8 lore raw

PATCH v3 4/7 arm64: dts: ti: k3-am65-main: Add VMAP registers to PCI root complexes

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Rewrap the long lines at this chance.

---
 arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/ti/k3-am65-main.dtsi +14 -4
index 08ce765828a4..46806f07a630 100644
@@ -887,8 +887,13 @@ main_gpio1: gpio@601000 {
 
 	pcie0_rc: pcie@5500000 {
 		compatible = "ti,am654-pcie-rc";
-		reg = <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x2000>, <0x0 0x5506000 0x0 0x1000>;
-		reg-names = "app", "dbics", "config", "atu";
+		reg = <0x0 0x5500000 0x0 0x1000>,
+		      <0x0 0x5501000 0x0 0x1000>,
+		      <0x0 0x10000000 0x0 0x2000>,
+		      <0x0 0x5506000 0x0 0x1000>,
+		      <0x0 0x2900000 0x0 0x1000>,
+		      <0x0 0x2908000 0x0 0x1000>;
+		reg-names = "app", "dbics", "config", "atu", "vmap_lp", "vmap_hp";
 		power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <3>;
 		#size-cells = <2>;
@@ -908,8 +913,13 @@ pcie0_rc: pcie@5500000 {
 
 	pcie1_rc: pcie@5600000 {
 		compatible = "ti,am654-pcie-rc";
-		reg = <0x0 0x5600000 0x0 0x1000>, <0x0 0x5601000 0x0 0x1000>, <0x0 0x18000000 0x0 0x2000>, <0x0 0x5606000 0x0 0x1000>;
-		reg-names = "app", "dbics", "config", "atu";
+		reg = <0x0 0x5600000 0x0 0x1000>,
+		      <0x0 0x5601000 0x0 0x1000>,
+		      <0x0 0x18000000 0x0 0x2000>,
+		      <0x0 0x5606000 0x0 0x1000>,
+		      <0x0 0x2910000 0x0 0x1000>,
+		      <0x0 0x2918000 0x0 0x1000>;
+		reg-names = "app", "dbics", "config", "atu", "vmap_lp", "vmap_hp";
 		power-domains = <&k3_pds 121 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <3>;
 		#size-cells = <2>;
Signature · 1 line
2.43.0
#9 lore raw

Re: [PATCH v3 4/7] arm64: dts: ti: k3-am65-main: Add VMAP registers to PCI root complexes

Quoted 9 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

Rewrap the long lines at this chance.

---
 arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

You still have DTS packed in the middle of driver changes, suggesting dependency.

Such ordering does not make sense, because entire DTS goes separate tree and branch. It only complicates stuff because if you have dependency, which you cannot have, it won't be that easily visible.

You already got the same comment.

Please fix your driver to remove dependency and ABI break, and then fix the patch order.

Best regards,
Krzysztof

author
#10 lore raw

Re: [PATCH v3 4/7] arm64: dts: ti: k3-am65-main: Add VMAP registers to PCI root complexes

Quoted 14 lines · Krzysztof Kozlowski
Quoted 9 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

Rewrap the long lines at this chance.

---
 arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

You still have DTS packed in the middle of driver changes, suggesting dependency.

Quoted 9 lines

Such ordering does not make sense, because entire DTS goes separate tree and branch. It only complicates stuff because if you have dependency, which you cannot have, it won't be that easily visible.

You already got the same comment.

Please fix your driver to remove dependency and ABI break, and then fix the patch order.

Could you be a bit more precise in your review, please? Should I also pull the last patch to front, or more all DT changes into a separate series?

The PCI driver will not fail unless you ask it for the new feature (CONFIG_TI_PVU) AND provide an incomplete DT (DMA pools, but no VMAP regs).

Thanks,
Jan

Signature · 2 lines
Siemens AG, Technology
Linux Expert Center
author
#11 lore raw

PATCH v3 5/7 soc: ti: Add IOMPU-like PVU driver

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

The TI Peripheral Virtualization Unit (PVU) permits to define a limited set of mappings for DMA requests on the system memory. Unlike with an IOMMU, there is no fallback to a memory-backed page table, only a fixed set of register-backed TLBs. Emulating an IOMMU behavior appears to be the more fragile the more fragmentation of pending requests occur.

Therefore, this driver does not expose the PVU as an IOMMU. It rather introduces a simple, static interface to devices that are under restricted-dma-pool constraints. They can register their pools with the PVUs, enabling only those pools to work for DMA. As also MSI is issued as DMA, the PVU already register the related translator region of the AM654 as valid DMA target.

This driver is the essential building block for limiting DMA from untrusted devices to clearly defined memory regions in the absence of a real IOMMU (SMMU).

---
 drivers/soc/ti/Kconfig  |   4 +
 drivers/soc/ti/Makefile |   1 +
 drivers/soc/ti/ti-pvu.c | 487 ++++++++++++++++++++++++++++++++++++++++
 include/linux/ti-pvu.h  |  16 ++
 4 files changed, 508 insertions(+)
 create mode 100644 drivers/soc/ti/ti-pvu.c
 create mode 100644 include/linux/ti-pvu.h
drivers/soc/ti/Kconfig +4 -0
index 1a93001c9e36..af7173ad84de 100644
@@ -82,6 +82,10 @@ config TI_PRUSS
 	  processors on various TI SoCs. It's safe to say N here if you're
 	  not interested in the PRU or if you are unsure.
 
+config TI_PVU
+	bool "TI Peripheral Virtualization Unit driver"
+	depends on ARCH_K3 && DMA_RESTRICTED_POOL
+
 endif # SOC_TI
 
 config TI_SCI_INTA_MSI_DOMAIN
drivers/soc/ti/Makefile +1 -0
index cb800a745e66..ecff3fd8c433 100644
@@ -12,3 +12,4 @@ obj-$(CONFIG_TI_K3_RINGACC)		+= k3-ringacc.o
 obj-$(CONFIG_TI_K3_SOCINFO)		+= k3-socinfo.o
 obj-$(CONFIG_TI_PRUSS)			+= pruss.o
 obj-$(CONFIG_POWER_AVS_OMAP)		+= smartreflex.o
+obj-$(CONFIG_TI_PVU)			+= ti-pvu.o
drivers/soc/ti/ti-pvu.c new file +487 -0

487 lines not on this page · raw message

include/linux/ti-pvu.h new file +16 -0
new file mode 100644
index 000000000000..acd4d9e0dc86
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI Peripheral Virtualization Unit driver for static DMA isolation
+ *
+ * Copyright (c) 2024, Siemens AG
+ */
+
+#ifndef _LINUX_TI_PVU_H
+#define _LINUX_TI_PVU_H
+
+#include <linux/ioport.h>
+
+int ti_pvu_create_region(unsigned int virt_id, const struct resource *region);
+int ti_pvu_remove_region(unsigned int virt_id, const struct resource *region);
+
+#endif /* _LINUX_TI_PVU_H */
Signature · 1 line
2.43.0
author
#12 lore raw

PATCH v3 6/7 PCI: keystone: Add supported for PVU-based DMA isolation on AM654

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

The AM654 lacks an IOMMU, thus does not support isolating DMA requests from untrusted PCI devices to selected memory regions this way. Use static PVU-based protection instead.

For this, we use the availability of restricted-dma-pool memory regions as trigger and register those as valid DMA targets with the PVU. In addition, we need to enable the mapping of requester IDs to VirtIDs in the PCI RC. We only use a single VirtID so far, catching all devices. This may be extended later on.

---
CC: Lorenzo Pieralisi <[email protected]>
CC: "Krzysztof Wilczyński" <[email protected]>
CC: Bjorn Helgaas <[email protected]>
CC: [email protected]

---
 drivers/pci/controller/dwc/pci-keystone.c | 101 ++++++++++++++++++++++
 1 file changed, 101 insertions(+)
drivers/pci/controller/dwc/pci-keystone.c +101 -0
index 2219b1a866fa..96b871656da4 100644
@@ -19,6 +19,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/msi.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_pci.h>
 #include <linux/phy/phy.h>
@@ -26,6 +27,7 @@
 #include <linux/regmap.h>
 #include <linux/resource.h>
 #include <linux/signal.h>
+#include <linux/ti-pvu.h>
 
 #include "../../pci.h"
 #include "pcie-designware.h"
@@ -111,6 +113,16 @@
 
 #define PCI_DEVICE_ID_TI_AM654X		0xb00c
 
+#define KS_PCI_VIRTID			0
+
+#define PCIE_VMAP_xP_CTRL		0x0
+#define PCIE_VMAP_xP_REQID		0x4
+#define PCIE_VMAP_xP_VIRTID		0x8
+
+#define PCIE_VMAP_xP_CTRL_EN		BIT(0)
+
+#define PCIE_VMAP_xP_VIRTID_VID_MASK	0xfff
+
 struct ks_pcie_of_data {
 	enum dw_pcie_device_mode mode;
 	const struct dw_pcie_host_ops *host_ops;
@@ -1125,6 +1137,89 @@ static const struct of_device_id ks_pcie_of_match[] = {
 	{ },
 };
 
+#ifdef CONFIG_TI_PVU
+static const char *ks_vmap_res[] = {"vmap_lp", "vmap_hp"};
+
+static int ks_init_restricted_dma(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct of_phandle_iterator it;
+	bool init_vmap = false;
+	struct resource phys;
+	struct resource *res;
+	void __iomem *base;
+	unsigned int n;
+	u32 val;
+	int err;
+
+	of_for_each_phandle(&it, err, dev->of_node, "memory-region",
+			    NULL, 0) {
+		if (!of_device_is_compatible(it.node, "restricted-dma-pool"))
+			continue;
+
+		err = of_address_to_resource(it.node, 0, &phys);
+		if (err < 0) {
+			dev_err(dev, "failed to parse memory region %pOF: %d\n",
+				it.node, err);
+			continue;
+		}
+
+		err = ti_pvu_create_region(KS_PCI_VIRTID, &phys);
+		if (err < 0)
+			return err;
+
+		init_vmap = true;
+	}
+
+	if (init_vmap) {
+		for (n = 0; n < ARRAY_SIZE(ks_vmap_res); n++) {
+			res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							   ks_vmap_res[n]);
+			base = devm_pci_remap_cfg_resource(dev, res);
+			if (IS_ERR(base))
+				return PTR_ERR(base);
+
+			writel(0, base + PCIE_VMAP_xP_REQID);
+
+			val = readl(base + PCIE_VMAP_xP_VIRTID);
+			val &= ~PCIE_VMAP_xP_VIRTID_VID_MASK;
+			val |= KS_PCI_VIRTID;
+			writel(val, base + PCIE_VMAP_xP_VIRTID);
+
+			val = readl(base + PCIE_VMAP_xP_CTRL);
+			val |= PCIE_VMAP_xP_CTRL_EN;
+			writel(val, base + PCIE_VMAP_xP_CTRL);
+		}
+	}
+
+	return 0;
+}
+
+static void ks_release_restricted_dma(struct platform_device *pdev)
+{
+	struct of_phandle_iterator it;
+	struct resource phys;
+	int err;
+
+	of_for_each_phandle(&it, err, pdev->dev.of_node, "memory-region",
+			    NULL, 0) {
+		if (of_device_is_compatible(it.node, "restricted-dma-pool") &&
+		    of_address_to_resource(it.node, 0, &phys) == 0)
+			ti_pvu_remove_region(KS_PCI_VIRTID, &phys);
+
+	}
+}
+#else
+static inline int ks_init_restricted_dma(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static inline void ks_release_restricted_dma(struct platform_device *pdev)
+{
+}
+#endif
+
 static int ks_pcie_probe(struct platform_device *pdev)
 {
 	const struct dw_pcie_host_ops *host_ops;
@@ -1273,6 +1368,10 @@ static int ks_pcie_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_get_sync;
 
+	ret = ks_init_restricted_dma(pdev);
+	if (ret < 0)
+		goto err_get_sync;
+
 	switch (mode) {
 	case DW_PCIE_RC_TYPE:
 		if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_HOST)) {
@@ -1354,6 +1453,8 @@ static void ks_pcie_remove(struct platform_device *pdev)
 	int num_lanes = ks_pcie->num_lanes;
 	struct device *dev = &pdev->dev;
 
+	ks_release_restricted_dma(pdev);
+
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
 	ks_pcie_disable_phy(ks_pcie);
Signature · 1 line
2.43.0
author
#13 lore raw

PATCH v3 7/7 arm64: dts: ti: iot2050: Enforce DMA isolation for devices behind PCI RC

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

Reserve a 64M memory region below the top of 1G RAM (smallest RAM size across the series, space left for firmware carve-outs) and ensure that all PCI devices do their DMA only inside that region. This is configured via a restricted-dma-pool and enforced with the help of the first PVU.

---
 .../arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi +15 -0
index e76828ccf21b..8af4bb132a10 100644
@@ -82,6 +82,11 @@ wdt_reset_memory_region: wdt-memory@a2200000 {
 			reg = <0x00 0xa2200000 0x00 0x1000>;
 			no-map;
 		};
+
+		pci_restricted_dma_region: restricted-dma@ba000000 {
+			compatible = "restricted-dma-pool";
+			reg = <0 0xba000000 0 0x4000000>;
+		};
 	};
 
 	leds {
@@ -571,6 +576,10 @@ seboot-backup@e80000 {
 	};
 };
 
+&pcie0_rc {
+	memory-region = <&pci_restricted_dma_region>;
+};
+
 &pcie1_rc {
 	status = "okay";
 	pinctrl-names = "default";
@@ -580,6 +589,8 @@ &pcie1_rc {
 	phys = <&serdes1 PHY_TYPE_PCIE 0>;
 	phy-names = "pcie-phy0";
 	reset-gpios = <&wkup_gpio0 27 GPIO_ACTIVE_HIGH>;
+
+	memory-region = <&pci_restricted_dma_region>;
 };
 
 &mailbox0_cluster0 {
@@ -640,3 +651,7 @@ &mcu_r5fss0 {
 	/* lock-step mode not supported on iot2050 boards */
 	ti,cluster-mode = <0>;
 };
+
+&ti_pvu0 {
+	status = "okay";
+};
Signature · 1 line
2.43.0