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 1/4] vfio: selftests: Introduce vfio_dma_mapping_perf_test
Date: Tue, 14 Jul 2026 16:44:58 +0000 [thread overview]
Message-ID: <alZnitH5racGUSr0@google.com> (raw)
In-Reply-To: <20260701203311.326798-2-aaronlewis@google.com>
On 2026-07-01 08:33 PM, Aaron Lewis wrote:
> Introduce a tool to aid in latency testing rather than a traditional
> pass/fail test. The goal is to make the test configurable to expose
> latency issues and make them easy to reproduce and share.
>
> Start with a basic test that performs a simple DMA map/unmap and reports
> the duration of each operation. Report the following four metrics:
>
> 1. Time taken by mmap().
> 2. Time taken to map a DMA region.
> 3. Time taken to unmap a DMA region.
> 4. Time taken by munmap().
>
> Subsequent commits in this series will introduce more features to allow
> for a wider variety of testing.
>
> Signed-off-by: Aaron Lewis <aaronlewis@google.com>
> diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c
> new file mode 100644
> index 000000000000..87d84450fc47
> --- /dev/null
> +++ b/tools/testing/selftests/vfio/vfio_dma_mapping_perf_test.c
> +static void timer_start(struct timespec *start) {
> + clock_gettime(CLOCK_MONOTONIC, start);
> +}
> +
> +static double timer_elapsed_ms(struct timespec start)
> +{
> + struct timespec end;
> +
> + clock_gettime(CLOCK_MONOTONIC, &end);
> +
> + return (double)(end.tv_sec - start.tv_sec) * MSEC_PER_SEC +
> + (double)(end.tv_nsec - start.tv_nsec) / NSEC_PER_MSEC;
> +}
Please add these to the library and let's exposed the full granularity
(number of nanoseconds as a u64) and let caller decide how to format it.
> +
> +FIXTURE(vfio_dma_mapping_perf_test) {
> + struct iommu *iommu;
> + struct vfio_pci_device *device;
> + struct iova_allocator *iova_allocator;
> +};
> +
> +FIXTURE_VARIANT(vfio_dma_mapping_perf_test) {
> + const char *iommu_mode;
> + int mmap_flags;
> +};
> +
> +#define FIXTURE_VARIANT_ADD_IOMMU_MODE(_iommu_mode, _name, _mmap_flags) \
> +FIXTURE_VARIANT_ADD(vfio_dma_mapping_perf_test, _iommu_mode ## _ ## _name) { \
> + .iommu_mode = #_iommu_mode, \
> + .mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE | (_mmap_flags), \
> +}
> +
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(anonymous, 0);
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(anonymous_hugetlb_2mb, MAP_HUGETLB | MAP_HUGE_2MB);
> +FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(anonymous_hugetlb_1gb, MAP_HUGETLB | MAP_HUGE_1GB);
> +
> +#undef FIXTURE_VARIANT_ADD_IOMMU_MODE
> +
> +FIXTURE_SETUP(vfio_dma_mapping_perf_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_test)
> +{
> + iova_allocator_cleanup(self->iova_allocator);
> + vfio_pci_device_cleanup(self->device);
> + iommu_cleanup(self->iommu);
> +}
> +
> +TEST_F(vfio_dma_mapping_perf_test, dma_map_unmap)
> +{
> + const u64 size = SZ_1G;
> + const int flags = variant->mmap_flags;
> + struct dma_region region;
> + struct timespec start;
> + u64 unmapped;
> + int rc;
> +
> + timer_start(&start);
> + region.vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
> + printf("Completed mmap() in %.2lfms\n", timer_elapsed_ms(start));
> +
> + /* Skip the test if there aren't enough HugeTLB pages available. */
> + if (flags & MAP_HUGETLB && region.vaddr == MAP_FAILED)
> + SKIP(return, "mmap() failed: %s (%d)\n", strerror(errno), errno);
> + else
> + ASSERT_NE(region.vaddr, MAP_FAILED);
> +
> + region.iova = iova_allocator_alloc(self->iova_allocator, size);
> + region.size = size;
> +
> + timer_start(&start);
> + 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));
To ease with parsing the test output for performance results maybe we
should avoid including specific addresses/sizes mixed in? You can print
out the configuration first and then all the performance data. e.g.
Test Config: size=1GB, backing=HugeTLB, page_size=1GB
mmap: XX.YYYYYs
IOMMU map: XX.YYYYYs
IOMMU unmap: XX.YYYYYs
munmap: XX.YYYYYs
I don't think logging the HVA or IOVAs are particularly useful.
> + 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));
Consider generating the timer code. e.g.
+#define TIME(_name, _expression) do { \
+ struct timespec __start; \
+ \
+ timer_start(&__start); \
+ _expression; \
+ printf(_name ": %.2lfms", timer_elapsed_ms(__start)); \
+} while (0)
+
TEST_F(vfio_dma_mapping_perf_test, dma_map_unmap)
{
const u64 size = test_params.size;
const int flags = variant->mmap_flags | test_params.mmap_flags;
struct dma_region region;
- struct timespec start;
u64 unmapped;
- int rc;
- timer_start(&start);
- region.vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
- printf("Completed mmap() in %.2lfms\n", timer_elapsed_ms(start));
+ TIME("mmap", mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0));
/* Skip the test if there aren't enough HugeTLB pages available. */
if (flags & MAP_HUGETLB && region.vaddr == MAP_FAILED)
@@ -108,21 +112,13 @@ TEST_F(vfio_dma_mapping_perf_test, dma_map_unmap)
region.iova = iova_allocator_alloc(self->iova_allocator, size);
region.size = size;
- timer_start(&start);
- 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));
+ TIME("IOMMU map", iommu_map(self->iommu, ®ion));
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);
+ TIME("IOMMU unmap", ASSERT_EQ(0,__iommu_unmap(self->iommu, ®ion, &unmapped)));
ASSERT_EQ(unmapped, region.size);
- timer_start(&start);
- ASSERT_TRUE(!munmap(region.vaddr, size));
- printf("Completed munmap() in %.2lfms\n", timer_elapsed_ms(start));
+ TIME("munmap", ASSERT_TRUE(!munmap(region.vaddr, size)));
}
> + ASSERT_EQ(rc, 0);
> + ASSERT_EQ(unmapped, region.size);
> +
> + timer_start(&start);
> + ASSERT_TRUE(!munmap(region.vaddr, size));
> + printf("Completed munmap() in %.2lfms\n", timer_elapsed_ms(start));
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + device_bdf = vfio_selftests_get_bdf(&argc, argv);
> + return test_harness_run(argc, argv);
> +}
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
next prev parent reply other threads:[~2026-07-14 16:45 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 [this message]
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
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=alZnitH5racGUSr0@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.