drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c

Source file repositories/reference/linux-study-clean/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c

File Facts

System
Linux kernel
Corpus path
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
Extension
.c
Size
27386 bytes
Lines
820
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 arm_smmu_test_writer {
	struct arm_smmu_entry_writer writer;
	struct kunit *test;
	const __le64 *init_entry;
	const __le64 *target_entry;
	__le64 *entry;

	bool invalid_entry_written;
	unsigned int num_syncs;
};

#define NUM_ENTRY_QWORDS 8
#define NUM_EXPECTED_SYNCS(x) x

static struct arm_smmu_ste bypass_ste;
static struct arm_smmu_ste abort_ste;
static struct arm_smmu_device smmu = {
	.features = ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_ATTR_TYPES_OVR
};
static struct mm_struct sva_mm = {
	.pgd = (void *)0xdaedbeefdeadbeefULL,
};

enum arm_smmu_test_master_feat {
	ARM_SMMU_MASTER_TEST_ATS = BIT(0),
	ARM_SMMU_MASTER_TEST_STALL = BIT(1),
	ARM_SMMU_MASTER_TEST_NESTED = BIT(2),
};

static void arm_smmu_test_make_s2_ste(struct arm_smmu_ste *ste,
				      enum arm_smmu_test_master_feat feat);

static bool arm_smmu_entry_differs_in_used_bits(const __le64 *entry,
						const __le64 *used_bits,
						const __le64 *target,
						const __le64 *safe,
						unsigned int length)
{
	bool differs = false;
	unsigned int i;

	for (i = 0; i < length; i++) {
		__le64 used = used_bits[i] & ~safe[i];

		if ((entry[i] & used) != (target[i] & used))
			differs = true;
	}
	return differs;
}

static void
arm_smmu_test_writer_record_syncs(struct arm_smmu_entry_writer *writer)
{
	struct arm_smmu_test_writer *test_writer =
		container_of(writer, struct arm_smmu_test_writer, writer);
	__le64 *entry_used_bits;
	__le64 *safe_target;
	__le64 *safe_init;

	entry_used_bits = kunit_kzalloc(
		test_writer->test, sizeof(*entry_used_bits) * NUM_ENTRY_QWORDS,
		GFP_KERNEL);
	KUNIT_ASSERT_NOT_NULL(test_writer->test, entry_used_bits);

	safe_target = kunit_kzalloc(test_writer->test,
				    sizeof(*safe_target) * NUM_ENTRY_QWORDS,
				    GFP_KERNEL);
	KUNIT_ASSERT_NOT_NULL(test_writer->test, safe_target);

	safe_init = kunit_kzalloc(test_writer->test,
				  sizeof(*safe_init) * NUM_ENTRY_QWORDS,
				  GFP_KERNEL);
	KUNIT_ASSERT_NOT_NULL(test_writer->test, safe_init);

	pr_debug("STE value is now set to: ");
	print_hex_dump_debug("    ", DUMP_PREFIX_NONE, 16, 8,
			     test_writer->entry,
			     NUM_ENTRY_QWORDS * sizeof(*test_writer->entry),
			     false);

	test_writer->num_syncs += 1;
	if (!test_writer->entry[0]) {
		test_writer->invalid_entry_written = true;
	} else {
		/*
		 * At any stage in a hitless transition, the entry must be
		 * equivalent to either the initial entry or the target entry
		 * when only considering the bits used by the current
		 * configuration.
		 */

Annotation

Implementation Notes