tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c
Extension
.c
Size
3673 bytes
Lines
143
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (bar->info.size > bar_size) {
			bar_size = bar->info.size;
			largest = bar;
		}
	}

	return largest;
}

FIXTURE(vfio_dma_mapping_mmio_test) {
	struct iommu *iommu;
	struct vfio_pci_device *device;
	struct iova_allocator *iova_allocator;
	struct vfio_pci_bar *bar;
};

FIXTURE_VARIANT(vfio_dma_mapping_mmio_test) {
	const char *iommu_mode;
};

#define FIXTURE_VARIANT_ADD_IOMMU_MODE(_iommu_mode)			       \
FIXTURE_VARIANT_ADD(vfio_dma_mapping_mmio_test, _iommu_mode) {		       \
	.iommu_mode = #_iommu_mode,					       \
}

FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES();

#undef FIXTURE_VARIANT_ADD_IOMMU_MODE

FIXTURE_SETUP(vfio_dma_mapping_mmio_test)
{
	self->iommu = iommu_init(variant->iommu_mode);
	self->device = vfio_pci_device_init(device_bdf, self->iommu);
	self->iova_allocator = iova_allocator_init(self->iommu);
	self->bar = largest_mapped_bar(self->device);

	if (!self->bar)
		SKIP(return, "No mappable BAR found on device %s", device_bdf);
}

FIXTURE_TEARDOWN(vfio_dma_mapping_mmio_test)
{
	iova_allocator_cleanup(self->iova_allocator);
	vfio_pci_device_cleanup(self->device);
	iommu_cleanup(self->iommu);
}

static void do_mmio_map_test(struct iommu *iommu,
			     struct iova_allocator *iova_allocator,
			     void *vaddr, size_t size)
{
	struct dma_region region = {
		.vaddr = vaddr,
		.size = size,
		.iova = iova_allocator_alloc(iova_allocator, size),
	};

	/*
	 * NOTE: Check for iommufd compat success once it lands. Native iommufd
	 * will never support this.
	 */
	if (!strcmp(iommu->mode->name, MODE_VFIO_TYPE1V2_IOMMU) ||
	    !strcmp(iommu->mode->name, MODE_VFIO_TYPE1_IOMMU)) {
		iommu_map(iommu, &region);
		iommu_unmap(iommu, &region);
	} else {
		VFIO_ASSERT_NE(__iommu_map(iommu, &region), 0);
	}
}

TEST_F(vfio_dma_mapping_mmio_test, map_full_bar)
{
	do_mmio_map_test(self->iommu, self->iova_allocator,
			 self->bar->vaddr, self->bar->info.size);
}

TEST_F(vfio_dma_mapping_mmio_test, map_partial_bar)
{
	if (self->bar->info.size < 2 * getpagesize())
		SKIP(return, "BAR too small (size=0x%llx)", self->bar->info.size);

	do_mmio_map_test(self->iommu, self->iova_allocator,
			 self->bar->vaddr, getpagesize());
}

/* Test IOMMU mapping of BAR mmap with intentionally poor vaddr alignment. */
TEST_F(vfio_dma_mapping_mmio_test, map_bar_misaligned)
{
	/* Limit size to bound test time for large BARs */
	size_t size = min_t(size_t, self->bar->info.size, SZ_1G);

Annotation

Implementation Notes