drivers/iommu/io-pgtable-dart.c

Source file repositories/reference/linux-study-clean/drivers/iommu/io-pgtable-dart.c

File Facts

System
Linux kernel
Corpus path
drivers/iommu/io-pgtable-dart.c
Extension
.c
Size
11417 bytes
Lines
484
Domain
Driver Families
Bucket
drivers/iommu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dart_io_pgtable {
	struct io_pgtable	iop;

	int			levels;
	int			tbl_bits;
	int			bits_per_level;

	void			*pgd[DART_MAX_TABLES];
};

typedef u64 dart_iopte;


static dart_iopte paddr_to_iopte(phys_addr_t paddr,
				     struct dart_io_pgtable *data)
{
	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)
{
	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 int dart_init_pte(struct dart_io_pgtable *data,
			     unsigned long iova, phys_addr_t paddr,
			     dart_iopte prot, int num_entries,
			     dart_iopte *ptep)
{
	int i;
	dart_iopte pte = prot;
	size_t sz = data->iop.cfg.pgsize_bitmap;

	for (i = 0; i < num_entries; i++)
		if (ptep[i] & APPLE_DART_PTE_VALID) {
			/* We require an unmap first */
			WARN_ON(ptep[i] & APPLE_DART_PTE_VALID);
			return -EEXIST;
		}

	/* subpage protection: always allow access to the entire page */
	pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_START, 0);
	pte |= FIELD_PREP(APPLE_DART_PTE_SUBPAGE_END, 0xfff);

	pte |= APPLE_DART_PTE_VALID;

	for (i = 0; i < num_entries; i++)
		ptep[i] = pte | paddr_to_iopte(paddr + i * sz, data);

	return 0;
}

static dart_iopte dart_install_table(dart_iopte *table,
					     dart_iopte *ptep,
					     dart_iopte curr,
					     struct dart_io_pgtable *data)
{
	dart_iopte old, new;

	new = paddr_to_iopte(__pa(table), data) | APPLE_DART_PTE_VALID;

	/*
	 * Ensure the table itself is visible before its PTE can be.
	 * Whilst we could get away with cmpxchg64_release below, this
	 * doesn't have any ordering semantics when !CONFIG_SMP.
	 */
	dma_wmb();

	old = cmpxchg64_relaxed(ptep, curr, new);

	return old;

Annotation

Implementation Notes