linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] iommu: M1 Pro/Max DART support
@ 2022-05-03  6:22 Janne Grunau
  2022-05-03  6:22 ` [PATCH v2 1/4] dt-bindings: iommu: dart: add t6000 compatible Janne Grunau
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Janne Grunau @ 2022-05-03  6:22 UTC (permalink / raw)
  To: iommu
  Cc: Sven Peter, Alyssa Rosenzweig, Hector Martin, Mark Kettenis,
	Joerg Roedel, Will Deacon, Rob Herring, Robin Murphy, devicetree,
	linux-kernel, linux-arm-kernel

Hej,

I've taken over this series to add support for DART on M1 Pro/Max from
Sven.

Since v1 we have discovered further differences in the PTE format. It
has four differences which makes it incompatible with the one in the
M1:

  - the physical addresses are shifted left by 4 bits and and have 2 more
    bits inside the PTE entries
  - the read/write protection flags are at a different position
  - the subpage protection feature is now mandatory. For Linux we can
    just configure it to always allow access to the entire page.
  - BIT(1) tags "uncached" mappings (used for the display controller)

The last difference is the most troublesome since it makes the PTE format
incomaptible with iopte_type(). Handling this inside io-pgtable-arm.c
seems manageable since DART supports just a single block size. It opens
the question at which point we decide that DART uses its own
io_pgtable_ops.

There is second type of DART (t8110) present on M1 Pro/Max SoCs which
uses the same PTE format as t6000.

Janne

Sven Peter (4):
  dt-bindings: iommu: dart: add t6000 compatible
  iommu/io-pgtable: Add DART subpage protection support
  iommu/io-pgtable: Add DART PTE support for t6000
  iommu: dart: Support t6000 variant

 .../devicetree/bindings/iommu/apple,dart.yaml |  4 +-
 drivers/iommu/apple-dart.c                    | 24 +++++-
 drivers/iommu/io-pgtable-arm.c                | 76 ++++++++++++++++++-
 drivers/iommu/io-pgtable.c                    |  1 +
 include/linux/io-pgtable.h                    |  3 +
 5 files changed, 101 insertions(+), 7 deletions(-)


base-commit: 3123109284176b1532874591f7c81f3837bbdc17
-- 
2.35.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/4] dt-bindings: iommu: dart: add t6000 compatible
  2022-05-03  6:22 [PATCH v2 0/4] iommu: M1 Pro/Max DART support Janne Grunau
@ 2022-05-03  6:22 ` Janne Grunau
  2022-05-03  6:22 ` [PATCH v2 2/4] iommu/io-pgtable: Add DART subpage protection support Janne Grunau
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Janne Grunau @ 2022-05-03  6:22 UTC (permalink / raw)
  To: iommu
  Cc: Sven Peter, Alyssa Rosenzweig, Hector Martin, Mark Kettenis,
	Joerg Roedel, Will Deacon, Rob Herring, Robin Murphy, devicetree,
	linux-kernel, linux-arm-kernel, Rob Herring

From: Sven Peter <sven@svenpeter.dev>

The M1 Max/Pro SoCs come with a new DART variant that is incompatible with
the previous one. Add a new compatible for those.

Signed-off-by: Sven Peter <sven@svenpeter.dev>
Acked-by: Rob Herring <robh@kernel.org>

---
v2 changes:
 - added Rob's Acked-by:
---
 Documentation/devicetree/bindings/iommu/apple,dart.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/apple,dart.yaml b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
index 82ad669feef7..06af2bacbe97 100644
--- a/Documentation/devicetree/bindings/iommu/apple,dart.yaml
+++ b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
@@ -22,7 +22,9 @@ description: |+
 
 properties:
   compatible:
-    const: apple,t8103-dart
+    enum:
+      - apple,t8103-dart
+      - apple,t6000-dart
 
   reg:
     maxItems: 1
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/4] iommu/io-pgtable: Add DART subpage protection support
  2022-05-03  6:22 [PATCH v2 0/4] iommu: M1 Pro/Max DART support Janne Grunau
  2022-05-03  6:22 ` [PATCH v2 1/4] dt-bindings: iommu: dart: add t6000 compatible Janne Grunau
