diff mbox series

[v3,4/5] iommu/io-pgtable-dart: Add DART PTE support for t6000

Message ID 20220621071848.14834-5-j@jannau.net (mailing list archive)
State New, archived
Headers show
Series iommu: M1 Pro/Max DART support | expand

Commit Message

Janne Grunau June 21, 2022, 7:18 a.m. UTC
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.
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 in v3:
- apply change to io-pgtable-dart.c
- handle pte <> paddr conversion based on the pte format instead of
  the output address size

Changes in v2:
- add APPLE_DART2 PTE format

 drivers/iommu/io-pgtable-dart.c | 51 +++++++++++++++++++++++++++------
 drivers/iommu/io-pgtable.c      |  1 +
 include/linux/io-pgtable.h      |  1 +
 3 files changed, 45 insertions(+), 8 deletions(-)

Comments

Robin Murphy June 27, 2022, 3:13 p.m. UTC | #1
On 2022-06-21 08:18, Janne Grunau wrote:
> 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.
> 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 in v3:
> - apply change to io-pgtable-dart.c
> - handle pte <> paddr conversion based on the pte format instead of
>    the output address size
> 
> Changes in v2:
> - add APPLE_DART2 PTE format
> 
>   drivers/iommu/io-pgtable-dart.c | 51 +++++++++++++++++++++++++++------
>   drivers/iommu/io-pgtable.c      |  1 +
>   include/linux/io-pgtable.h      |  1 +
>   3 files changed, 45 insertions(+), 8 deletions(-)
> 
[...]
> @@ -536,7 +571,7 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
>   	if (!cfg->coherent_walk)
>   		return NULL;
>   
> -	if (cfg->oas > 36)
> +	if (cfg->oas != 36 && cfg->oas != 42)
>   		return NULL;

Wouldn't it make sense to tie this to the format? Maybe 36-bit OAS is 
still valid with v2, but presumably 42-bit with v1 definitely isn't.

Robin.
Hector Martin July 31, 2022, 7:04 a.m. UTC | #2
On 28/06/2022 00.13, Robin Murphy wrote:
> On 2022-06-21 08:18, Janne Grunau wrote:
>> 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.
>> 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 in v3:
>> - apply change to io-pgtable-dart.c
>> - handle pte <> paddr conversion based on the pte format instead of
>>    the output address size
>>
>> Changes in v2:
>> - add APPLE_DART2 PTE format
>>
>>   drivers/iommu/io-pgtable-dart.c | 51 +++++++++++++++++++++++++++------
>>   drivers/iommu/io-pgtable.c      |  1 +
>>   include/linux/io-pgtable.h      |  1 +
>>   3 files changed, 45 insertions(+), 8 deletions(-)
>>
> [...]
>> @@ -536,7 +571,7 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
>>   	if (!cfg->coherent_walk)
>>   		return NULL;
>>   
>> -	if (cfg->oas > 36)
>> +	if (cfg->oas != 36 && cfg->oas != 42)
>>   		return NULL;
> 
> Wouldn't it make sense to tie this to the format? Maybe 36-bit OAS is 
> still valid with v2, but presumably 42-bit with v1 definitely isn't.

FWIW, 36-bit OAS with v2 is valid (this is the case on M2/t8112).

- Hector
Janne Grunau Sept. 1, 2022, 12:22 a.m. UTC | #3
On 2022-06-27 16:13:20 +0100, Robin Murphy wrote:
> On 2022-06-21 08:18, Janne Grunau wrote:
> > 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.
> > 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 in v3:
> > - apply change to io-pgtable-dart.c
> > - handle pte <> paddr conversion based on the pte format instead of
> >    the output address size
> > 
> > Changes in v2:
> > - add APPLE_DART2 PTE format
> > 
> >   drivers/iommu/io-pgtable-dart.c | 51 +++++++++++++++++++++++++++------
> >   drivers/iommu/io-pgtable.c      |  1 +
> >   include/linux/io-pgtable.h      |  1 +
> >   3 files changed, 45 insertions(+), 8 deletions(-)
> > 
> [...]
> > @@ -536,7 +571,7 @@ apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
> >   	if (!cfg->coherent_walk)
> >   		return NULL;
> > -	if (cfg->oas > 36)
> > +	if (cfg->oas != 36 && cfg->oas != 42)
> >   		return NULL;
> 
> Wouldn't it make sense to tie this to the format? Maybe 36-bit OAS is still
> valid with v2, but presumably 42-bit with v1 definitely isn't.

The format is not know inside the alloc call unless I add per format 
alloc wrapper. I think we can trust the caller for now.

Janne
diff mbox series

