All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Matlack <dmatlack@google.com>
To: Samiullah Khawaja <skhawaja@google.com>
Cc: Aex Williamson <alex@shazbot.org>, Shuah Khan <shuah@kernel.org>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: Re: [PATCH 2/2] vfio: selftests: Add iommufd multi iommu test
Date: Fri, 8 May 2026 20:14:08 +0000	[thread overview]
Message-ID: <af5EEN8PhVz4pTdE@google.com> (raw)
In-Reply-To: <20260505221518.619123-3-skhawaja@google.com>

On 2026-05-05 10:14 PM, Samiullah Khawaja wrote:
> Add a test for iommufd to verify creation of multiple iommus using an
> already setup iommufd and switch between them.
> 
> Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
> ---
>  tools/testing/selftests/vfio/Makefile         |   1 +
>  .../vfio/vfio_iommufd_multi_iommu_test.c      | 203 ++++++++++++++++++
>  2 files changed, 204 insertions(+)
>  create mode 100644 tools/testing/selftests/vfio/vfio_iommufd_multi_iommu_test.c
> 
> diff --git a/tools/testing/selftests/vfio/Makefile b/tools/testing/selftests/vfio/Makefile
> index 0684932d91bf..24bdeaad590f 100644
> --- a/tools/testing/selftests/vfio/Makefile
> +++ b/tools/testing/selftests/vfio/Makefile
> @@ -8,6 +8,7 @@ else
>  CFLAGS = $(KHDR_INCLUDES)
>  TEST_GEN_PROGS += vfio_dma_mapping_test
>  TEST_GEN_PROGS += vfio_dma_mapping_mmio_test
> +TEST_GEN_PROGS += vfio_iommufd_multi_iommu_test
>  TEST_GEN_PROGS += vfio_iommufd_setup_test
>  TEST_GEN_PROGS += vfio_pci_device_test
>  TEST_GEN_PROGS += vfio_pci_device_init_perf_test
> diff --git a/tools/testing/selftests/vfio/vfio_iommufd_multi_iommu_test.c b/tools/testing/selftests/vfio/vfio_iommufd_multi_iommu_test.c
> new file mode 100644
> index 000000000000..7199c662637c
> --- /dev/null
> +++ b/tools/testing/selftests/vfio/vfio_iommufd_multi_iommu_test.c
> @@ -0,0 +1,203 @@
> +// 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 IOMMU_DEFAULT 0
> +#define IOMMU_WITH_PT 1
> +#define IOMMU_WITHOUT_PT 2
> +
> +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);
> +}

Can you create library helpers in the library to share with
vfio_pci_driver_test.c?

  dma_region_setup()
  dma_region_teardown()

