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

iommu/io-pgtable: Add DART pagetable format

Apple's DART iommu uses a pagetable format that shares some
similarities with the ones already implemented by io-pgtable.c.
Add a new format variant to support the required differences
so that we don't have to duplicate the pagetable handling code.

Reviewed-by: Alexander Graf <graf@amazon.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Sven Peter <sven@svenpeter.dev>
Link: https://lore.kernel.org/r/20210803121651.61594-2-sven@svenpeter.dev
Signed-off-by: Joerg Roedel <jroedel@suse.de>

authored by

Sven Peter and committed by
Joerg Roedel
892384cd 9eec3f9b

+71
+63
drivers/iommu/io-pgtable-arm.c
··· 130 130 #define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL 131 131 #define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL 132 132 133 + #define APPLE_DART_PTE_PROT_NO_WRITE (1<<7) 134 + #define APPLE_DART_PTE_PROT_NO_READ (1<<8) 135 + 133 136 /* IOPTE accessors */ 134 137 #define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d)) 135 138 ··· 404 401 int prot) 405 402 { 406 403 arm_lpae_iopte pte; 404 + 405 + if (data->iop.fmt == APPLE_DART) { 406 + pte = 0; 407 + if (!(prot & IOMMU_WRITE)) 408 + pte |= APPLE_DART_PTE_PROT_NO_WRITE; 409 + if (!(prot & IOMMU_READ)) 410 + pte |= APPLE_DART_PTE_PROT_NO_READ; 411 + return pte; 412 + } 407 413 408 414 if (data->iop.fmt == ARM_64_LPAE_S1 || 409 415 data->iop.fmt == ARM_32_LPAE_S1) { ··· 1114 1102 return NULL; 1115 1103 } 1116 1104 1105 + static struct io_pgtable * 1106 + apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) 1107 + { 1108 + struct arm_lpae_io_pgtable *data; 1109 + int i; 1110 + 1111 + if (cfg->oas > 36) 1112 + return NULL; 1113 + 1114 + data = arm_lpae_alloc_pgtable(cfg); 1115 + if (!data) 1116 + return NULL; 1117 + 1118 + /* 1119 + * The table format itself always uses two levels, but the total VA 1120 + * space is mapped by four separate tables, making the MMIO registers 1121 + * an effective "level 1". For simplicity, though, we treat this 1122 + * equivalently to LPAE stage 2 concatenation at level 2, with the 1123 + * additional TTBRs each just pointing at consecutive pages. 1124 + */ 1125 + if (data->start_level < 1) 1126 + goto out_free_data; 1127 + if (data->start_level == 1 && data->pgd_bits > 2) 1128 + goto out_free_data; 1129 + if (data->start_level > 1) 1130 + data->pgd_bits = 0; 1131 + data->start_level = 2; 1132 + cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits; 1133 + data->pgd_bits += data->bits_per_level; 1134 + 1135 + data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL, 1136 + cfg); 1137 + if (!data->pgd) 1138 + goto out_free_data; 1139 + 1140 + for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i) 1141 + cfg->apple_dart_cfg.ttbr[i] = 1142 + virt_to_phys(data->pgd + i * ARM_LPAE_GRANULE(data)); 1143 + 1144 + return &data->iop; 1145 + 1146 + out_free_data: 1147 + kfree(data); 1148 + return NULL; 1149 + } 1150 + 1117 1151 struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { 1118 1152 .alloc = arm_64_lpae_alloc_pgtable_s1, 1119 1153 .free = arm_lpae_free_pgtable, ··· 1182 1124 1183 1125 struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = { 1184 1126 .alloc = arm_mali_lpae_alloc_pgtable, 1127 + .free = arm_lpae_free_pgtable, 1128 + }; 1129 + 1130 + struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = { 1131 + .alloc = apple_dart_alloc_pgtable, 1185 1132 .free = arm_lpae_free_pgtable, 1186 1133 }; 1187 1134
+1
drivers/iommu/io-pgtable.c
··· 20 20 [ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns, 21 21 [ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns, 22 22 [ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns, 23 + [APPLE_DART] = &io_pgtable_apple_dart_init_fns, 23 24 #endif 24 25 #ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S 25 26 [ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
+7
include/linux/io-pgtable.h
··· 16 16 ARM_V7S, 17 17 ARM_MALI_LPAE, 18 18 AMD_IOMMU_V1, 19 + APPLE_DART, 19 20 IO_PGTABLE_NUM_FMTS, 20 21 }; 21 22 ··· 137 136 u64 transtab; 138 137 u64 memattr; 139 138 } arm_mali_lpae_cfg; 139 + 140 + struct { 141 + u64 ttbr[4]; 142 + u32 n_ttbrs; 143 + } apple_dart_cfg; 140 144 }; 141 145 }; 142 146 ··· 260 254 extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns; 261 255 extern struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns; 262 256 extern struct io_pgtable_init_fns io_pgtable_amd_iommu_v1_init_fns; 257 + extern struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns; 263 258 264 259 #endif /* __IO_PGTABLE_H */