@ 2022-05-03  6:22 ` Janne Grunau
  2022-05-03  6:23 ` [PATCH v2 3/4] iommu/io-pgtable: Add DART PTE support for t6000 Janne Grunau
  2022-05-03  6:23 ` [PATCH v2 4/4] iommu: dart: Support t6000 variant Janne Grunau
  3 siblings, 0 replies; 5+ messages in thread
From: Janne Grunau @ 2022-05-03  6:22 UTC (permalink / raw)
  To: iommu
  Cc: Sven Peter, Alyssa Rosenzweig, Hector Martin, Mark Kettenis,
	Joerg Roedel, Will Deacon, Rob Herring, Robin Murphy, devicetree,
	linux-kernel, linux-arm-kernel

From: Sven Peter <sven@svenpeter.dev>

DART allows to only expose a subpage to the device. While this is an
optional feature on the M1 DARTs the new ones present on the Pro/Max
models require this field in every PTE.

Signed-off-by: Sven Peter <sven@svenpeter.dev>
---
 drivers/iommu/io-pgtable-arm.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 94ff319ae8ac..71570bbc9096 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -10,6 +10,7 @@
 #define pr_fmt(fmt)	"arm-lpae io-pgtable: " fmt
 
 #include <linux/atomic.h>
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/io-pgtable.h>
 #include <linux/kernel.h>
@@ -133,6 +134,9 @@
 #define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
 #define APPLE_DART_PTE_PROT_NO_READ (1<<8)
 
+#define APPLE_DART_PTE_SUBPAGE_START	GENMASK_ULL(63, 52)
+#define APPLE_DART_PTE_SUBPAGE_END	GENMASK_ULL(51, 40)
+
 /* IOPTE accessors */
 #define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
 
@@ -273,6 +277,12 @@ static void __arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
 	else
 		pte |= ARM_LPAE_PTE_TYPE_BLOCK;
 
+	if (data->iop.fmt == APPLE_DART) {
+		/* subpage protection: always allow access to the entire page */
+		pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_START, 0);
+		pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_END, 0xfff);
+	}
+
 	for (i = 0; i < num_entries; i++)
 		ptep[i] = pte | paddr_to_iopte(paddr + i * sz, data);
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/4] iommu/io-pgtable: Add DART PTE support for t6000
  2022-05-03  6:22 [PATCH v2 0/4] iommu: M1 Pro/Max DART support Janne Grunau
  2022-05-03  6:22 ` [PATCH v2 1/4] dt-bindings: iommu: dart: add t6000 compatible Janne Grunau
  2022-05-03  6:22 ` [PATCH v2 2/4] iommu/io-pgtable: Add DART subpage protection support Janne Grunau
@ 2022-05-03  6:23 ` Janne Grunau
  2022-05-03  6:23 ` [PATCH v2 4/4] iommu: dart: Support t6000 variant Janne Grunau
  3 siblings, 0 replies; 5+ messages in thread
From: Janne Grunau @ 2022-05-03  6:23 UTC (permalink / raw)
  To: iommu
  Cc: Sven Peter, Alyssa Rosenzweig, Hector Martin, Mark Kettenis,
	Joerg Roedel, Will Deacon, Rob Herring, Robin Murphy, devicetree,
	linux-kernel, linux-arm-kernel

From: Sven Peter <sven@svenpeter.dev>

The DARTs present in the M1 Pro/Max/Ultra SoC use a diffent PTE format.
They support a 42bit physical address space by shifting the paddr and
extending its mask inside the PTE.
PTE flags are incompatible with iopte_type() since BIT(1) in the PTE
tags "uncached" mappings.
They also come with mandatory sub-page protection now which we just
configure to always allow access to the entire page. This feature is
already present but optional on the previous DARTs which allows to
unconditionally configure it.

Signed-off-by: Sven Peter <sven@svenpeter.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>

---
Changes since v1:
 - add APPLE_DART2 PTE format
---
 drivers/iommu/io-pgtable-arm.c | 68 ++++++++++++++++++++++++++++++++--
 drivers/iommu/io-pgtable.c     |  1 +
 include/linux/io-pgtable.h     |  3 ++
 3 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 71570bbc9096..f9121251fb57 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -134,9 +134,20 @@
 #define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
 #define APPLE_DART_PTE_PROT_NO_READ (1<<8)
 
+#define APPLE_DART_PTE_VALID BIT(0) // identical to ARM_LPAE_PTE_TYPE_BLOCK
+
+#define APPLE_DART2_PTE_PROT_NO_CACHE BIT(1)
+#define APPLE_DART2_PTE_PROT_NO_WRITE BIT(2)
+#define APPLE_DART2_PTE_PROT_NO_READ BIT(3)
+
 #define APPLE_DART_PTE_SUBPAGE_START	GENMASK_ULL(63, 52)
 #define APPLE_DART_PTE_SUBPAGE_END	GENMASK_ULL(51, 40)
 
+#define APPLE_DART_PADDR_MASK_PS_36BIT	GENMASK_ULL(35, 12)
+#define APPLE_DART_PADDR_SHIFT_PS_36BIT	(0)
+#define APPLE_DART_PADDR_MASK_PS_42BIT	GENMASK_ULL(37, 10)
+#define APPLE_DART_PADDR_SHIFT_PS_42BIT	(4)
+
 /* IOPTE accessors */
 #define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
 
@@ -160,6 +171,10 @@ typedef u64 arm_lpae_iopte;
 static inline bool iopte_leaf(arm_lpae_iopte pte, int lvl,
 			      enum io_pgtable_fmt fmt)
 {
+	if (fmt == APPLE_DART2)
+		return lvl == (ARM_LPAE_MAX_LEVELS - 1) &&
+			FIELD_GET(APPLE_DART_PTE_VALID, pte);
+
 	if (lvl == (ARM_LPAE_MAX_LEVELS - 1) && fmt != ARM_MALI_LPAE)
 		return iopte_type(pte) == ARM_LPAE_PTE_TYPE_PAGE;
 
@@ -171,6 +186,13 @@ static arm_lpae_iopte paddr_to_iopte(phys_addr_t paddr,
 {
 	arm_lpae_iopte pte = paddr;
 
+	if (data->iop.fmt == APPLE_DART || data->iop.fmt == APPLE_DART2) {
+		pte = paddr >> data->iop.cfg.apple_dart_cfg.paddr_shift;
+		pte &= data->iop.cfg.apple_dart_cfg.paddr_mask;
+
+		return pte;
+	}
+
 	/* Of the bits which overlap, either 51:48 or 15:12 are always RES0 */
 	return (pte | (pte >> (48 - 12))) & ARM_LPAE_PTE_ADDR_MASK;
 }
@@ -180,6 +202,12 @@ static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
 {
 	u64 paddr = pte & ARM_LPAE_PTE_ADDR_MASK;
 
+	if (data->iop.fmt == APPLE_DART || data->iop.fmt == APPLE_DART2) {
+		paddr = pte & data->iop.cfg.apple_dart_cfg.paddr_mask;
+		paddr <<= data->iop.cfg.apple_dart_cfg.paddr_shift;
+		return paddr;
+	}
+
 	if (ARM_LPAE_GRANULE(data) < SZ_64K)
 		return paddr;
 
@@ -272,12 +300,13 @@ static void __arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
 	size_t sz = ARM_LPAE_BLOCK_SIZE(lvl, data);
 	int i;
 
-	if (data->iop.fmt != ARM_MALI_LPAE && lvl == ARM_LPAE_MAX_LEVELS - 1)
+	if ((data->iop.fmt != ARM_MALI_LPAE && data->iop.fmt != APPLE_DART2) &&
+		lvl == ARM_LPAE_MAX_LEVELS - 1)
 		pte |= ARM_LPAE_PTE_TYPE_PAGE;
 	else
 		pte |= ARM_LPAE_PTE_TYPE_BLOCK;
 
-	if (data->iop.fmt == APPLE_DART) {
+	if (data->iop.fmt == APPLE_DART || data->iop.fmt == APPLE_DART2) {
 		/* subpage protection: always allow access to the entire page */
 		pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_START, 0);
 		pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_END, 0xfff);
@@ -330,7 +359,18 @@ static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table,
 	arm_lpae_iopte old, new;
 	struct io_pgtable_cfg *cfg = &data->iop.cfg;
 
-	new = paddr_to_iopte(__pa(table), data) | ARM_LPAE_PTE_TYPE_TABLE;
+	new = paddr_to_iopte(__pa(table), data);
+	/*
+	 * The APPLE_DART2 PTE format is incompatible with ARM_LPAE_PTE_TYPE_*
+	 * since BIT(1) is used to tag "uncached" mappings.
+	 * This is the only place where ARM_LPAE_PTE_TYPE_TABLE has to be
+	 * taken into account since APPLE_DART2 supports only a single block
+	 * size.
+	 */
+	if (data->iop.fmt == APPLE_DART2)
+		new |= APPLE_DART_PTE_VALID;
+	else
+		new |= ARM_LPAE_PTE_TYPE_TABLE;
 	if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS)
 		new |= ARM_LPAE_PTE_NSTABLE;
 
@@ -424,6 +464,16 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
 			pte |= APPLE_DART_PTE_PROT_NO_READ;
 		return pte;
 	}
+	if (data->iop.fmt == APPLE_DART2) {
+		pte = 0;
+		if (!(prot & IOMMU_WRITE))
+			pte |= APPLE_DART2_PTE_PROT_NO_WRITE;
+		if (!(prot & IOMMU_READ))
+			pte |= APPLE_DART2_PTE_PROT_NO_READ;
+		if (!(prot & IOMMU_CACHE))
+			pte |= APPLE_DART2_PTE_PROT_NO_CACHE;
+		return pte;
+	}
 
 	if (data->iop.fmt == ARM_64_LPAE_S1 ||
 	    data->iop.fmt == ARM_32_LPAE_S1) {
@@ -1123,8 +1173,18 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
 	struct arm_lpae_io_pgtable *data;
 	int i;
 
-	if (cfg->oas > 36)
+	switch (cfg->oas) {
+	case 36:
+		cfg->apple_dart_cfg.paddr_shift = APPLE_DART_PADDR_SHIFT_PS_36BIT;
+		cfg->apple_dart_cfg.paddr_mask = APPLE_DART_PADDR_MASK_PS_36BIT;
+		break;
+	case 42:
+		cfg->apple_dart_cfg.paddr_shift = APPLE_DART_PADDR_SHIFT_PS_42BIT;
+		cfg->apple_dart_cfg.paddr_mask = APPLE_DART_PADDR_MASK_PS_42BIT;
+		break;
+	default:
 		return NULL;
+	}
 
 	data = arm_lpae_alloc_pgtable(cfg);
 	if (!data)
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index f4bfcef98297..a217d2e85520 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -21,6 +21,7 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
 	[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
 	[ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns,
 	[APPLE_DART] = &io_pgtable_apple_dart_init_fns,
+	[APPLE_DART2] = &io_pgtable_apple_dart_init_fns,
 #endif
 #ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
 	[ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 86af6f0a00a2..36f251dc6f6b 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -17,6 +17,7 @@ enum io_pgtable_fmt {
 	ARM_MALI_LPAE,
 	AMD_IOMMU_V1,
 	APPLE_DART,
+	APPLE_DART2,
 	IO_PGTABLE_NUM_FMTS,
 };
 
@@ -136,6 +137,8 @@ struct io_pgtable_cfg {
 		struct {
 			u64 ttbr[4];
 			u32 n_ttbrs;
+			u32 paddr_shift;
+			u64 paddr_mask;
 		} apple_dart_cfg;
 	};
 };
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 4/4] iommu: dart: Support t6000 variant
  2022-05-03  6:22 [PATCH v2 0/4] iommu: M1 Pro/Max DART support Janne Grunau
                   ` (2 preceding siblings ...)
  2022-05-03  6:23 ` [PATCH v2 3/4] iommu/io-pgtable: Add DART PTE support for t6000 Janne Grunau
@ 2022-05-03  6:23 ` Janne Grunau
  3 siblings, 0 replies; 5+ messages in thread