> +
> +FIXTURE(vfio_iommufd_multi_iommu_test) {
> +	struct iommu *iommu;
> +	struct vfio_pci_device *device;
> +	struct iova_allocator *iova_allocator;
> +	struct dma_region memcpy_region;
> +	void *vaddr;
> +
> +	u64 size;
> +	void *src;
> +	void *dst;
> +	iova_t src_iova;
> +	iova_t dst_iova;
> +};
> +
> +FIXTURE_SETUP(vfio_iommufd_multi_iommu_test)
> +{
> +	struct vfio_pci_driver *driver;
> +
> +	self->iommu = iommu_init("iommufd");

MODE_IOMMUFD

> +	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);
> +
> +	if (driver->ops)
> +		vfio_pci_driver_init(self->device);
> +
> +	self->size = self->memcpy_region.size / 2;
> +	self->src = self->memcpy_region.vaddr;
> +	self->dst = self->src + self->size;
> +
> +	self->src_iova = to_iova(self->device, self->src);
> +	self->dst_iova = to_iova(self->device, self->dst);
> +}
> +
> +FIXTURE_TEARDOWN(vfio_iommufd_multi_iommu_test)
> +{
> +	struct vfio_pci_driver *driver = &self->device->driver;
> +
> +	if (driver->ops)
> +		vfio_pci_driver_remove(self->device);
> +
> +	region_teardown(self->iommu, &self->memcpy_region);
> +	region_teardown(self->iommu, &driver->region);
> +
> +	iova_allocator_cleanup(self->iova_allocator);
> +	vfio_pci_device_cleanup(self->device);
> +	iommu_cleanup(self->iommu);
> +}
> +
> +FIXTURE_VARIANT(vfio_iommufd_multi_iommu_test) {
> +	u32 start_iommu;
> +	u32 end_iommu;
> +};
> +
> +#define ADD_IOMMU_VARIANT(S, E) \
> +	FIXTURE_VARIANT_ADD(vfio_iommufd_multi_iommu_test, S##_to_##E) { \
> +		.start_iommu = IOMMU_##S, \
> +		.end_iommu = IOMMU_##E \
> +	};
> +
> +#define ADD_ALL_VARIANTS(S) \
> +	ADD_IOMMU_VARIANT(S, DEFAULT) \
> +	ADD_IOMMU_VARIANT(S, WITH_PT) \
> +	ADD_IOMMU_VARIANT(S, WITHOUT_PT)
> +
> +ADD_ALL_VARIANTS(DEFAULT)
> +ADD_ALL_VARIANTS(WITH_PT)
> +ADD_ALL_VARIANTS(WITHOUT_PT)
> +
> +static struct iommu *setup_variant_iommu(struct iommu *fixture_iommu,
> +					 u32 dev_id, u32 type)
> +{
> +	switch (type) {
> +	case IOMMU_WITH_PT:
> +		return iommufd_iommu_init(fixture_iommu->iommufd, dev_id,
> +					  IOMMUFD_IOMMU_INIT_CREATE_PT);
> +	case IOMMU_WITHOUT_PT:
> +		return iommufd_iommu_init(fixture_iommu->iommufd, dev_id, 0);
> +	default:
> +		return fixture_iommu;
> +	}
> +}
> +
> +static void test_memcpy(struct vfio_pci_device *device, void *src, void *dst,
> +			iova_t src_iova, iova_t dst_iova, u64 size, char val)
> +{
> +	if (!device->driver.ops)
> +		return;
> +
> +	memset(src, val, size);
> +	memset(dst, 0, size);
> +
> +	vfio_pci_driver_memcpy_start(device, src_iova, dst_iova, size, 100);

Why do 100 copies?

> +	VFIO_ASSERT_EQ(vfio_pci_driver_memcpy_wait(device), 0);
> +	VFIO_ASSERT_EQ(memcmp(src, dst, size), 0);
> +}
> +
> +TEST_F(vfio_iommufd_multi_iommu_test, memcpy)
> +{
> +	struct dma_region memcpy_region1, driver_region1;
> +	struct dma_region memcpy_region2, driver_region2;
> +	struct iommu *iommu1;
> +	struct iommu *iommu2;
> +
> +	iommu1 = setup_variant_iommu(self->iommu, self->device->dev_id,
> +				     variant->start_iommu);
> +	if (iommu1 != self->iommu) {
> +		memcpy_region1 = self->memcpy_region;
> +		driver_region1 = self->device->driver.region;
> +
> +		iommu_map(iommu1, &memcpy_region1);

Can you make a helper to copy dma_region into a new iommu? It should set
up the new struct dma_region based on the old one, re-initialize the
link field, and then call iommu_map().

> +		iommu_map(iommu1, &driver_region1);
> +
> +		vfio_pci_device_attach_iommu(self->device, iommu1);
> +	}
> +
> +	test_memcpy(self->device, self->src, self->dst, self->src_iova,
> +		    self->dst_iova, self->size, 'x');

nit: You can pass in self to avoid unpacking it in every call to
test_memcpy(). The type would be:

  struct _test_data_vfio_iommufd_multi_iommu_test *self

> +
> +	iommu2 = setup_variant_iommu(self->iommu, self->device->dev_id,
> +				     variant->end_iommu);
> +	if (iommu2 != self->iommu) {
> +		memcpy_region2 = self->memcpy_region;
> +		driver_region2 = self->device->driver.region;
> +
> +		iommu_map(iommu2, &memcpy_region2);
> +		iommu_map(iommu2, &driver_region2);
> +	}
> +
> +	vfio_pci_device_attach_iommu(self->device, iommu2);
> +	test_memcpy(self->device, self->src, self->dst, self->src_iova,
> +		    self->dst_iova, self->size, 'a');

test_memcpy() zeroes self->dst every time so do you need to use a
different character for each call?

> +
> +	vfio_pci_device_attach_iommu(self->device, iommu1);
> +	test_memcpy(self->device, self->src, self->dst, self->src_iova,
> +		    self->dst_iova, self->size, '1');
> +
> +	if (iommu1 != self->iommu) {
> +		/* attach back to default iommu for cleanup */
> +		vfio_pci_device_attach_iommu(self->device, self->iommu);
> +		iommu_unmap(iommu1, &memcpy_region1);
> +		iommu_unmap(iommu1, &driver_region1);
> +		iommu_cleanup(iommu1);
> +	}
> +
> +	if (iommu2 != self->iommu) {
> +		iommu_unmap(iommu2, &memcpy_region2);
> +		iommu_unmap(iommu2, &driver_region2);

nit: You don't need to unmap before cleanup. Is this just to exercise
that unmap works on the variant iommus?

> +		iommu_cleanup(iommu2);
> +	}
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	device_bdf = vfio_selftests_get_bdf(&argc, argv);
> +
> +	return test_harness_run(argc, argv);
> +}
> -- 
> 2.54.0.545.g6539524ca2-goog
> 

  reply	other threads:[~2026-05-08 20:14 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-05 22:14 [PATCH 0/2] vfio: selftests: Add iommufd multi iommu test Samiullah Khawaja
2026-05-05 22:14 ` [PATCH 1/2] vfio: selftests: Add support of creating multiple iommus from iommufd Samiullah Khawaja
2026-05-08 18:17   ` David Matlack
2026-05-11 20:21     ` Samiullah Khawaja
2026-05-11 20:59       ` David Matlack
2026-05-11 21:41         ` Samiullah Khawaja
2026-05-05 22:14 ` [PATCH 2/2] vfio: selftests: Add iommufd multi iommu test Samiullah Khawaja
2026-05-08 20:14   ` David Matlack [this message]
2026-05-11 20:53     ` Samiullah Khawaja
2026-05-11 21:10       ` David Matlack
2026-05-11 21:27         ` Samiullah Khawaja

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=af5EEN8PhVz4pTdE@google.com \
    --to=dmatlack@google.com \
    --cc=alex@shazbot.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=shuah@kernel.org \
    --cc=skhawaja@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.