Skip to content

Commit 892384c

Browse files
svenpeter42joergroedel
authored andcommitted
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 <[email protected]> Reviewed-by: Alyssa Rosenzweig <[email protected]> Reviewed-by: Robin Murphy <[email protected]> Signed-off-by: Sven Peter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 9eec3f9 commit 892384c

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

drivers/iommu/io-pgtable-arm.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@
130130
#define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL
131131
#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL
132132

133+
#define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
134+
#define APPLE_DART_PTE_PROT_NO_READ (1<<8)
135+
133136
/* IOPTE accessors */
134137
#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))
135138

@@ -402,6 +405,15 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
402405
{
403406
arm_lpae_iopte pte;
404407

408+
if (data->iop.fmt == APPLE_DART) {
409+
pte = 0;
410+
if (!(prot & IOMMU_WRITE))
411+
pte |= APPLE_DART_PTE_PROT_NO_WRITE;
412+
if (!(prot & IOMMU_READ))
413+
pte |= APPLE_DART_PTE_PROT_NO_READ;
414+
return pte;
415+
}
416+
405417
if (data->iop.fmt == ARM_64_LPAE_S1 ||
406418
data->iop.fmt == ARM_32_LPAE_S1) {
407419
pte = ARM_LPAE_PTE_nG;
@@ -1102,6 +1114,52 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
11021114
return NULL;
11031115
}
11041116

1117+
static struct io_pgtable *
1118+
apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
1119+
{
1120+
struct arm_lpae_io_pgtable *data;
1121+
int i;
1122+
1123+
if (cfg->oas > 36)
1124+
return NULL;
1125+
1126+
data = arm_lpae_alloc_pgtable(cfg);
1127+
if (!data)
1128+
return NULL;
1129+
1130+
/*
1131+
* The table format itself always uses two levels, but the total VA
1132+
* space is mapped by four separate tables, making the MMIO registers
1133+
* an effective "level 1". For simplicity, though, we treat this
1134+
* equivalently to LPAE stage 2 concatenation at level 2, with the
1135+
* additional TTBRs each just pointing at consecutive pages.
1136+
*/
1137+
if (data->start_level < 1)
1138+
goto out_free_data;
1139+
if (data->start_level == 1 && data->pgd_bits > 2)
1140+
goto out_free_data;
1141+
if (data->start_level > 1)
1142+
data->pgd_bits = 0;
1143+
data->start_level = 2;
1144+
cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits;
1145+
data->pgd_bits += data->bits_per_level;
1146+
1147+
data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL,
1148+
cfg);
1149+
if (!data->pgd)
1150+
goto out_free_data;
1151+
1152+
for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i)
1153+
cfg->apple_dart_cfg.ttbr[i] =
1154+
virt_to_phys(data->pgd + i * ARM_LPAE_GRANULE(data));
1155+
1156+
return &data->iop;
1157+
1158+
out_free_data:
1159+
kfree(data);
1160+
return NULL;
1161+
}
1162+
11051163
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
11061164
.alloc = arm_64_lpae_alloc_pgtable_s1,
11071165
.free = arm_lpae_free_pgtable,
@@ -1127,6 +1185,11 @@ struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
11271185
.free = arm_lpae_free_pgtable,
11281186
};
11291187

1188+
struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = {
1189+
.alloc = apple_dart_alloc_pgtable,
1190+
.free = arm_lpae_free_pgtable,
1191+
};
1192+
11301193
#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST
11311194

11321195
static struct io_pgtable_cfg *cfg_cookie __initdata;

drivers/iommu/io-pgtable.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
2020
[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
2121
[ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
2222
[ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns,
23+
[APPLE_DART] = &io_pgtable_apple_dart_init_fns,
2324
#endif
2425
#ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
2526
[ARM_V7S] = &io_pgtable_arm_v7s_init_fns,

include/linux/io-pgtable.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum io_pgtable_fmt {
1616
ARM_V7S,
1717
ARM_MALI_LPAE,
1818
AMD_IOMMU_V1,
19+
APPLE_DART,
1920
IO_PGTABLE_NUM_FMTS,
2021
};
2122

@@ -136,6 +137,11 @@ struct io_pgtable_cfg {
136137
u64 transtab;
137138
u64 memattr;
138139
} arm_mali_lpae_cfg;
140+
141+
struct {
142+
u64 ttbr[4];
143+
u32 n_ttbrs;
144+
} apple_dart_cfg;
139145
};
140146
};
141147

@@ -254,5 +260,6 @@ extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
254260
extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;
255261
extern struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns;
256262
extern struct io_pgtable_init_fns io_pgtable_amd_iommu_v1_init_fns;
263+
extern struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns;
257264

258265
#endif /* __IO_PGTABLE_H */

0 commit comments

Comments
 (0)