* [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage
@ 2026-07-03 3:28 Narayana Murty N
2026-07-03 3:28 ` [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment Narayana Murty N
` (6 more replies)
0 siblings, 7 replies; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
This RFC adds PowerPC sPAPR TCE v2 support to VFIO selftests.
The series adds a selftest IOMMU mode for the legacy VFIO container
backend, adds helpers for default and dynamic DMA windows, and exercises
the sPAPR DDW path through the DMA mapping tests.
sPAPR TCE v2 remains a legacy VFIO container backend. This series does
not add iommufd or VFIO cdev support for sPAPR.
The main points are
1. add VFIO_SELFTESTS_IOMMU_MODE for selecting a backend
2. add vfio_spapr_tce_v2_iommu as the PowerPC VFIO backend
3. preserve the platform default DMA window
4. create and tear down only selftest-created DDWs
5. prepare the DMA window before IOVA allocation
6. exercise DDW creation for hugepage DMA mappings
7. accept sPAPR-specific errno for invalid DMA ranges
Example:
VFIO_SELFTESTS_IOMMU_MODE=vfio_spapr_tce_v2_iommu
./vfio_dma_mapping_test <BDF>
Observed coverage includes anonymous mappings through the default window
and 2MB hugetlb mappings through a DDW. 1GB hugetlb mappings may skip when
the platform rejects the requested DDW characteristics.
Feedback is requested from the VFIO and PowerPC communities on:
1. whether the sPAPR TCE v2 helpers should remain in the common VFIO
selftest library or move into a sPAPR-specific test helper?
2. whether DDW setup through hugepage mappings is the right initial
coverage?
3. whether the sPAPR-specific overflow errno expectation should be
accepted, skipped, or hidden behind a backend helper?
4. whether PowerPC should generate only the sPAPR TCE v2 fixture variants,
or keep the generic IOMMU-mode matrix and skip unsupported modes.
TODO: vfio_spapr_tce_v1_iommu yet to be covered.
Narayana Murty N (6):
selftests/vfio: allow selecting IOMMU backend from environment
selftests/vfio: add sPAPR TCE v2 IOMMU mode
selftests/vfio: add sPAPR TCE v2 DMA window helpers
selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings
selftests/vfio: Accept sPAPR errno for DMA range overflow
selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le
.../selftests/vfio/lib/include/libvfio.h | 9 +
.../vfio/lib/include/libvfio/iommu.h | 26 ++
tools/testing/selftests/vfio/lib/iommu.c | 280 +++++++++++++++++-
tools/testing/selftests/vfio/lib/libvfio.c | 37 +++
.../selftests/vfio/vfio_dma_mapping_test.c | 30 ++
.../selftests/vfio/vfio_pci_device_test.c | 4 +-
tools/testing/selftests/vfio/Makefile | 2 +-
7 files changed, 382 insertions(+), 6 deletions(-)
--
2.51.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:06 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode Narayana Murty N
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Add support for selecting the IOMMU mode through the environment
variable VFIO_SELFTESTS_IOMMU_MODE. This allows tests to be run
with different IOMMU backends without modifying test code.
The environment variable is validated against the list of supported
modes. On PowerPC, this includes the sPAPR TCE v2 mode which will
be added in a subsequent patch.
If the environment variable is not set, tests use their default
mode, preserving existing behavior.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
.../selftests/vfio/lib/include/libvfio.h | 9 +++++
tools/testing/selftests/vfio/lib/libvfio.c | 39 +++++++++++++++++++
.../selftests/vfio/vfio_pci_device_test.c | 4 +-
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio.h b/tools/testing/selftests/vfio/lib/include/libvfio.h
index 07862b470777..c0b4a2ab06c5 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio.h
@@ -24,6 +24,15 @@
const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs);
+/*
+ * Return the IOMMU mode string from the environment variable
+ * $VFIO_SELFTESTS_IOMMU_MODE.
+ *
+ * Returns NULL if the environment variable is not set, allowing
+ * tests to use their default mode.
+ */
+const char *vfio_selftests_get_iommu_mode(void);
+
/*
* Reserve virtual address space of size at an address satisfying
* (vaddr % align) == offset.
diff --git a/tools/testing/selftests/vfio/lib/libvfio.c b/tools/testing/selftests/vfio/lib/libvfio.c
index 3a3d1ed635c1..617c8dc7288c 100644
--- a/tools/testing/selftests/vfio/lib/libvfio.c
+++ b/tools/testing/selftests/vfio/lib/libvfio.c
@@ -101,3 +101,42 @@ void *mmap_reserve(size_t size, size_t align, size_t offset)
return map_align;
}
+
+static const char *get_iommu_mode_env(void)
+{
+ const char *mode;
+ static const char * const valid_modes[] = {
+ MODE_VFIO_TYPE1_IOMMU,
+ MODE_VFIO_TYPE1V2_IOMMU,
+ MODE_IOMMUFD_COMPAT_TYPE1,
+ MODE_IOMMUFD_COMPAT_TYPE1V2,
+ MODE_IOMMUFD,
+#ifdef __powerpc__
+ MODE_VFIO_SPAPR_TCE_V2_IOMMU,
+#endif
+ };
+ int i;
+
+ mode = getenv("VFIO_SELFTESTS_IOMMU_MODE");
+ if (!mode)
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(valid_modes); i++) {
+ if (!strcmp(mode, valid_modes[i]))
+ return mode;
+ }
+
+ fprintf(stderr, "Invalid VFIO_SELFTESTS_IOMMU_MODE: %s\n", mode);
+ fprintf(stderr, "Valid modes are:\n");
+ for (i = 0; i < ARRAY_SIZE(valid_modes); i++)
+ fprintf(stderr, " %s\n", valid_modes[i]);
+ exit(KSFT_SKIP);
+}
+
+const char *vfio_selftests_get_iommu_mode(void)
+{
+ return get_iommu_mode_env();
+}
+
+ return map_align;
+}
diff --git a/tools/testing/selftests/vfio/vfio_pci_device_test.c b/tools/testing/selftests/vfio/vfio_pci_device_test.c
index 93c11fd5e081..45b8bf60527a 100644
--- a/tools/testing/selftests/vfio/vfio_pci_device_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_device_test.c
@@ -29,7 +29,7 @@ FIXTURE(vfio_pci_device_test) {
FIXTURE_SETUP(vfio_pci_device_test)
{
- self->iommu = iommu_init(default_iommu_mode);
+ self->iommu = iommu_init(vfio_selftests_get_iommu_mode());
self->device = vfio_pci_device_init(device_bdf, self->iommu);
}
@@ -121,7 +121,7 @@ FIXTURE_VARIANT_ADD(vfio_pci_irq_test, msix) {
FIXTURE_SETUP(vfio_pci_irq_test)
{
- self->iommu = iommu_init(default_iommu_mode);
+ self->iommu = iommu_init(vfio_selftests_get_iommu_mode());
self->device = vfio_pci_device_init(device_bdf, self->iommu);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
2026-07-03 3:28 ` [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:09 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers Narayana Murty N
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Add a PowerPC-specific VFIO selftest IOMMU mode for sPAPR TCE v2.
The new mode uses the legacy VFIO container interface with
VFIO_SPAPR_TCE_v2_IOMMU. It does not use iommufd or VFIO cdev.
On PowerPC, generate the sPAPR TCE v2 fixture variant so the tests exercise
the backend that is valid for this platform.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
tools/testing/selftests/vfio/lib/include/libvfio/iommu.h | 8 ++++++++
tools/testing/selftests/vfio/lib/iommu.c | 7 +++++++
2 files changed, 15 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..ba027a7270d0 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
@@ -66,17 +66,25 @@ struct iommu_iova_range *iommu_iova_ranges(struct iommu *iommu, u32 *nranges);
#define MODE_IOMMUFD_COMPAT_TYPE1 "iommufd_compat_type1"
#define MODE_IOMMUFD_COMPAT_TYPE1V2 "iommufd_compat_type1v2"
#define MODE_IOMMUFD "iommufd"
+#ifdef __powerpc__
+#define MODE_VFIO_SPAPR_TCE_V2_IOMMU "vfio_spapr_tce_v2_iommu"
+#endif
/*
* Generator for VFIO selftests fixture variants that replicate across all
* possible IOMMU modes. Tests must define FIXTURE_VARIANT_ADD_IOMMU_MODE()
* which should then use FIXTURE_VARIANT_ADD() to create the variant.
*/
+#ifdef __powerpc__
+#define FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(...) \
+FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_spapr_tce_v2_iommu, ##__VA_ARGS__)
+#else
#define FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(...) \
FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1_iommu, ##__VA_ARGS__); \
FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1v2_iommu, ##__VA_ARGS__); \
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1, ##__VA_ARGS__); \
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1v2, ##__VA_ARGS__); \
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd, ##__VA_ARGS__)
+#endif
#endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_IOMMU_H */
diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
index 035dac069d60..e86457a715bf 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -47,6 +47,13 @@ static const struct iommu_mode iommu_modes[] = {
{
.name = MODE_IOMMUFD,
},
+#ifdef __powerpc__
+ {
+ .name = MODE_VFIO_SPAPR_TCE_V2_IOMMU,
+ .container_path = "/dev/vfio/vfio",
+ .iommu_type = VFIO_SPAPR_TCE_v2_IOMMU,
+ },
+#endif
};
static const struct iommu_mode *lookup_iommu_mode(const char *iommu_mode)
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
2026-07-03 3:28 ` [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment Narayana Murty N
2026-07-03 3:28 ` [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:05 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings Narayana Murty N
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Add helper support for sPAPR TCE v2 DMA windows in the VFIO selftest
library.
Track the platform default DMA window separately from selftest-created
dynamic DMA windows. The default window is discovered with
VFIO_IOMMU_SPAPR_TCE_GET_INFO and is not removed during cleanup.
Add helpers to create and remove DDWs, return the active IOVA range, and
register/unregister memory around DMA map/unmap operations. Window
selection is done before IOVA allocation; the map path only validates,
registers memory, and calls VFIO_IOMMU_MAP_DMA.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
.../vfio/lib/include/libvfio/iommu.h | 18 ++
tools/testing/selftests/vfio/lib/iommu.c | 273 +++++++++++++++++-
tools/testing/selftests/vfio/lib/libvfio.c | 2 -
3 files changed, 288 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
index ba027a7270d0..c9b9ab929f1f 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
@@ -24,12 +24,26 @@ struct dma_region {
u64 size;
};
+struct spapr_tce_window {
+ u64 start;
+ u64 size;
+ u32 page_shift;
+ bool valid;
+ bool dynamic;
+ bool remove_on_cleanup;
+};
+
struct iommu {
const struct iommu_mode *mode;
int container_fd;
int iommufd;
u32 ioas_id;
struct list_head dma_regions;
+#ifdef __powerpc__
+ struct spapr_tce_window default_window;
+ struct spapr_tce_window ddw_window;
+ struct spapr_tce_window *active_window;
+#endif
};
struct iommu *iommu_init(const char *iommu_mode);
@@ -61,6 +75,10 @@ iova_t iommu_hva2iova(struct iommu *iommu, void *vaddr);
struct iommu_iova_range *iommu_iova_ranges(struct iommu *iommu, u32 *nranges);
+int iommu_prepare_dma_window(struct iommu *iommu, u64 min_size,
+ u64 page_size, bool force_dynamic);
+bool iommu_supports_unmap_all(struct iommu *iommu);
+
#define MODE_VFIO_TYPE1_IOMMU "vfio_type1_iommu"
#define MODE_VFIO_TYPE1V2_IOMMU "vfio_type1v2_iommu"
#define MODE_IOMMUFD_COMPAT_TYPE1 "iommufd_compat_type1"
diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
index e86457a715bf..19d19bb45a14 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -16,9 +16,11 @@
#include <linux/types.h>
#include <linux/vfio.h>
#include <linux/iommufd.h>
+#include <linux/sizes.h>
#include "../../../kselftest.h"
#include <libvfio.h>
+#include <limits.h>
const char *default_iommu_mode = MODE_IOMMUFD;
@@ -93,6 +95,233 @@ int __iommu_hva2iova(struct iommu *iommu, void *vaddr, iova_t *iova)
return -ENOENT;
}
+#ifdef __powerpc__
+static bool iommu_is_spapr_tce_v2(struct iommu *iommu)
+{
+ return !!(iommu->mode->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU);
+}
+
+static u32 page_size_to_shift(u64 page_size)
+{
+ return __builtin_ctzll(page_size);
+}
+
+static int spapr_tce_read_default_window(struct iommu *iommu)
+{
+ struct vfio_iommu_spapr_tce_info info = {
+ .argsz = sizeof(info),
+ };
+
+ if (iommu->default_window.valid)
+ return 0;
+
+ if (ioctl(iommu->container_fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info))
+ return -errno;
+
+ iommu->default_window.start = info.dma32_window_start;
+ iommu->default_window.size = info.dma32_window_size;
+ iommu->default_window.page_shift = page_size_to_shift(getpagesize());
+ iommu->default_window.valid = true;
+ iommu->default_window.dynamic = false;
+ iommu->default_window.remove_on_cleanup = false;
+
+ return 0;
+}
+
+static int spapr_tce_create_ddw(struct iommu *iommu, u64 min_size, u32 page_shift)
+{
+ struct vfio_iommu_spapr_tce_create create = {
+ .argsz = sizeof(create),
+ .page_shift = page_shift,
+ .levels = 1,
+ .window_size = min_size,
+ };
+
+ if (ioctl(iommu->container_fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create))
+ return -errno;
+
+ iommu->ddw_window.start = create.start_addr;
+ iommu->ddw_window.size = create.window_size;
+ iommu->ddw_window.page_shift = page_shift;
+ iommu->ddw_window.valid = true;
+ iommu->ddw_window.dynamic = true;
+ iommu->ddw_window.remove_on_cleanup = true;
+
+ return 0;
+}
+
+static int spapr_tce_remove_window(struct iommu *iommu, struct spapr_tce_window *window)
+{
+ struct vfio_iommu_spapr_tce_remove remove = {
+ .argsz = sizeof(remove),
+ .start_addr = window->start,
+ };
+
+ if (!window->valid || !window->remove_on_cleanup)
+ return 0;
+
+ if (ioctl(iommu->container_fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove))
+ return -errno;
+
+ window->valid = false;
+ return 0;
+}
+
+static bool spapr_tce_window_satisfies(struct spapr_tce_window *window,
+ u64 min_size, u32 page_shift,
+ bool require_dynamic)
+{
+ if (!window || !window->valid)
+ return false;
+
+ if (require_dynamic && !window->dynamic)
+ return false;
+
+ if (window->size < min_size)
+ return false;
+
+ if (window->page_shift != page_shift)
+ return false;
+
+ return true;
+}
+
+static struct iommu_iova_range *spapr_tce_iova_ranges(struct iommu *iommu, u32 *nranges)
+{
+ struct iommu_iova_range *ranges;
+ int ret;
+
+ if (!iommu->active_window) {
+ ret = iommu_prepare_dma_window(iommu, SZ_1G, getpagesize(), false);
+ if (ret)
+ return NULL;
+ }
+
+ ranges = calloc(1, sizeof(*ranges));
+ VFIO_ASSERT_NOT_NULL(ranges);
+
+ ranges[0].start = iommu->active_window->start;
+ ranges[0].last = iommu->active_window->start + iommu->active_window->size - 1;
+
+ *nranges = 1;
+ return ranges;
+}
+
+static bool spapr_tce_iova_inside_window(struct iommu *iommu, struct dma_region *region)
+{
+ struct spapr_tce_window *window = iommu->active_window;
+
+ if (!window || !window->valid)
+ return false;
+
+ if (region->iova < window->start)
+ return false;
+
+ if (region->iova + region->size > window->start + window->size)
+ return false;
+
+ return true;
+}
+
+static int spapr_register_memory(struct iommu *iommu, struct dma_region *region)
+{
+ struct vfio_iommu_spapr_register_memory args = {
+ .argsz = sizeof(args),
+ .vaddr = (u64)region->vaddr,
+ .size = region->size,
+ };
+
+ if (ioctl(iommu->container_fd, VFIO_IOMMU_SPAPR_REGISTER_MEMORY, &args))
+ return -errno;
+
+ return 0;
+}
+
+static int spapr_unregister_memory(struct iommu *iommu, struct dma_region *region)
+{
+ struct vfio_iommu_spapr_register_memory args = {
+ .argsz = sizeof(args),
+ .vaddr = (u64)region->vaddr,
+ .size = region->size,
+ };
+
+ if (ioctl(iommu->container_fd, VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, &args))
+ return -errno;
+
+ return 0;
+}
+
+int iommu_prepare_dma_window(struct iommu *iommu, u64 min_size,
+ u64 page_size, bool force_dynamic)
+{
+ u32 page_shift;
+ int ret;
+
+ if (!iommu_is_spapr_tce_v2(iommu))
+ return 0;
+
+ if (!page_size)
+ page_size = getpagesize();
+
+ page_shift = page_size_to_shift(page_size);
+
+ ret = spapr_tce_read_default_window(iommu);
+ if (ret)
+ return ret;
+
+ /*
+ * Normal mapping path:
+ * use default window when it satisfies the request.
+ */
+ if (!force_dynamic &&
+ spapr_tce_window_satisfies(&iommu->default_window,
+ min_size, page_shift, false)) {
+ iommu->active_window = &iommu->default_window;
+ return 0;
+ }
+
+ /*
+ * Dynamic path:
+ * use existing DDW if it already satisfies the request.
+ */
+ if (spapr_tce_window_satisfies(&iommu->ddw_window,
+ min_size, page_shift, true)) {
+ iommu->active_window = &iommu->ddw_window;
+ return 0;
+ }
+
+ /*
+ * Neither default nor DDW is sufficient.
+ * Remove only the selftest-created DDW, then create a new DDW.
+ */
+ ret = spapr_tce_remove_window(iommu, &iommu->ddw_window);
+ if (ret)
+ return ret;
+
+ ret = spapr_tce_create_ddw(iommu, min_size, page_shift);
+ if (ret)
+ return ret;
+
+ iommu->active_window = &iommu->ddw_window;
+ return 0;
+}
+#else
+int iommu_prepare_dma_window(struct iommu *iommu, u64 min_size,
+ u64 page_size, bool force_dynamic)
+{
+ return 0;
+}
+#endif
+
+bool iommu_supports_unmap_all(struct iommu *iommu)
+{
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu))
+ return false;
+#endif
+ return true;
+}
+
iova_t iommu_hva2iova(struct iommu *iommu, void *vaddr)
{
iova_t iova;
@@ -113,9 +342,27 @@ static int vfio_iommu_map(struct iommu *iommu, struct dma_region *region)
.iova = region->iova,
.size = region->size,
};
+ int ret;
- if (ioctl(iommu->container_fd, VFIO_IOMMU_MAP_DMA, &args))
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu)) {
+ if (!spapr_tce_iova_inside_window(iommu, region))
+ return -EINVAL;
+
+ ret = spapr_register_memory(iommu, region);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ ret = ioctl(iommu->container_fd, VFIO_IOMMU_MAP_DMA, &args);
+ if (ret) {
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu))
+ spapr_unregister_memory(iommu, region);
+#endif
return -errno;
+ }
return 0;
}
@@ -177,8 +424,18 @@ static int __vfio_iommu_unmap(int fd, u64 iova, u64 size, u32 flags, u64 *unmapp
static int vfio_iommu_unmap(struct iommu *iommu, struct dma_region *region,
u64 *unmapped)
{
- return __vfio_iommu_unmap(iommu->container_fd, region->iova,
- region->size, 0, unmapped);
+ int ret;
+
+ ret = __vfio_iommu_unmap(iommu->container_fd, region->iova,
+ region->size, 0, unmapped);
+ if (ret)
+ return ret;
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu))
+ ret = spapr_unregister_memory(iommu, region);
+#endif
+
+ return ret;
}
static int __iommufd_unmap(int fd, u64 iova, u64 length, u32 ioas_id, u64 *unmapped)
@@ -324,6 +581,11 @@ static struct iommu_iova_range *vfio_iommu_iova_ranges(struct iommu *iommu,
struct vfio_info_cap_header *hdr;
struct iommu_iova_range *ranges = NULL;
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu))
+ return spapr_tce_iova_ranges(iommu, nranges);
+#endif
+
info = vfio_iommu_get_info(iommu->container_fd);
hdr = vfio_iommu_info_cap_hdr(info, VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE);
VFIO_ASSERT_NOT_NULL(hdr);
@@ -462,6 +724,11 @@ struct iommu *iommu_init(const char *iommu_mode)
void iommu_cleanup(struct iommu *iommu)
{
+#ifdef __powerpc__
+ if (iommu_is_spapr_tce_v2(iommu))
+ spapr_tce_remove_window(iommu, &iommu->ddw_window);
+#endif
+
if (iommu->iommufd)
VFIO_ASSERT_EQ(close(iommu->iommufd), 0);
else
diff --git a/tools/testing/selftests/vfio/lib/libvfio.c b/tools/testing/selftests/vfio/lib/libvfio.c
index 617c8dc7288c..12f731963b05 100644
--- a/tools/testing/selftests/vfio/lib/libvfio.c
+++ b/tools/testing/selftests/vfio/lib/libvfio.c
@@ -138,5 +138,3 @@ const char *vfio_selftests_get_iommu_mode(void)
return get_iommu_mode_env();
}
- return map_align;
-}
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
` (2 preceding siblings ...)
2026-07-03 3:28 ` [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:11 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow Narayana Murty N
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Prepare the DMA window before IOVA allocation in the DMA mapping tests.
Anonymous mappings use the default sPAPR DMA window. HugeTLB mappings force
a DDW with the requested page size, allowing the test to exercise DDW
creation, mapping, unmapping, and cleanup.
Skip gracefully when hugepage allocation fails or when the platform does
not support the requested DDW characteristics. Also skip unmap-all when
the backend cannot pair it with the sPAPR memory unregister flow.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
.../selftests/vfio/vfio_dma_mapping_test.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
index 7d0de8c79de1..4411fdbd56da 100644
--- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
+++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <stdio.h>
+#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -119,8 +120,19 @@ FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(anonymous_hugetlb_1gb, SZ_1G, MAP_HUGETLB |
FIXTURE_SETUP(vfio_dma_mapping_test)
{
+ const u64 page_size = variant->size ?: getpagesize();
+ const bool force_dynamic = !!variant->size;
+ int ret;
+
self->iommu = iommu_init(variant->iommu_mode);
self->device = vfio_pci_device_init(device_bdf, self->iommu);
+
+ ret = iommu_prepare_dma_window(self->iommu, page_size, page_size,
+ force_dynamic);
+ if (ret)
+ SKIP(return, "DMA window unavailable: %s (%d)\n",
+ strerror(-ret), -ret);
+
self->iova_allocator = iova_allocator_init(self->iommu);
}
@@ -227,6 +239,7 @@ FIXTURE_SETUP(vfio_dma_map_limit_test)
u64 region_size = getpagesize();
iova_t last_iova;
u32 nranges;
+ int ret;
/*
* Over-allocate mmap by double the size to provide enough backing vaddr
@@ -236,6 +249,13 @@ FIXTURE_SETUP(vfio_dma_map_limit_test)
self->iommu = iommu_init(variant->iommu_mode);
self->device = vfio_pci_device_init(device_bdf, self->iommu);
+
+ ret = iommu_prepare_dma_window(self->iommu, region_size, region_size,
+ false);
+ if (ret)
+ SKIP(return, "DMA window unavailable: %s (%d)\n",
+ strerror(-ret), -ret);
+
region->vaddr = mmap(NULL, self->mmap_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
ASSERT_NE(region->vaddr, MAP_FAILED);
@@ -277,6 +297,8 @@ TEST_F(vfio_dma_map_limit_test, unmap_all)
u64 unmapped;
int rc;
+ if (!iommu_supports_unmap_all(self->iommu))
+ SKIP(return, "IOMMU backend does not support unmap-all\n");
iommu_map(self->iommu, region);
ASSERT_EQ(region->iova, to_iova(self->device, region->vaddr));
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
` (3 preceding siblings ...)
2026-07-03 3:28 ` [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:08 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le Narayana Murty N
2026-07-03 8:28 ` [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Harsh Prateek Bora
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Accept sPAPR errno for DMA range overflow
The DMA map limit test expects an overflowing IOVA range to fail with
-EOVERFLOW. That matches the Type1 and iommufd paths.
On sPAPR TCE v2, the same invalid range is rejected as outside the active
TCE window and currently returns -ENXIO. Treat that as the expected ppc
result for this RFC while keeping the existing -EOVERFLOW expectation for
other backends.
This keeps the overflow test enabled for sPAPR TCE v2 instead of skipping
it.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
tools/testing/selftests/vfio/vfio_dma_mapping_test.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
index 4411fdbd56da..cd2d3276a46c 100644
--- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
+++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
@@ -316,10 +316,18 @@ TEST_F(vfio_dma_map_limit_test, overflow)
region->size = self->mmap_size;
rc = __iommu_map(self->iommu, region);
+#ifdef __powerpc__
+ ASSERT_EQ(rc, -ENXIO);
+#else
ASSERT_EQ(rc, -EOVERFLOW);
+#endif
rc = __iommu_unmap(self->iommu, region, NULL);
+#ifdef __powerpc__
+ ASSERT_EQ(rc, -ENXIO);
+#else
ASSERT_EQ(rc, -EOVERFLOW);
+#endif
}
int main(int argc, char *argv[])
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
` (4 preceding siblings ...)
2026-07-03 3:28 ` [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow Narayana Murty N
@ 2026-07-03 3:28 ` Narayana Murty N
2026-07-03 8:14 ` sashiko-bot
2026-07-03 8:28 ` [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Harsh Prateek Bora
6 siblings, 1 reply; 14+ messages in thread
From: Narayana Murty N @ 2026-07-03 3:28 UTC (permalink / raw)
To: alex, dmatlack, shuah
Cc: amastro, rananta, nnmlinux, kvm, linux-kselftest, linux-kernel,
vaibhav, sbhat, harshpb
Enable VFIO selftests to build on ppc64 and ppc64le made the changes to
Makefile to include ppc64 and ppc64le.
With sPAPR TCE v2 support added to the VFIO selftest library, PowerPC
systems can run the DMA mapping tests against the legacy VFIO container
backend.
Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
---
tools/testing/selftests/vfio/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vfio/Makefile b/tools/testing/selftests/vfio/Makefile
index 2c32c48db509..8fd6afd334e5 100644
--- a/tools/testing/selftests/vfio/Makefile
+++ b/tools/testing/selftests/vfio/Makefile
@@ -1,6 +1,6 @@
ARCH ?= $(shell uname -m)
-ifeq (,$(filter $(ARCH),aarch64 arm64 x86 x86_64))
+ifeq (,$(filter $(ARCH),aarch64 arm64 x86 x86_64 ppc64 ppc64le))
# Do nothing on unsupported architectures
include ../lib.mk
else
--
2.51.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers
2026-07-03 3:28 ` [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers Narayana Murty N
@ 2026-07-03 8:05 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:05 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] `vfio_iommu_map()` incorrectly returns a clobbered `errno` if `VFIO_IOMMU_MAP_DMA` fails.
- [Medium] If memory unregistration fails during unmap, the region is left in the `dma_regions` list despite being successfully unmapped in the IOMMU.
- [Medium] Failed DDW creation leaves `iommu->active_window` pointing to an invalidated window, leading to stale IOVA ranges being returned.
--
commit 2deeaa397a1d09614f068ff5ae82a0732c573cd4
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: add sPAPR TCE v2 DMA window helpers
This commit adds helper support for sPAPR TCE v2 DMA windows in the VFIO
selftest library. It tracks the platform default DMA window separately from
selftest-created dynamic DMA windows, and adds helpers to create, remove,
and register memory around DMA map/unmap operations.
> diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
> index e86457a715bf7..19d19bb45a14b 100644
> --- a/tools/testing/selftests/vfio/lib/iommu.c
> +++ b/tools/testing/selftests/vfio/lib/iommu.c
[ ... ]
> + /*
> + * Neither default nor DDW is sufficient.
> + * Remove only the selftest-created DDW, then create a new DDW.
> + */
> + ret = spapr_tce_remove_window(iommu, &iommu->ddw_window);
> + if (ret)
> + return ret;
> +
> + ret = spapr_tce_create_ddw(iommu, min_size, page_shift);
> + if (ret)
> + return ret;
[Severity: Medium]
If spapr_tce_create_ddw() fails here, does it leave iommu->active_window
pointing to a window that was just invalidated by spapr_tce_remove_window()?
If iommu->active_window was previously set to &iommu->ddw_window, it is not
reset to NULL on this error path. Later, spapr_tce_iova_ranges() reads
iommu->active_window->start without checking if the window is valid:
static struct iommu_iova_range *spapr_tce_iova_ranges(...)
{
...
ranges[0].start = iommu->active_window->start;
ranges[0].last = iommu->active_window->start +
iommu->active_window->size - 1;
...
}
Could this return stale IOVA ranges to the caller?
> +
> + iommu->active_window = &iommu->ddw_window;
> + return 0;
> +}
[ ... ]
> @@ -113,9 +342,27 @@ static int vfio_iommu_map(struct iommu *iommu, struct dma_region *region)
> .iova = region->iova,
> .size = region->size,
> };
> + int ret;
>
> - if (ioctl(iommu->container_fd, VFIO_IOMMU_MAP_DMA, &args))
> +#ifdef __powerpc__
> + if (iommu_is_spapr_tce_v2(iommu)) {
> + if (!spapr_tce_iova_inside_window(iommu, region))
> + return -EINVAL;
> +
> + ret = spapr_register_memory(iommu, region);
> + if (ret)
> + return ret;
> + }
> +#endif
> +
> + ret = ioctl(iommu->container_fd, VFIO_IOMMU_MAP_DMA, &args);
> + if (ret) {
> +#ifdef __powerpc__
> + if (iommu_is_spapr_tce_v2(iommu))
> + spapr_unregister_memory(iommu, region);
> +#endif
> return -errno;
> + }
[Severity: Medium]
Can the cleanup call to spapr_unregister_memory() clobber the errno from the
failed VFIO_IOMMU_MAP_DMA ioctl?
Since spapr_unregister_memory() performs its own ioctl, it might overwrite
the thread-local errno. Will this result in vfio_iommu_map() returning the
result of the cleanup operation instead of the actual mapping failure?
>
> return 0;
> }
[ ... ]
> @@ -177,8 +424,18 @@ static int __vfio_iommu_unmap(int fd, u64 iova, u64 size, u32 flags, u64 *unmapp
> static int vfio_iommu_unmap(struct iommu *iommu, struct dma_region *region,
> u64 *unmapped)
> {
> - return __vfio_iommu_unmap(iommu->container_fd, region->iova,
> - region->size, 0, unmapped);
> + int ret;
> +
> + ret = __vfio_iommu_unmap(iommu->container_fd, region->iova,
> + region->size, 0, unmapped);
> + if (ret)
> + return ret;
> +#ifdef __powerpc__
> + if (iommu_is_spapr_tce_v2(iommu))
> + ret = spapr_unregister_memory(iommu, region);
> +#endif
> +
> + return ret;
> }
[Severity: Medium]
If __vfio_iommu_unmap() succeeds but spapr_unregister_memory() fails, does
returning this error bypass the region cleanup in __iommu_unmap()?
In __iommu_unmap():
if (iommu->iommufd)
ret = iommufd_unmap(iommu, region, unmapped);
else
ret = vfio_iommu_unmap(iommu, region, unmapped);
if (ret)
return ret;
list_del_init(®ion->link);
If we return the unregistration failure here, the early return in
__iommu_unmap() skips list_del_init(). Will this leave the successfully
unmapped region in the dma_regions list and corrupt internal state tracking?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment
2026-07-03 3:28 ` [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment Narayana Murty N
@ 2026-07-03 8:06 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:06 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] A syntax error is introduced at the end of the file due to stray duplicated code.
- [Low] The macro `MODE_VFIO_SPAPR_TCE_V2_IOMMU` is referenced but never defined, breaking the build on PowerPC.
--
commit 711defe4ecc8034b88efefbbf07a52494153b474
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: allow selecting IOMMU backend from environment
This commit adds support for selecting the IOMMU mode through the
VFIO_SELFTESTS_IOMMU_MODE environment variable. It validates the environment
variable against a list of supported modes, including sPAPR TCE v2 on PowerPC.
> diff --git a/tools/testing/selftests/vfio/lib/libvfio.c b/tools/testing/selftests/vfio/lib/libvfio.c
> index 3a3d1ed635c1d..617c8dc7288ca 100644
> --- a/tools/testing/selftests/vfio/lib/libvfio.c
> +++ b/tools/testing/selftests/vfio/lib/libvfio.c
[ ... ]
> @@ -101,3 +101,42 @@ void *mmap_reserve(size_t size, size_t align, size_t offset)
>
> return map_align;
> }
> +
> +static const char *get_iommu_mode_env(void)
> +{
> + const char *mode;
> + static const char * const valid_modes[] = {
> + MODE_VFIO_TYPE1_IOMMU,
> + MODE_VFIO_TYPE1V2_IOMMU,
> + MODE_IOMMUFD_COMPAT_TYPE1,
> + MODE_IOMMUFD_COMPAT_TYPE1V2,
> + MODE_IOMMUFD,
> +#ifdef __powerpc__
> + MODE_VFIO_SPAPR_TCE_V2_IOMMU,
[Severity: Low]
Does this break the build on PowerPC because MODE_VFIO_SPAPR_TCE_V2_IOMMU is
referenced but never defined?
I notice this is fixed in a later commit
8dfc3e7df9b7153c07746fbc4679447d70174937 ("selftests/vfio: add sPAPR TCE v2
IOMMU mode"), but introducing an undefined identifier here will cause git
bisect failures for PowerPC builds.
> +#endif
> + };
[ ... ]
> +const char *vfio_selftests_get_iommu_mode(void)
> +{
> + return get_iommu_mode_env();
> +}
> +
> + return map_align;
> +}
[Severity: Low]
Is this stray return statement and closing brace a copy-paste error?
It causes a syntax error at the file scope. I see this is removed in a later
commit 2deeaa397a1d09614f068ff5ae82a0732c573cd4 ("selftests/vfio: add sPAPR
TCE v2 DMA window helpers"), but having it in this patch breaks the build
and git bisect.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow
2026-07-03 3:28 ` [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow Narayana Murty N
@ 2026-07-03 8:08 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:08 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Architecture-specific macro breaks test execution with alternative IOMMU backends on PowerPC.
- [Medium] The test's expectation of `-ENXIO` codifies and relies upon an integer overflow bug in the test library's user-space validation helper.
--
commit 93dbee7bb3c363a49eb5141c94b3669c7520cd26
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: Accept sPAPR errno for DMA range overflow
The DMA map limit test expects an overflowing IOVA range to fail with
-EOVERFLOW. This commit modifies the test to expect -ENXIO when compiled
for powerpc to account for sPAPR TCE v2 rejecting the range as outside
the active TCE window.
> diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
> index 4411fdbd56da5..cd2d3276a46c4 100644
> --- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
> +++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
> @@ -316,10 +316,18 @@ TEST_F(vfio_dma_map_limit_test, overflow)
> region->size = self->mmap_size;
>
> rc = __iommu_map(self->iommu, region);
> +#ifdef __powerpc__
> + ASSERT_EQ(rc, -ENXIO);
[Severity: Medium]
Will this architecture-specific macro break test execution if an alternative
IOMMU backend is used on PowerPC?
Since earlier patches in this series allow selecting the IOMMU backend via
the VFIO_SELFTESTS_IOMMU_MODE environment variable, running the test on
PowerPC with iommufd would return the generic -EOVERFLOW error. Because of
the #ifdef, the test would erroneously expect -ENXIO and fail.
Would it be better to base this branch on the active backend type (e.g.,
inspecting variant->iommu_mode) rather than the compilation target?
[Severity: Medium]
Does expecting -ENXIO here codify a bug in the user-space validation
helper?
In the overflow test, the region->iova is set to a large value so that
region->iova + region->size wraps around to 0.
Looking at spapr_tce_iova_inside_window() introduced earlier in the series,
it evaluates:
tools/testing/selftests/vfio/lib/iommu.c:spapr_tce_iova_inside_window() {
...
if (region->iova + region->size > window->start + window->size)
return false;
...
}
Due to the wrap-around, 0 > 0 + window->size evaluates to false, causing
the validation helper to return true. This bypasses user-space validation,
allowing the invalid IOVA to be sent to the kernel via VFIO_IOMMU_MAP_DMA,
which then rejects it with -ENXIO.
If the user-space bounds check is fixed to catch wrap-arounds (for example,
checking if region->iova + region->size < region->iova), the helper would
correctly return false and the user-space map attempt would return -EINVAL.
Would that fix cause this test to fail because it now explicitly expects
-ENXIO?
> +#else
> ASSERT_EQ(rc, -EOVERFLOW);
> +#endif
>
> rc = __iommu_unmap(self->iommu, region, NULL);
> +#ifdef __powerpc__
> + ASSERT_EQ(rc, -ENXIO);
> +#else
> ASSERT_EQ(rc, -EOVERFLOW);
> +#endif
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=5
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode
2026-07-03 3:28 ` [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode Narayana Murty N
@ 2026-07-03 8:09 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:09 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The fallback default IOMMU mode remains hardcoded to MODE_IOMMUFD, causing test suites to crash out-of-the-box on PowerPC where IOMMUFD is not supported for VFIO.
--
commit 8dfc3e7df9b7153c07746fbc4679447d70174937
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: add sPAPR TCE v2 IOMMU mode
Add a PowerPC-specific VFIO selftest IOMMU mode for sPAPR TCE v2.
The new mode uses the legacy VFIO container interface with
VFIO_SPAPR_TCE_v2_IOMMU.
[ ... ]
> diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
> index 035dac069d601..e86457a715bf7 100644
> --- a/tools/testing/selftests/vfio/lib/iommu.c
> +++ b/tools/testing/selftests/vfio/lib/iommu.c
> @@ -47,6 +47,13 @@ static const struct iommu_mode iommu_modes[] = {
> {
> .name = MODE_IOMMUFD,
> },
> +#ifdef __powerpc__
> + {
> + .name = MODE_VFIO_SPAPR_TCE_V2_IOMMU,
> + .container_path = "/dev/vfio/vfio",
> + .iommu_type = VFIO_SPAPR_TCE_v2_IOMMU,
> + },
> +#endif
> };
[Severity: Medium]
Since default_iommu_mode remains hardcoded to MODE_IOMMUFD earlier in this
file, does this cause test suites like vfio_pci_driver_test to crash
out-of-the-box on PowerPC systems?
For instance, device_has_selftests_driver() uses this default mode directly
before checking platform-specific fixtures:
tools/testing/selftests/vfio/vfio_pci_driver_test.c:device_has_selftests_driver() {
...
iommu = iommu_init(default_iommu_mode);
...
}
If /dev/iommu cannot be opened or device bindings fail on PowerPC because
IOMMUFD isn't supported, does this trigger a failed assertion
(VFIO_ASSERT_GT(iommu->iommufd, 0)) and abort execution rather than
skipping gracefully?
Should default_iommu_mode be conditionally defined for PowerPC to use
MODE_VFIO_SPAPR_TCE_V2_IOMMU as the default fallback?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings
2026-07-03 3:28 ` [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings Narayana Murty N
@ 2026-07-03 8:11 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:11 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The selftest helper `spapr_tce_iova_inside_window` fails to check for arithmetic overflow when validating whether an IOVA range fits within the window.
--
commit 09ce4770fae5d9e1ed108bb9feb0bc727a9b8bcc
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings
Prepare the DMA window before IOVA allocation in the DMA mapping tests.
Anonymous mappings use the default sPAPR DMA window, while HugeTLB mappings
force a DDW with the requested page size. The tests are skipped gracefully
if allocation fails or if the platform lacks support.
> diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
> index 7d0de8c79de13..4411fdbd56da5 100644
> --- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
> +++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
[ ... ]
> @@ -236,6 +249,13 @@ FIXTURE_SETUP(vfio_dma_map_limit_test)
>
> self->iommu = iommu_init(variant->iommu_mode);
> self->device = vfio_pci_device_init(device_bdf, self->iommu);
> +
> + ret = iommu_prepare_dma_window(self->iommu, region_size, region_size,
> + false);
[Severity: Medium]
Will this setup cause the test suite to silently pass invalid mappings in the
overflow test?
In tools/testing/selftests/vfio/lib/iommu.c, spapr_tce_iova_inside_window()
checks bounds using:
if (region->iova + region->size > window->start + window->size)
return false;
When the vfio_dma_map_limit_test's overflow test constructs a wrapping IOVA
(region->iova = ~(iova_t)0 & ~(region->size - 1)), region->iova + region->size
will wrap around to 0.
Since 0 is not greater than window->start + window->size, the check incorrectly
evaluates to false, making the function return true. Does this missing overflow
check defeat the wrapper's bounds validation and pass invalid mapping requests
down to the kernel ioctl?
> + if (ret)
> + SKIP(return, "DMA window unavailable: %s (%d)\n",
> + strerror(-ret), -ret);
> +
> region->vaddr = mmap(NULL, self->mmap_size, PROT_READ | PROT_WRITE,
> MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> ASSERT_NE(region->vaddr, MAP_FAILED);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=4
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le
2026-07-03 3:28 ` [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le Narayana Murty N
@ 2026-07-03 8:14 ` sashiko-bot
0 siblings, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-07-03 8:14 UTC (permalink / raw)
To: Narayana Murty N; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The VFIO selftests will still be silently skipped on PowerPC when building from the top-level kernel directory (e.g., via `make kselftest`).
--
commit e8d7fbeb96b4d48f400e3fc2cba19a75370e70e6
Author: Narayana Murty N <nnmlinux@linux.ibm.com>
selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le
This commit modifies the VFIO selftests Makefile to enable building on
PowerPC architectures. It allows PowerPC systems to run DMA mapping
tests against the legacy VFIO container backend.
> diff --git a/tools/testing/selftests/vfio/Makefile b/tools/testing/selftests/vfio/Makefile
> index e6e8cb52ab030..dc686a38ab0a9 100644
> --- a/tools/testing/selftests/vfio/Makefile
> +++ b/tools/testing/selftests/vfio/Makefile
> @@ -1,6 +1,6 @@
> ARCH ?= $(shell uname -m)
>
> -ifeq (,$(filter $(ARCH),aarch64 arm64 x86 x86_64))
> +ifeq (,$(filter $(ARCH),aarch64 arm64 x86 x86_64 ppc64 ppc64le))
[Severity: Medium]
Will this filter correctly match the architecture when building via the
top-level make kselftest?
The top-level kernel build system evaluates SUBARCH using
scripts/subarch.include, which maps both ppc64 and ppc64le to the canonical
name powerpc, exporting ARCH=powerpc to sub-makes.
Because powerpc is not included in this filter list, the tests will still
be silently skipped during automated testing when invoked from the
top-level kernel directory.
> # Do nothing on unsupported architectures
> include ../lib.mk
> else
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703032806.40946-1-nnmlinux@linux.ibm.com?part=6
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
` (5 preceding siblings ...)
2026-07-03 3:28 ` [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le Narayana Murty N
@ 2026-07-03 8:28 ` Harsh Prateek Bora
6 siblings, 0 replies; 14+ messages in thread
From: Harsh Prateek Bora @ 2026-07-03 8:28 UTC (permalink / raw)
To: Narayana Murty N, alex, dmatlack, shuah, linuxppc-dev
Cc: amastro, rananta, kvm, linux-kselftest, linux-kernel, vaibhav,
sbhat
+ linuxppc-dev
On 03/07/26 8:58 am, Narayana Murty N wrote:
> This RFC adds PowerPC sPAPR TCE v2 support to VFIO selftests.
>
> The series adds a selftest IOMMU mode for the legacy VFIO container
> backend, adds helpers for default and dynamic DMA windows, and exercises
> the sPAPR DDW path through the DMA mapping tests.
>
> sPAPR TCE v2 remains a legacy VFIO container backend. This series does
> not add iommufd or VFIO cdev support for sPAPR.
>
> The main points are
> 1. add VFIO_SELFTESTS_IOMMU_MODE for selecting a backend
> 2. add vfio_spapr_tce_v2_iommu as the PowerPC VFIO backend
> 3. preserve the platform default DMA window
> 4. create and tear down only selftest-created DDWs
> 5. prepare the DMA window before IOVA allocation
> 6. exercise DDW creation for hugepage DMA mappings
> 7. accept sPAPR-specific errno for invalid DMA ranges
>
> Example:
>
> VFIO_SELFTESTS_IOMMU_MODE=vfio_spapr_tce_v2_iommu
> ./vfio_dma_mapping_test <BDF>
>
> Observed coverage includes anonymous mappings through the default window
> and 2MB hugetlb mappings through a DDW. 1GB hugetlb mappings may skip when
> the platform rejects the requested DDW characteristics.
>
> Feedback is requested from the VFIO and PowerPC communities on:
> 1. whether the sPAPR TCE v2 helpers should remain in the common VFIO
> selftest library or move into a sPAPR-specific test helper?
> 2. whether DDW setup through hugepage mappings is the right initial
> coverage?
> 3. whether the sPAPR-specific overflow errno expectation should be
> accepted, skipped, or hidden behind a backend helper?
> 4. whether PowerPC should generate only the sPAPR TCE v2 fixture variants,
> or keep the generic IOMMU-mode matrix and skip unsupported modes.
>
> TODO: vfio_spapr_tce_v1_iommu yet to be covered.
>
> Narayana Murty N (6):
> selftests/vfio: allow selecting IOMMU backend from environment
> selftests/vfio: add sPAPR TCE v2 IOMMU mode
> selftests/vfio: add sPAPR TCE v2 DMA window helpers
> selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings
> selftests/vfio: Accept sPAPR errno for DMA range overflow
> selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le
>
> .../selftests/vfio/lib/include/libvfio.h | 9 +
> .../vfio/lib/include/libvfio/iommu.h | 26 ++
> tools/testing/selftests/vfio/lib/iommu.c | 280 +++++++++++++++++-
> tools/testing/selftests/vfio/lib/libvfio.c | 37 +++
> .../selftests/vfio/vfio_dma_mapping_test.c | 30 ++
> .../selftests/vfio/vfio_pci_device_test.c | 4 +-
> tools/testing/selftests/vfio/Makefile | 2 +-
> 7 files changed, 382 insertions(+), 6 deletions(-)
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-07-03 8:28 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03 3:28 [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Narayana Murty N
2026-07-03 3:28 ` [RFC PATCH 1/6] selftests/vfio: allow selecting IOMMU backend from environment Narayana Murty N
2026-07-03 8:06 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 2/6] selftests/vfio: add sPAPR TCE v2 IOMMU mode Narayana Murty N
2026-07-03 8:09 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 3/6] selftests/vfio: add sPAPR TCE v2 DMA window helpers Narayana Murty N
2026-07-03 8:05 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 4/6] selftests/vfio: Exercise sPAPR DDW path for hugepage DMA mappings Narayana Murty N
2026-07-03 8:11 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 5/6] selftests/vfio: Accept sPAPR errno for DMA range overflow Narayana Murty N
2026-07-03 8:08 ` sashiko-bot
2026-07-03 3:28 ` [RFC PATCH 6/6] selftests/vfio: Enable VFIO selftests on ppc64 and ppc64le Narayana Murty N
2026-07-03 8:14 ` sashiko-bot
2026-07-03 8:28 ` [RFC PATCH 0/6] selftests/vfio: Add sPAPR TCE v2 coverage Harsh Prateek Bora
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox