From: David Matlack <dmatlack@google.com>
To: Aaron Lewis <aaronlewis@google.com>
Cc: kvm@vger.kernel.org, alex@shazbot.org, jgg@nvidia.com
Subject: Re: [PATCH 2/4] vfio: selftests: Add memfd test to vfio_dma_mapping_perf_test
Date: Tue, 14 Jul 2026 16:53:07 +0000 [thread overview]
Message-ID: <alZpc7oSwtw7hExk@google.com> (raw)
In-Reply-To: <20260701203311.326798-3-aaronlewis@google.com>
On 2026-07-01 08:33 PM, Aaron Lewis wrote:
> Add a second test to "vfio_dma_mapping_perf_test" to evaluate memfd
> latencies. A key motivator for adding this test is to demonstrate that
> the IOMMU_IOAS_MAP_FILE ioctl is significantly faster than other methods
> of mapping DMA regions. While this performance difference is not fully
> apparent with the test's current capabilities, it will become evident
> as more features are introduced later in the series.
>
> To support this, add IOMMU_IOAS_MAP_FILE ioctl support to the VFIO
> selftest library via iommufd_map_file().
>
> Signed-off-by: Aaron Lewis <aaronlewis@google.com>
> ---
> .../vfio/lib/include/libvfio/iommu.h | 7 ++
> tools/testing/selftests/vfio/lib/iommu.c | 24 ++++
> .../vfio/vfio_dma_mapping_perf_test.c | 118 ++++++++++++++++++
> 3 files changed, 149 insertions(+)
>
> diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
> index e9a3386a4719..eeef5990292c 100644
> --- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
> +++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
> @@ -35,6 +35,13 @@ struct iommu {
> struct iommu *iommu_init(const char *iommu_mode);
> void iommu_cleanup(struct iommu *iommu);
>
> +int __iommufd_map_file(struct iommu *iommu, struct dma_region *region, int fd);
> +
> +static inline void iommufd_map_file(struct iommu *iommu, struct dma_region *region, int fd)
> +{
> + VFIO_ASSERT_EQ(__iommufd_map_file(iommu, region, fd), 0);
> +}
> +
> int __iommu_map(struct iommu *iommu, struct dma_region *region);
>
> static inline void iommu_map(struct iommu *iommu, struct dma_region *region)
> diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
> index 035dac069d60..6730b39060ca 100644
> --- a/tools/testing/selftests/vfio/lib/iommu.c
> +++ b/tools/testing/selftests/vfio/lib/iommu.c
> @@ -97,6 +97,30 @@ iova_t iommu_hva2iova(struct iommu *iommu, void *vaddr)
> return iova;
> }
>
> +int __iommufd_map_file(struct iommu *iommu, struct dma_region *region, int fd)
> +{
> + VFIO_ASSERT_TRUE(iommu->iommufd, "IOMMU_IOAS_MAP_FILE is an IOMMUFD IOCTL.");
> +
> + struct iommu_ioas_map_file args = {
> + .size = sizeof(args),
> + .flags = IOMMU_IOAS_MAP_READABLE |
> + IOMMU_IOAS_MAP_WRITEABLE |
> + IOMMU_IOAS_MAP_FIXED_IOVA,
> + .ioas_id = iommu->ioas_id,
> + .fd = fd,
> + .start = 0,
> + .iova = region->iova,
> + .length = region->size,
> + };
> +
> + if (ioctl(iommu->iommufd, IOMMU_IOAS_MAP_FILE, &args))
> + return -errno;
> +
> + list_add(®ion->link, &iommu->dma_regions);
> +
> + return 0;
> +}
> +
> static int vfio_iommu_map(struct iommu *iommu, struct dma_region *region)
> {
> struct vfio_iommu_type1_dma_map args = {
> diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c
> index 87d84450fc47..4639bda7ebaa 100644
> --- a/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c
> +++ b/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c
> @@ -117,6 +117,124 @@ TEST_F(vfio_dma_mapping_perf_test, dma_map_unmap)
> printf("Completed munmap() in %.2lfms\n", timer_elapsed_ms(start));
> }
>
> +FIXTURE(vfio_dma_mapping_perf_memfd_test) {
> + struct iommu *iommu;
> + struct vfio_pci_device *device;
> + struct iova_allocator *iova_allocator;
> +};
> +
> +FIXTURE_VARIANT(vfio_dma_mapping_perf_memfd_test) {
> + const char *iommu_mode;
> + int mmap_flags;
> + int memfd_flags;
> +};
> +
> +#define FIXTURE_VARIANT_ADD_IOMMU_MODE(_iommu_mode, _name, _mmap_flags, _memfd_flags) \
> +FIXTURE_VARIANT_ADD(vfio_dma_mapping_perf_memfd_test, _iommu_mode ## _ ## _name) { \
> + .iommu_mode = #_iommu_mode, \
> + .mmap_flags = MAP_SHARED | (_mmap_flags), \
> + .memfd_flags = MAP_SHARED | (_memfd_flags), \
> +}
> +
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(memfd, 0, 0);
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(memfd_hugetlb_2mb,
> + MAP_HUGETLB | MAP_HUGE_2MB,
> + MFD_HUGETLB | MFD_HUGE_2MB);
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(memfd_hugetlb_1gb,
> + MAP_HUGETLB | MAP_HUGE_1GB,
> + MFD_HUGETLB | MFD_HUGE_1GB);
Only iommufd supports file-based mapping so not need to replicate across
all other IOMMU modes. Just run with iommufd.
And then you can drop the special case below where you fallback to
HVA-based mapping in the file-based test, which is largely duplicating
the other test.
If you want to also have test coverage for HVA-based mapping of
file-backed memory then you should add that separately, and include
iommufd in it.
> +
> +#undef FIXTURE_VARIANT_ADD_IOMMU_MODE
> +
> +FIXTURE_SETUP(vfio_dma_mapping_perf_memfd_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);
> +}
> +
> +FIXTURE_TEARDOWN(vfio_dma_mapping_perf_memfd_test)
> +{
> + iova_allocator_cleanup(self->iova_allocator);
> + vfio_pci_device_cleanup(self->device);
> + iommu_cleanup(self->iommu);
> +}
> +
> +static void *setup_memfd(int *fd, u64 size, int mmap_flags, int mfd_flags)
> +{
> + void *buf = MAP_FAILED;
> + struct timespec start;
> +
> + timer_start(&start);
> + *fd = memfd_create("vfio_dma_mapping_perf_memfd_test", mfd_flags);
> + printf("Completed memfd_create() in %.2lfms\n", timer_elapsed_ms(start));
> + if (*fd <= 0)
> + return MAP_FAILED;
> +
> + if (ftruncate(*fd, size))
> + goto out;
> +
> + timer_start(&start);
> + buf = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, *fd, 0);
> + printf("Completed mmap() for memfd in %.2lfms\n", timer_elapsed_ms(start));
> +
> +out:
> + if (buf == MAP_FAILED)
> + close(*fd);
> +
> + return buf;
> +}
> +
> +static void teardown_memfd(int fd, u64 size, void *vaddr)
> +{
> + struct timespec start;
> +
> + if (vaddr != MAP_FAILED) {
> + timer_start(&start);
> + munmap(vaddr, size);
> + printf("Completed munmap() in %.2lfms\n", timer_elapsed_ms(start));
> + }
> +
> + if (fd != -1) {
> + timer_start(&start);
> + close(fd);
> + printf("Completed close() in %.2lfms\n", timer_elapsed_ms(start));
> + }
> +}
> +
> +TEST_F(vfio_dma_mapping_perf_memfd_test, dma_map_unmap_from_file)
> +{
> + const u64 size = SZ_1G;
> + struct dma_region region;
> + struct timespec start;
> + u64 unmapped;
> + int rc, fd;
> +
> + region.vaddr = setup_memfd(&fd, size, variant->mmap_flags, variant->memfd_flags);
> + ASSERT_NE(region.vaddr, MAP_FAILED);
> +
> + region.iova = iova_allocator_alloc(self->iova_allocator, size);
> + region.size = size;
> +
> + timer_start(&start);
> + if (strcmp(variant->iommu_mode, MODE_IOMMUFD) == 0) {
> + iommufd_map_file(self->iommu, ®ion, fd);
> + } else {
> + iommu_map(self->iommu, ®ion);
> + }
> + printf("Mapped HVA %p (size %luG) at IOVA 0x%lx in %.2lfms\n",
> + region.vaddr, size / SZ_1G, region.iova, timer_elapsed_ms(start));
> + ASSERT_EQ(region.iova, to_iova(self->device, region.vaddr));
> +
> + timer_start(&start);
> + rc = __iommu_unmap(self->iommu, ®ion, &unmapped);
> + printf("Unmapped IOVA 0x%lx in %.2lfms\n", region.iova, timer_elapsed_ms(start));
> + ASSERT_EQ(rc, 0);
> + ASSERT_EQ(unmapped, region.size);
Maybe we should add this assert to iommu_unmap() and you can just use
iommu_unmap() here and in the other test?
> +
> + teardown_memfd(fd, size, region.vaddr);
> +}
> +
> int main(int argc, char *argv[])
> {
> device_bdf = vfio_selftests_get_bdf(&argc, argv);
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
next prev parent reply other threads:[~2026-07-14 16:53 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 20:33 [PATCH 0/4] Introduce vfio_dma_mapping_perf_test Aaron Lewis
2026-07-01 20:33 ` [PATCH 1/4] vfio: selftests: " Aaron Lewis
2026-07-01 20:44 ` sashiko-bot
2026-07-14 16:44 ` David Matlack
2026-07-01 20:33 ` [PATCH 2/4] vfio: selftests: Add memfd test to vfio_dma_mapping_perf_test Aaron Lewis
2026-07-01 20:43 ` sashiko-bot
2026-07-14 16:53 ` David Matlack [this message]
2026-07-01 20:33 ` [PATCH 3/4] vfio: selftests: Allow a size for vfio_dma_mapping_perf_test Aaron Lewis
2026-07-01 20:44 ` sashiko-bot
2026-07-14 17:49 ` David Matlack
2026-07-01 20:33 ` [PATCH 4/4] vfio: selftests: Allow the flag MAP_POPULATE to be set on the cmdline Aaron Lewis
2026-07-07 20:30 ` David Matlack
2026-07-07 20:32 ` David Matlack
2026-07-14 16:27 ` [PATCH 0/4] Introduce vfio_dma_mapping_perf_test David Matlack
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=alZpc7oSwtw7hExk@google.com \
--to=dmatlack@google.com \
--cc=aaronlewis@google.com \
--cc=alex@shazbot.org \
--cc=jgg@nvidia.com \
--cc=kvm@vger.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.