Commit 892384cd authored by Sven Peter's avatar Sven Peter Committed by Joerg Roedel
Browse files

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: default avatarAlexander Graf <graf@amazon.com>
Reviewed-by: default avatarAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarSven Peter <sven@svenpeter.dev>
Link: https://lore.kernel.org/r/20210803121651.61594-2-sven@svenpeter.dev


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 9eec3f9b
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -130,6 +130,9 @@
#define ARM_MALI_LPAE_MEMATTR_IMP_DEF	0x88ULL
#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL

#define APPLE_DART_PTE_PROT_NO_WRITE (1<<7)
#define APPLE_DART_PTE_PROT_NO_READ (1<<8)

/* IOPTE accessors */
#define iopte_deref(pte,d) __va(iopte_to_paddr(pte, d))

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

	if (data->iop.fmt == APPLE_DART) {
		pte = 0;
		if (!(prot & IOMMU_WRITE))
			pte |= APPLE_DART_PTE_PROT_NO_WRITE;
		if (!(prot & IOMMU_READ))
			pte |= APPLE_DART_PTE_PROT_NO_READ;
		return pte;
	}

	if (data->iop.fmt == ARM_64_LPAE_S1 ||
	    data->iop.fmt == ARM_32_LPAE_S1) {
		pte = ARM_LPAE_PTE_nG;
@@ -1102,6 +1114,52 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
	return NULL;
}

static struct io_pgtable *
apple_dart_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
{
	struct arm_lpae_io_pgtable *data;
	int i;

	if (cfg->oas > 36)
		return NULL;

	data = arm_lpae_alloc_pgtable(cfg);
	if (!data)
		return NULL;

	/*
	 * The table format itself always uses two levels, but the total VA
	 * space is mapped by four separate tables, making the MMIO registers
	 * an effective "level 1". For simplicity, though, we treat this
	 * equivalently to LPAE stage 2 concatenation at level 2, with the
	 * additional TTBRs each just pointing at consecutive pages.
	 */
	if (data->start_level < 1)
		goto out_free_data;
	if (data->start_level == 1 && data->pgd_bits > 2)
		goto out_free_data;
	if (data->start_level > 1)
		data->pgd_bits = 0;
	data->start_level = 2;
	cfg->apple_dart_cfg.n_ttbrs = 1 << data->pgd_bits;
	data->pgd_bits += data->bits_per_level;

	data->pgd = __arm_lpae_alloc_pages(ARM_LPAE_PGD_SIZE(data), GFP_KERNEL,
					   cfg);
	if (!data->pgd)
		goto out_free_data;

	for (i = 0; i < cfg->apple_dart_cfg.n_ttbrs; ++i)
		cfg->apple_dart_cfg.ttbr[i] =
			virt_to_phys(data->pgd + i * ARM_LPAE_GRANULE(data));

	return &data->iop;

out_free_data:
	kfree(data);
	return NULL;
}

struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
	.alloc	= arm_64_lpae_alloc_pgtable_s1,
	.free	= arm_lpae_free_pgtable,
@@ -1127,6 +1185,11 @@ struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
	.free	= arm_lpae_free_pgtable,
};

struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns = {
	.alloc	= apple_dart_alloc_pgtable,
	.free	= arm_lpae_free_pgtable,
};

#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST

static struct io_pgtable_cfg *cfg_cookie __initdata;
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
	[ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
	[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,
#endif
#ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
	[ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ enum io_pgtable_fmt {
	ARM_V7S,
	ARM_MALI_LPAE,
	AMD_IOMMU_V1,
	APPLE_DART,
	IO_PGTABLE_NUM_FMTS,
};

@@ -136,6 +137,11 @@ struct io_pgtable_cfg {
			u64	transtab;
			u64	memattr;
		} arm_mali_lpae_cfg;

		struct {
			u64 ttbr[4];
			u32 n_ttbrs;
		} apple_dart_cfg;
	};
};

@@ -254,5 +260,6 @@ extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns;
extern struct io_pgtable_init_fns io_pgtable_amd_iommu_v1_init_fns;
extern struct io_pgtable_init_fns io_pgtable_apple_dart_init_fns;

#endif /* __IO_PGTABLE_H */