From: Samiullah Khawaja <skhawaja@google.com>
To: David Matlack <dmatlack@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: Mon, 11 May 2026 20:53:12 +0000 [thread overview]
Message-ID: <agI6peKFWDdn939Z@google.com> (raw)
In-Reply-To: <af5EEN8PhVz4pTdE@google.com>
On Fri, May 08, 2026 at 08:14:08PM +0000, David Matlack wrote:
>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()
I thought it is ok to duplicate this as each test (in future) might have
different mapping requirements? we might have memfd, guest_memfd,
dma_buf with various mapping strategies for different usecases?
Or you are thinking of a basic helper that can be used by tests if they
are not doing anything fancy?
>
>> +
>> +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
Will update.
>
>> + 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);
>> +}
>> +
[snip]
>> +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?
Will remove in next revision.
>
>> + 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().
Can you please clarify, I didn't get it completely. so basically
something that can be called like following?
setup_copy_dma_regions(self, iommu1, &memcpy_region1, &driver_region1);
I think I get that you are concerned about link init. Maybe I can do?
int clone_dma_region(struct dma_region *source_region,
struct dma_region *dest_region);
We can maybe add it to the library?
>
>> + 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
Agreed. Will do.
>
>> +
>> + 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?
I will update this.
>
>> +
>> + 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?
Not really. I thought it is needed. But I think I will keep it to
exercise that. Will add a comment to clarify.
>
>> + 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
>>
Thanks,
Sami
next prev parent reply other threads:[~2026-05-11 20:53 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
2026-05-11 20:53 ` Samiullah Khawaja [this message]
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=agI6peKFWDdn939Z@google.com \
--to=skhawaja@google.com \
--cc=alex@shazbot.org \
--cc=dmatlack@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=shuah@kernel.org \
/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.