tools/testing/selftests/vfio/vfio_pci_driver_test.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/vfio/vfio_pci_driver_test.c
Extension
.c
Size
6419 bytes
Lines
264
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

// SPDX-License-Identifier: GPL-2.0-only
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <linux/sizes.h>
#include <linux/vfio.h>

#include <libvfio.h>

#include "kselftest_harness.h"

static const char *device_bdf;

#define ASSERT_NO_MSI(_eventfd) do {			\
	u64 __value;					\
							\
	ASSERT_EQ(-1, read(_eventfd, &__value, 8));	\
	ASSERT_EQ(EAGAIN, errno);			\
} while (0)

static void region_setup(struct iommu *iommu,
			 struct iova_allocator *iova_allocator,
			 struct dma_region *region, u64 size)
{
	const int flags = MAP_SHARED | MAP_ANONYMOUS;
	const int prot = PROT_READ | PROT_WRITE;
	void *vaddr;

	vaddr = mmap(NULL, size, prot, flags, -1, 0);
	VFIO_ASSERT_NE(vaddr, MAP_FAILED);

	region->vaddr = vaddr;
	region->iova = iova_allocator_alloc(iova_allocator, size);
	region->size = size;

	iommu_map(iommu, region);
}

static void region_teardown(struct iommu *iommu, struct dma_region *region)
{
	iommu_unmap(iommu, region);
	VFIO_ASSERT_EQ(munmap(region->vaddr, region->size), 0);
}

FIXTURE(vfio_pci_driver_test) {
	struct iommu *iommu;
	struct vfio_pci_device *device;
	struct iova_allocator *iova_allocator;
	struct dma_region memcpy_region;
	void *vaddr;
	int msi_fd;

	u64 size;
	void *src;
	void *dst;
	iova_t src_iova;
	iova_t dst_iova;
	iova_t unmapped_iova;
};

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

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

FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES();

FIXTURE_SETUP(vfio_pci_driver_test)
{
	struct vfio_pci_driver *driver;

	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);

	driver = &self->device->driver;

	region_setup(self->iommu, self->iova_allocator, &self->memcpy_region, SZ_1G);
	region_setup(self->iommu, self->iova_allocator, &driver->region, SZ_2M);

	/* Any IOVA that doesn't overlap memcpy_region and driver->region. */
	self->unmapped_iova = iova_allocator_alloc(self->iova_allocator, SZ_1G);

	vfio_pci_driver_init(self->device);
	self->msi_fd = self->device->msi_eventfds[driver->msi];

Annotation

Implementation Notes