drivers/iommu/io-pgtable-arm-selftests.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iommu/io-pgtable-arm-selftests.c
Extension
.c
Size
5112 bytes
Lines
215
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

if (!ops) {
			kunit_err(test, "failed to allocate io pgtable ops\n");
			return -ENOMEM;
		}

		/*
		 * Initial sanity checks.
		 * Empty page tables shouldn't provide any translations.
		 */
		if (ops->iova_to_phys(ops, 42))
			return __FAIL(test, i);

		if (ops->iova_to_phys(ops, SZ_1G + 42))
			return __FAIL(test, i);

		if (ops->iova_to_phys(ops, SZ_2G + 42))
			return __FAIL(test, i);

		/*
		 * Distinct mappings of different granule sizes.
		 */
		iova = 0;
		for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
			size = 1UL << j;

			if (ops->map_pages(ops, iova, iova, size, 1,
					   IOMMU_READ | IOMMU_WRITE |
					   IOMMU_NOEXEC | IOMMU_CACHE,
					   GFP_KERNEL, &mapped))
				return __FAIL(test, i);

			/* Overlapping mappings */
			if (!ops->map_pages(ops, iova, iova + size, size, 1,
					    IOMMU_READ | IOMMU_NOEXEC,
					    GFP_KERNEL, &mapped))
				return __FAIL(test, i);

			if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
				return __FAIL(test, i);

			iova += SZ_1G;
		}

		/* Full unmap */
		iova = 0;
		for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
			size = 1UL << j;

			if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
				return __FAIL(test, i);

			if (ops->iova_to_phys(ops, iova + 42))
				return __FAIL(test, i);

			/* Remap full block */
			if (ops->map_pages(ops, iova, iova, size, 1,
					   IOMMU_WRITE, GFP_KERNEL, &mapped))
				return __FAIL(test, i);

			if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
				return __FAIL(test, i);

			iova += SZ_1G;
		}

		/*
		 * Map/unmap the last largest supported page of the IAS, this can
		 * trigger corner cases in the concatednated page tables.
		 */
		mapped = 0;
		size = 1UL << __fls(cfg->pgsize_bitmap);
		iova = (1UL << cfg->ias) - size;
		if (ops->map_pages(ops, iova, iova, size, 1,
				   IOMMU_READ | IOMMU_WRITE |
				   IOMMU_NOEXEC | IOMMU_CACHE,
				   GFP_KERNEL, &mapped))
			return __FAIL(test, i);
		if (mapped != size)
			return __FAIL(test, i);
		if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
			return __FAIL(test, i);

		free_io_pgtable_ops(ops);
	}

	return 0;
}

static void arm_lpae_do_selftests(struct kunit *test)
{

Annotation

Implementation Notes