drivers/iommu/generic_pt/kunit_iommu_pt.h

Source file repositories/reference/linux-study-clean/drivers/iommu/generic_pt/kunit_iommu_pt.h

File Facts

System
Linux kernel
Corpus path
drivers/iommu/generic_pt/kunit_iommu_pt.h
Extension
.h
Size
13751 bytes
Lines
489
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 count_valids {
	u64 per_size[PT_VADDR_MAX_LG2];
};

static int __count_valids(struct pt_range *range, void *arg, unsigned int level,
			  struct pt_table_p *table)
{
	struct pt_state pts = pt_init(range, level, table);
	struct count_valids *valids = arg;

	for_each_pt_level_entry(&pts) {
		if (pts.type == PT_ENTRY_TABLE) {
			pt_descend(&pts, arg, __count_valids);
			continue;
		}
		if (pts.type == PT_ENTRY_OA) {
			valids->per_size[pt_entry_oa_lg2sz(&pts)]++;
			continue;
		}
	}
	return 0;
}

/*
 * Number of valid table entries. This counts contiguous entries as a single
 * valid.
 */
static unsigned int count_valids(struct kunit *test)
{
	struct kunit_iommu_priv *priv = test->priv;
	struct pt_range range = pt_top_range(priv->common);
	struct count_valids valids = {};
	u64 total = 0;
	unsigned int i;

	KUNIT_ASSERT_NO_ERRNO(test,
			      pt_walk_range(&range, __count_valids, &valids));

	for (i = 0; i != ARRAY_SIZE(valids.per_size); i++)
		total += valids.per_size[i];
	return total;
}

/* Only a single page size is present, count the number of valid entries */
static unsigned int count_valids_single(struct kunit *test, pt_vaddr_t pgsz)
{
	struct kunit_iommu_priv *priv = test->priv;
	struct pt_range range = pt_top_range(priv->common);
	struct count_valids valids = {};
	u64 total = 0;
	unsigned int i;

	KUNIT_ASSERT_NO_ERRNO(test,
			      pt_walk_range(&range, __count_valids, &valids));

	for (i = 0; i != ARRAY_SIZE(valids.per_size); i++) {
		if ((1ULL << i) == pgsz)
			total = valids.per_size[i];
		else
			KUNIT_ASSERT_EQ(test, valids.per_size[i], 0);
	}
	return total;
}

static void do_unmap(struct kunit *test, pt_vaddr_t va, pt_vaddr_t len)
{
	struct kunit_iommu_priv *priv = test->priv;
	size_t ret;

	ret = iommu_unmap(&priv->domain, va, len);
	KUNIT_ASSERT_EQ(test, ret, len);
}

static void check_iova(struct kunit *test, pt_vaddr_t va, pt_oaddr_t pa,
		       pt_vaddr_t len)
{
	struct kunit_iommu_priv *priv = test->priv;
	pt_vaddr_t pfn = log2_div(va, priv->smallest_pgsz_lg2);
	pt_vaddr_t end_pfn = pfn + log2_div(len, priv->smallest_pgsz_lg2);

	for (; pfn != end_pfn; pfn++) {
		phys_addr_t res = iommu_iova_to_phys(&priv->domain,
						     pfn * priv->smallest_pgsz);

		KUNIT_ASSERT_EQ(test, res, (phys_addr_t)pa);
		if (res != pa)
			break;
		pa += priv->smallest_pgsz;
	}
}

Annotation

Implementation Notes