Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu/io-pgtable-dart: Add DART PTE support for t6000

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>
Reviewed-by: Rob Herring <robh@kernel.org>
Acked-by: Hector Martin <marcan@marcan.st>
Link: https://lore.kernel.org/r/20220916094152.87137-5-j@jannau.net
Signed-off-by: Joerg Roedel <jroedel@suse.de>

authored by

Sven Peter and committed by
Joerg Roedel
dc09fe1c d8fe365a

+44 -7
+42 -7
drivers/iommu/io-pgtable-dart.c
··· 45 45 #define APPLE_DART_PTE_SUBPAGE_END GENMASK_ULL(51, 40) 46 46 47 47 #define APPLE_DART1_PADDR_MASK GENMASK_ULL(35, 12) 48 + #define APPLE_DART2_PADDR_MASK GENMASK_ULL(37, 10) 49 + #define APPLE_DART2_PADDR_SHIFT (4) 48 50 49 51 /* Apple DART1 protection bits */ 50 52 #define APPLE_DART1_PTE_PROT_NO_READ BIT(8) 51 53 #define APPLE_DART1_PTE_PROT_NO_WRITE BIT(7) 52 54 #define APPLE_DART1_PTE_PROT_SP_DIS BIT(1) 55 + 56 + /* Apple DART2 protection bits */ 57 + #define APPLE_DART2_PTE_PROT_NO_READ BIT(3) 58 + #define APPLE_DART2_PTE_PROT_NO_WRITE BIT(2) 59 + #define APPLE_DART2_PTE_PROT_NO_CACHE BIT(1) 53 60 54 61 /* marks PTE as valid */ 55 62 #define APPLE_DART_PTE_VALID BIT(0) ··· 79 72 static dart_iopte paddr_to_iopte(phys_addr_t paddr, 80 73 struct dart_io_pgtable *data) 81 74 { 82 - return paddr & APPLE_DART1_PADDR_MASK; 75 + dart_iopte pte; 76 + 77 + if (data->iop.fmt == APPLE_DART) 78 + return paddr & APPLE_DART1_PADDR_MASK; 79 + 80 + /* format is APPLE_DART2 */ 81 + pte = paddr >> APPLE_DART2_PADDR_SHIFT; 82 + pte &= APPLE_DART2_PADDR_MASK; 83 + 84 + return pte; 83 85 } 84 86 85 87 static phys_addr_t iopte_to_paddr(dart_iopte pte, 86 88 struct dart_io_pgtable *data) 87 89 { 88 - return pte & APPLE_DART1_PADDR_MASK; 90 + u64 paddr; 91 + 92 + if (data->iop.fmt == APPLE_DART) 93 + return pte & APPLE_DART1_PADDR_MASK; 94 + 95 + /* format is APPLE_DART2 */ 96 + paddr = pte & APPLE_DART2_PADDR_MASK; 97 + paddr <<= APPLE_DART2_PADDR_SHIFT; 98 + 99 + return paddr; 89 100 } 90 101 91 102 static void *__dart_alloc_pages(size_t size, gfp_t gfp, ··· 215 190 { 216 191 dart_iopte pte = 0; 217 192 218 - if (!(prot & IOMMU_WRITE)) 219 - pte |= APPLE_DART1_PTE_PROT_NO_WRITE; 220 - if (!(prot & IOMMU_READ)) 221 - pte |= APPLE_DART1_PTE_PROT_NO_READ; 193 + if (data->iop.fmt == APPLE_DART) { 194 + if (!(prot & IOMMU_WRITE)) 195 + pte |= APPLE_DART1_PTE_PROT_NO_WRITE; 196 + if (!(prot & IOMMU_READ)) 197 + pte |= APPLE_DART1_PTE_PROT_NO_READ; 198 + } 199 + if (data->iop.fmt == APPLE_DART2) { 200 + if (!(prot & IOMMU_WRITE)) 201 + pte |= APPLE_DART2_PTE_PROT_NO_WRITE; 202 + if (!(prot & IOMMU_READ)) 203 + pte |= APPLE_DART2_PTE_PROT_NO_READ; 204 + if (!(prot & IOMMU_CACHE)) 205 + pte |= APPLE_DART2_PTE_PROT_NO_CACHE; 206 + } 222 207 223 208 return pte; 224 209 } ··· 403 368 if (!cfg->coherent_walk) 404 369 return NULL; 405 370 406 - if (cfg->oas > DART1_MAX_ADDR_BITS) 371 + if (cfg->oas != 36 && cfg->oas != 42) 407 372 return NULL; 408 373 409 374 if (cfg->ias > cfg->oas)
+1
drivers/iommu/io-pgtable.c
··· 23 23 #endif 24 24 #ifdef CONFIG_IOMMU_IO_PGTABLE_DART 25 25 [APPLE_DART] = &io_pgtable_apple_dart_init_fns, 26 + [APPLE_DART2] = &io_pgtable_apple_dart_init_fns, 26 27 #endif 27 28 #ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S 28 29 [ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
+1
include/linux/io-pgtable.h
··· 17 17 ARM_MALI_LPAE, 18 18 AMD_IOMMU_V1, 19 19 APPLE_DART, 20 + APPLE_DART2, 20 21 IO_PGTABLE_NUM_FMTS, 21 22 }; 22 23