From: Janne Grunau @ 2022-05-03  6:23 UTC (permalink / raw)
  To: iommu
  Cc: Sven Peter, Alyssa Rosenzweig, Hector Martin, Mark Kettenis,
	Joerg Roedel, Will Deacon, Rob Herring, Robin Murphy, devicetree,
	linux-kernel, linux-arm-kernel

From: Sven Peter <sven@svenpeter.dev>

The M1 Pro/Max/Ultra SoCs come with a new variant of DART which
supports a larger physical address space with a different PTE format.
Pass through the correct paddr address space size and the PTE format
to the io-pgtable code which will take care of the rest.

Signed-off-by: Sven Peter <sven@svenpeter.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>

---
Changes since v1:
 - use APPLE_DART PTE format for dart-t6000
---
 drivers/iommu/apple-dart.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index decafb07ad08..fe0dedd67fd8 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -81,10 +81,16 @@
 #define DART_TTBR_VALID BIT(31)
 #define DART_TTBR_SHIFT 12
 
+struct apple_dart_hw {
+	u32 oas;
+	enum io_pgtable_fmt fmt;
+};
+
 /*
  * Private structure associated with each DART device.
  *
  * @dev: device struct
+ * @hw: SoC-specific hardware data
  * @regs: mapped MMIO region
  * @irq: interrupt number, can be shared with other DARTs
  * @clks: clocks associated with this DART
@@ -98,6 +104,7 @@
  */
 struct apple_dart {
 	struct device *dev;
+	const struct apple_dart_hw *hw;
 
 	void __iomem *regs;
 
@@ -421,13 +428,13 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
 	pgtbl_cfg = (struct io_pgtable_cfg){
 		.pgsize_bitmap = dart->pgsize,
 		.ias = 32,
-		.oas = 36,
+		.oas = dart->hw->oas,
 		.coherent_walk = 1,
 		.iommu_dev = dart->dev,
 	};
 
 	dart_domain->pgtbl_ops =
-		alloc_io_pgtable_ops(APPLE_DART, &pgtbl_cfg, domain);
+		alloc_io_pgtable_ops(dart->hw->fmt, &pgtbl_cfg, domain);
 	if (!dart_domain->pgtbl_ops) {
 		ret = -ENOMEM;
 		goto done;
@@ -857,6 +864,7 @@ static int apple_dart_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dart->dev = dev;
+	dart->hw = of_device_get_match_data(dev);
 	spin_lock_init(&dart->lock);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -946,8 +954,18 @@ static int apple_dart_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct apple_dart_hw apple_dart_hw_t8103 = {
+	.oas = 36,
+	.fmt = APPLE_DART,
+};
+static const struct apple_dart_hw apple_dart_hw_t6000 = {
+	.oas = 42,
+	.fmt = APPLE_DART2,
+};
+
 static const struct of_device_id apple_dart_of_match[] = {
-	{ .compatible = "apple,t8103-dart", .data = NULL },
+	{ .compatible = "apple,t8103-dart", .data = &apple_dart_hw_t8103 },
+	{ .compatible = "apple,t6000-dart", .data = &apple_dart_hw_t6000 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, apple_dart_of_match);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-05-03  6:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-03  6:22 [PATCH v2 0/4] iommu: M1 Pro/Max DART support Janne Grunau
2022-05-03  6:22 ` [PATCH v2 1/4] dt-bindings: iommu: dart: add t6000 compatible Janne Grunau
2022-05-03  6:22 ` [PATCH v2 2/4] iommu/io-pgtable: Add DART subpage protection support Janne Grunau
2022-05-03  6:23 ` [PATCH v2 3/4] iommu/io-pgtable: Add DART PTE support for t6000 Janne Grunau
2022-05-03  6:23 ` [PATCH v2 4/4] iommu: dart: Support t6000 variant Janne Grunau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).