Patch

diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
index fa8025c03bb5..9c3c2505f3dc 100644
--- a/drivers/iommu/io-pgtable-dart.c
+++ b/drivers/iommu/io-pgtable-dart.c
@@ -68,12 +68,19 @@ 
 #define APPLE_DART_PTE_SUBPAGE_END     GENMASK_ULL(51, 40)
 
 #define APPLE_DART1_PADDR_MASK	GENMASK_ULL(35, 12)
+#define APPLE_DART2_PADDR_MASK	GENMASK_ULL(37, 10)
+#define APPLE_DART2_PADDR_SHIFT	(4)
 
 /* Apple DART1 protection bits */
 #define APPLE_DART1_PTE_PROT_NO_READ	BIT(8)
 #define APPLE_DART1_PTE_PROT_NO_WRITE	BIT(7)
 #define APPLE_DART1_PTE_PROT_SP_DIS	BIT(1)
 
+/* Apple DART2 protection bits */
+#define APPLE_DART2_PTE_PROT_NO_READ	BIT(3)
+#define APPLE_DART2_PTE_PROT_NO_WRITE	BIT(2)
+#define APPLE_DART2_PTE_PROT_NO_CACHE	BIT(1)
+
 /* marks PTE as valid */
 #define APPLE_DART_PTE_VALID		BIT(0)
 
@@ -101,13 +108,31 @@  static inline bool iopte_leaf(dart_iopte pte, int lvl,
 static dart_iopte paddr_to_iopte(phys_addr_t paddr,
 				     struct dart_io_pgtable *data)
 {
-	return paddr & APPLE_DART1_PADDR_MASK;
+	dart_iopte pte;
+
+	if (data->iop.fmt == APPLE_DART)
+		return paddr & APPLE_DART1_PADDR_MASK;
+
+	/* format is APPLE_DART2 */
+	pte = paddr >> APPLE_DART2_PADDR_SHIFT;
+	pte &= APPLE_DART2_PADDR_MASK;
+
+	return pte;
 }
 
 static phys_addr_t iopte_to_paddr(dart_iopte pte,
 				  struct dart_io_pgtable *data)
 {
-	return pte & APPLE_DART1_PADDR_MASK;
+	u64 paddr;
+
+	if (data->iop.fmt == APPLE_DART)
+		return pte & APPLE_DART1_PADDR_MASK;
+
+	/* format is APPLE_DART2 */
+	paddr = pte & APPLE_DART2_PADDR_MASK;
+	paddr <<= APPLE_DART2_PADDR_SHIFT;
+
+	return paddr;
 }
 
 static void *__dart_alloc_pages(size_t size, gfp_t gfp,
@@ -139,7 +164,7 @@  static void __dart_init_pte(struct dart_io_pgtable *data,
 	size_t sz = DART_BLOCK_SIZE(lvl, data);
 	int i;
 
-	if (lvl == DART_MAX_LEVELS - 1)
+	if (lvl == DART_MAX_LEVELS - 1 && data->iop.fmt == APPLE_DART)
 		pte |= APPLE_DART1_PTE_PROT_SP_DIS;
 
 	pte |= APPLE_DART_PTE_VALID;
@@ -251,10 +276,20 @@  static dart_iopte dart_prot_to_pte(struct dart_io_pgtable *data,
 {
 	dart_iopte pte = 0;
 
-	if (!(prot & IOMMU_WRITE))
-		pte |= APPLE_DART1_PTE_PROT_NO_WRITE;
-	if (!(prot & IOMMU_READ))
-		pte |= APPLE_DART1_PTE_PROT_NO_READ;
+	if (data->iop.fmt == APPLE_DART) {
+		if (!(prot & IOMMU_WRITE))
+			pte |= APPLE_DART1_PTE_PROT_NO_WRITE;
+		if (!(prot & IOMMU_READ))
+			pte |= APPLE_DART1_PTE_PROT_NO_READ;
+	}
+	if (data->iop.fmt == APPLE_DART2) {
+		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;
 }
@@ -536,7 +571,7 @@  apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
 	if (!cfg->coherent_walk)
 		return NULL;
 
-	if (cfg->oas > 36)
+	if (cfg->oas != 36 && cfg->oas != 42)
 		return NULL;
 
 	data = dart_alloc_pgtable(cfg);
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
index e6edc6686859..a5d0f01afa7b 100644
--- a/drivers/iommu/io-pgtable.c
+++ b/drivers/iommu/io-pgtable.c
@@ -23,6 +23,7 @@  io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
 #endif
 #ifdef CONFIG_APPLE_DART
 	[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..76b98511cbc8 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,
 };