* [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode
@ 2026-11-03 0:22 David Matlack
2026-11-03 0:22 ` [PATCH v2 1/5] vfio: selftests: Automatically detect the IOMMU mode in iommu_init() David Matlack
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
This series makes the VFIO selftests library automatically detect which
IOMMU mode to use, rather than hardcoding iommufd as the default, and
makes tests skip, rather than fail, when the IOMMU mode they need is not
available. This was suggested by Sean while reviewing the KVM selftest
irq_test, which currently has to probe for the IOMMU mode itself [1].
iommufd is an optional feature, and VFIO's iommufd support additionally
requires CONFIG_VFIO_DEVICE_CDEV. On otherwise functional kernels that
only support the legacy VFIO container, the VFIO selftests (and
irq_test, when using a VFIO device) currently fail with an unhelpful
assert:
tools/testing/selftests/vfio/lib/iommu.c:448: Assertion Failure
Expression: iommu->iommufd > 0
Observed: 0xffffffffffffffff > 0
[errno: 2 - No such file or directory]
Patch 1 makes iommu_init(NULL) pick the most preferred IOMMU mode that is
available on the current system, and drops the global default_iommu_mode.
iommu_modes[] is now ordered by preference: iommufd, vfio_type1v2_iommu,
vfio_type1_iommu, iommufd_compat_type1v2, iommufd_compat_type1. A mode is
considered available if its container (or /dev/iommu) can be opened and,
for container modes, if VFIO_CHECK_EXTENSION reports support for the
mode's IOMMU type. iommufd mode additionally requires VFIO device cdevs.
Patch 2 adds iommu_mode_is_available(), iommu_mode_unavailable_msg(),
and SKIP_IF_IOMMU_MODE_UNAVAILABLE(), and uses them to skip tests when the
IOMMU mode they need is not available. Tests skip via the kselftest
harness's SKIP() rather than iommu_init() calling ksft_exit_skip(), since
the latter produces malformed TAP output when called from within a
harness test.
Patch 3 makes the VFIO selftests library print the names of all known
IOMMU modes when passed an unrecognized mode, and exposes the list via
iommu_mode_names().
Patch 4 converts irq_test to use the VFIO selftests library to pick the
IOMMU mode, and drops its probe_iommu_type().
Patch 5 lists the known IOMMU modes in irq_test's help output.
This series is based on vfio/next (vfio-v7.4-rc1).
v2:
- Print the known IOMMU modes when passed an unrecognized mode (patch 3)
[Sean]
- Print a helpful message when irq_test skips because the IOMMU mode
is not available (patch 4) [Sean]
- List the known IOMMU modes in irq_test's help output (patch 5)
- Add iommu_mode_unavailable_msg() so that the VFIO selftests and
irq_test print the same message when skipping, including "No IOMMU
mode is available. Is VFIO (or IOMMUFD) loaded and enabled?" when no
IOMMU mode is available (patches 1, 2, and 4)
v1: https://lore.kernel.org/kvm/20261029221710.1871112-1-dmatlack@google.com/
[1] https://lore.kernel.org/kvm/aiIG2L_KdPwuxYA1@google.com/
Testing
-----------------------------------------------------------------------
Tested in a QEMU VM with an emulated igb device behind an emulated Intel
IOMMU, bound to vfio-pci, on a kernel with CONFIG_IOMMUFD=y,
CONFIG_VFIO_DEVICE_CDEV=y, and CONFIG_VFIO_CONTAINER=y. To simulate
kernels with fewer IOMMU modes available, /dev/iommu and /dev/vfio/vfio
were deleted in the VM:
- All IOMMU modes available: All VFIO selftests pass. irq_test -d passes
using iommufd. irq_test -d -t bogus fails and lists the known modes.
- Only the legacy VFIO container available (/dev/iommu deleted): All
VFIO selftests pass, with the iommufd and iommufd_compat variants
skipped instead of failing. irq_test -d passes using
vfio_type1v2_iommu, and skips if -t iommufd is passed.
- No IOMMU mode available (/dev/iommu and /dev/vfio/vfio deleted):
vfio_pci_device_test, vfio_pci_driver_test, and irq_test -d all skip
with a message explaining why, and with well-formed TAP output.
David Matlack (5):
vfio: selftests: Automatically detect the IOMMU mode in iommu_init()
vfio: selftests: Skip tests when the IOMMU mode is not available
vfio: selftests: Print the known IOMMU modes on an unrecognized mode
KVM: selftests: Use VFIO selftests library to pick IOMMU mode in
irq_test
KVM: selftests: List the known IOMMU modes in irq_test's help output
tools/testing/selftests/kvm/irq_test.c | 23 +---
.../vfio/lib/include/libvfio/iommu.h | 38 +++++-
tools/testing/selftests/vfio/lib/iommu.c | 108 ++++++++++++++++--
.../vfio/vfio_dma_mapping_mmio_test.c | 2 +
.../selftests/vfio/vfio_dma_mapping_test.c | 4 +
.../vfio/vfio_pci_device_init_perf_test.c | 2 +
.../selftests/vfio/vfio_pci_device_test.c | 8 +-
.../selftests/vfio/vfio_pci_driver_test.c | 9 +-
.../selftests/vfio/vfio_pci_sriov_uapi_test.c | 4 +
9 files changed, 162 insertions(+), 36 deletions(-)
base-commit: 076d7e989cb69f6ded7d60f2a080eb909930061b
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/5] vfio: selftests: Automatically detect the IOMMU mode in iommu_init()
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
@ 2026-11-03 0:22 ` David Matlack
2026-11-03 0:22 ` [PATCH v2 2/5] vfio: selftests: Skip tests when the IOMMU mode is not available David Matlack
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
Automatically detect the IOMMU mode that is most likely to work on the
current system when iommu_init() is passed a NULL mode, rather than always
using iommufd. Drop the global default_iommu_mode and convert its users to
pass NULL to iommu_init().
iommufd is an optional feature, and VFIO's iommufd support additionally
requires CONFIG_VFIO_DEVICE_CDEV. Hardcoding iommufd as the default causes
tests to fail with an unhelpful assert on otherwise functional kernels
that only support the legacy VFIO container:
tools/testing/selftests/vfio/lib/iommu.c:448: Assertion Failure
Expression: iommu->iommufd > 0
Observed: 0xffffffffffffffff > 0
[errno: 2 - No such file or directory]
Order iommu_modes[] by preference and pick the first mode that is
available. Consider a mode available if its container (or /dev/iommu) can
be opened and, for container modes, if VFIO_CHECK_EXTENSION reports
support for the mode's IOMMU type. iommufd mode additionally requires VFIO
device cdevs. If no mode is available, fail with a message that explains
why.
Suggested-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/kvm/aiIG2L_KdPwuxYA1@google.com/
Signed-off-by: David Matlack <dmatlack@google.com>
---
.../vfio/lib/include/libvfio/iommu.h | 6 +-
tools/testing/selftests/vfio/lib/iommu.c | 68 ++++++++++++++++---
.../selftests/vfio/vfio_pci_device_test.c | 4 +-
.../selftests/vfio/vfio_pci_driver_test.c | 2 +-
4 files changed, 64 insertions(+), 16 deletions(-)
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
index e9a3386a4719..fb0a681ecc72 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
@@ -15,8 +15,6 @@ struct iommu_mode {
unsigned long iommu_type;
};
-extern const char *default_iommu_mode;
-
struct dma_region {
struct list_head link;
void *vaddr;
@@ -32,6 +30,10 @@ struct iommu {
struct list_head dma_regions;
};
+/*
+ * Pass NULL for iommu_mode to automatically pick the mode most likely to work
+ * on the current system.
+ */
struct iommu *iommu_init(const char *iommu_mode);
void iommu_cleanup(struct iommu *iommu);
diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
index b6f3c5c84e01..0393536370e7 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -20,14 +20,19 @@
#include "../../../kselftest.h"
#include <libvfio.h>
-const char *default_iommu_mode = MODE_IOMMUFD;
+/* Message to print when no IOMMU mode is available on the current system. */
+#define NO_IOMMU_MODE_AVAILABLE_MSG \
+ "No IOMMU mode is available. Is VFIO (or IOMMUFD) loaded and enabled?"
-/* Reminder: Keep in sync with FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(). */
+/*
+ * Ordered by preference, i.e. iommu_init(NULL) picks the first mode in this
+ * list that is available on the current system.
+ *
+ * Reminder: Keep in sync with FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES().
+ */
static const struct iommu_mode iommu_modes[] = {
{
- .name = MODE_VFIO_TYPE1_IOMMU,
- .container_path = "/dev/vfio/vfio",
- .iommu_type = VFIO_TYPE1_IOMMU,
+ .name = MODE_IOMMUFD,
},
{
.name = MODE_VFIO_TYPE1V2_IOMMU,
@@ -35,8 +40,8 @@ static const struct iommu_mode iommu_modes[] = {
.iommu_type = VFIO_TYPE1v2_IOMMU,
},
{
- .name = MODE_IOMMUFD_COMPAT_TYPE1,
- .container_path = "/dev/iommu",
+ .name = MODE_VFIO_TYPE1_IOMMU,
+ .container_path = "/dev/vfio/vfio",
.iommu_type = VFIO_TYPE1_IOMMU,
},
{
@@ -45,16 +50,56 @@ static const struct iommu_mode iommu_modes[] = {
.iommu_type = VFIO_TYPE1v2_IOMMU,
},
{
- .name = MODE_IOMMUFD,
+ .name = MODE_IOMMUFD_COMPAT_TYPE1,
+ .container_path = "/dev/iommu",
+ .iommu_type = VFIO_TYPE1_IOMMU,
},
};
-static const struct iommu_mode *lookup_iommu_mode(const char *iommu_mode)
+static bool iommu_mode_probe(const struct iommu_mode *mode)
+{
+ const char *path = mode->container_path ?: "/dev/iommu";
+ bool available;
+ int fd;
+
+ /* iommufd mode requires VFIO device cdevs (CONFIG_VFIO_DEVICE_CDEV). */
+ if (!mode->container_path && access("/dev/vfio/devices", F_OK))
+ return false;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ return false;
+
+ available = !mode->container_path ||
+ ioctl(fd, VFIO_CHECK_EXTENSION, mode->iommu_type) > 0;
+
+ close(fd);
+ return available;
+}
+
+/* Returns the most preferred IOMMU mode that is available, or NULL if none. */
+static const struct iommu_mode *iommu_mode_detect(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(iommu_modes); i++) {
+ if (iommu_mode_probe(&iommu_modes[i]))
+ return &iommu_modes[i];
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the IOMMU mode with the given name, or if iommu_mode is NULL, the
+ * most preferred IOMMU mode that is available (or NULL if none).
+ */
+static const struct iommu_mode *iommu_mode_lookup(const char *iommu_mode)
{
int i;
if (!iommu_mode)
- iommu_mode = default_iommu_mode;
+ return iommu_mode_detect();
for (i = 0; i < ARRAY_SIZE(iommu_modes); i++) {
if (strcmp(iommu_mode, iommu_modes[i].name))
@@ -425,7 +470,8 @@ struct iommu *iommu_init(const char *iommu_mode)
INIT_LIST_HEAD(&iommu->dma_regions);
- iommu->mode = lookup_iommu_mode(iommu_mode);
+ iommu->mode = iommu_mode_lookup(iommu_mode);
+ VFIO_ASSERT_NOT_NULL(iommu->mode, NO_IOMMU_MODE_AVAILABLE_MSG);
container_path = iommu->mode->container_path;
if (container_path) {
diff --git a/tools/testing/selftests/vfio/vfio_pci_device_test.c b/tools/testing/selftests/vfio/vfio_pci_device_test.c
index 93c11fd5e081..59a7c1f71804 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(NULL);
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(NULL);
self->device = vfio_pci_device_init(device_bdf, self->iommu);
}
diff --git a/tools/testing/selftests/vfio/vfio_pci_driver_test.c b/tools/testing/selftests/vfio/vfio_pci_driver_test.c
index 9538a3a436a6..f8f99ee6bb1a 100644
--- a/tools/testing/selftests/vfio/vfio_pci_driver_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_driver_test.c
@@ -255,7 +255,7 @@ static bool device_has_selftests_driver(const char *bdf)
struct iommu *iommu;
bool has_driver;
- iommu = iommu_init(default_iommu_mode);
+ iommu = iommu_init(NULL);
device = vfio_pci_device_init(device_bdf, iommu);
has_driver = !!device->driver.ops;
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/5] vfio: selftests: Skip tests when the IOMMU mode is not available
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
2026-11-03 0:22 ` [PATCH v2 1/5] vfio: selftests: Automatically detect the IOMMU mode in iommu_init() David Matlack
@ 2026-11-03 0:22 ` David Matlack
2026-11-03 0:22 ` [PATCH v2 3/5] vfio: selftests: Print the known IOMMU modes on an unrecognized mode David Matlack
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
Skip tests when the IOMMU mode they need is not available on the current
system, instead of failing. Add iommu_mode_is_available() to check whether
a given IOMMU mode (or, if NULL, any IOMMU mode) is available,
iommu_mode_unavailable_msg() to explain why a test is skipping, and
SKIP_IF_IOMMU_MODE_UNAVAILABLE() to skip a kselftest harness test if the
mode is not available.
On a kernel without iommufd, for example, all of the iommufd and
iommufd_compat test variants currently fail on an assert in iommu_init().
Skip them instead, with a message that explains why:
ok 33 vfio_pci_driver_test.iommufd.send_msi # SKIP IOMMU mode 'iommufd' is not available
Use SKIP_IF_IOMMU_MODE_UNAVAILABLE() in all tests that run across multiple
IOMMU modes, and in the tests that let the library pick the mode by
passing NULL to iommu_init(). Also skip vfio_pci_driver_test, which calls
iommu_init() from main() to probe the device, if no IOMMU mode is
available.
Skip from the test via the kselftest harness's SKIP(), rather than from
within iommu_init() via ksft_exit_skip(). ksft_exit_skip() is not aware of
the harness, and so would emit a bogus "1..0 # SKIP" plan line in the
middle of the TAP output, and the harness would report the reason for the
skip as "unknown".
Signed-off-by: David Matlack <dmatlack@google.com>
---
.../vfio/lib/include/libvfio/iommu.h | 31 ++++++++++++++++++-
tools/testing/selftests/vfio/lib/iommu.c | 20 ++++++++++++
.../vfio/vfio_dma_mapping_mmio_test.c | 2 ++
.../selftests/vfio/vfio_dma_mapping_test.c | 4 +++
.../vfio/vfio_pci_device_init_perf_test.c | 2 ++
.../selftests/vfio/vfio_pci_device_test.c | 4 +++
.../selftests/vfio/vfio_pci_driver_test.c | 7 +++++
.../selftests/vfio/vfio_pci_sriov_uapi_test.c | 4 +++
8 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
index fb0a681ecc72..f204c71494fe 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
@@ -32,11 +32,25 @@ struct iommu {
/*
* Pass NULL for iommu_mode to automatically pick the mode most likely to work
- * on the current system.
+ * on the current system. Use iommu_mode_is_available() to check that the mode
+ * is available before calling iommu_init(), e.g. to skip the test if not.
*/
struct iommu *iommu_init(const char *iommu_mode);
void iommu_cleanup(struct iommu *iommu);
+/*
+ * Returns true if the given IOMMU mode is usable on the current system. If
+ * iommu_mode is NULL, returns true if any IOMMU mode is usable.
+ */
+bool iommu_mode_is_available(const char *iommu_mode);
+
+/*
+ * Returns a message explaining that the given IOMMU mode (or, if iommu_mode is
+ * NULL, any IOMMU mode) is not available, e.g. for tests to print when
+ * skipping.
+ */
+const char *iommu_mode_unavailable_msg(const char *iommu_mode);
+
int __iommu_map(struct iommu *iommu, struct dma_region *region);
static inline void iommu_map(struct iommu *iommu, struct dma_region *region)
@@ -81,4 +95,19 @@ 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__)
+/*
+ * Skip the current kselftest harness test if the given IOMMU mode is not
+ * available on the current system, or if no IOMMU mode is available if
+ * _iommu_mode is NULL. Like SKIP(), statement is executed after marking the
+ * test as skipped (e.g. "return"), and this can be used anywhere SKIP() can be
+ * used.
+ */
+#define SKIP_IF_IOMMU_MODE_UNAVAILABLE(statement, _iommu_mode) do { \
+ const char *__iommu_mode = (_iommu_mode); \
+ \
+ if (!iommu_mode_is_available(__iommu_mode)) \
+ SKIP(statement, "%s", \
+ iommu_mode_unavailable_msg(__iommu_mode)); \
+} while (0)
+
#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 0393536370e7..526bb21f2766 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -111,6 +111,26 @@ static const struct iommu_mode *iommu_mode_lookup(const char *iommu_mode)
VFIO_FAIL("Unrecognized IOMMU mode: %s\n", iommu_mode);
}
+bool iommu_mode_is_available(const char *iommu_mode)
+{
+ if (!iommu_mode)
+ return iommu_mode_detect();
+
+ return iommu_mode_probe(iommu_mode_lookup(iommu_mode));
+}
+
+const char *iommu_mode_unavailable_msg(const char *iommu_mode)
+{
+ static char msg[128];
+
+ if (!iommu_mode)
+ return NO_IOMMU_MODE_AVAILABLE_MSG;
+
+ snprintf(msg, sizeof(msg), "IOMMU mode '%s' is not available",
+ iommu_mode);
+ return msg;
+}
+
int __iommu_hva2iova(struct iommu *iommu, void *vaddr, iova_t *iova)
{
struct dma_region *region;
diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c
index d7f25ef77671..add7d3881930 100644
--- a/tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c
+++ b/tools/testing/selftests/vfio/vfio_dma_mapping_mmio_test.c
@@ -64,6 +64,8 @@ FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES();
FIXTURE_SETUP(vfio_dma_mapping_mmio_test)
{
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
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);
diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
index 7d0de8c79de1..e42170aecf6e 100644
--- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
+++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
@@ -119,6 +119,8 @@ FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(anonymous_hugetlb_1gb, SZ_1G, MAP_HUGETLB |
FIXTURE_SETUP(vfio_dma_mapping_test)
{
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
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);
@@ -228,6 +230,8 @@ FIXTURE_SETUP(vfio_dma_map_limit_test)
iova_t last_iova;
u32 nranges;
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
/*
* Over-allocate mmap by double the size to provide enough backing vaddr
* for overflow tests
diff --git a/tools/testing/selftests/vfio/vfio_pci_device_init_perf_test.c b/tools/testing/selftests/vfio/vfio_pci_device_init_perf_test.c
index e1a54e153cd3..8a98c86096be 100644
--- a/tools/testing/selftests/vfio/vfio_pci_device_init_perf_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_device_init_perf_test.c
@@ -44,6 +44,8 @@ FIXTURE_SETUP(vfio_pci_device_init_perf_test)
{
int i;
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
self->iommu = iommu_init(variant->iommu_mode);
self->threads = calloc_assert(nr_devices, sizeof(self->threads[0]));
self->thread_args = calloc_assert(nr_devices, sizeof(self->thread_args[0]));
diff --git a/tools/testing/selftests/vfio/vfio_pci_device_test.c b/tools/testing/selftests/vfio/vfio_pci_device_test.c
index 59a7c1f71804..1b1baa1e1c85 100644
--- a/tools/testing/selftests/vfio/vfio_pci_device_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_device_test.c
@@ -29,6 +29,8 @@ FIXTURE(vfio_pci_device_test) {
FIXTURE_SETUP(vfio_pci_device_test)
{
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, NULL);
+
self->iommu = iommu_init(NULL);
self->device = vfio_pci_device_init(device_bdf, self->iommu);
}
@@ -121,6 +123,8 @@ FIXTURE_VARIANT_ADD(vfio_pci_irq_test, msix) {
FIXTURE_SETUP(vfio_pci_irq_test)
{
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, NULL);
+
self->iommu = iommu_init(NULL);
self->device = vfio_pci_device_init(device_bdf, self->iommu);
}
diff --git a/tools/testing/selftests/vfio/vfio_pci_driver_test.c b/tools/testing/selftests/vfio/vfio_pci_driver_test.c
index f8f99ee6bb1a..56178c25c2fd 100644
--- a/tools/testing/selftests/vfio/vfio_pci_driver_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_driver_test.c
@@ -80,6 +80,8 @@ FIXTURE_SETUP(vfio_pci_driver_test)
{
struct vfio_pci_driver *driver;
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
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);
@@ -270,6 +272,11 @@ int main(int argc, char *argv[])
{
device_bdf = vfio_selftests_get_bdf(&argc, argv);
+ if (!iommu_mode_is_available(NULL)) {
+ fprintf(stderr, "%s\n", iommu_mode_unavailable_msg(NULL));
+ return KSFT_SKIP;
+ }
+
if (!device_has_selftests_driver(device_bdf)) {
fprintf(stderr, "No driver found for device %s\n", device_bdf);
return KSFT_SKIP;
diff --git a/tools/testing/selftests/vfio/vfio_pci_sriov_uapi_test.c b/tools/testing/selftests/vfio/vfio_pci_sriov_uapi_test.c
index f3a018b8699d..32a1e651c815 100644
--- a/tools/testing/selftests/vfio/vfio_pci_sriov_uapi_test.c
+++ b/tools/testing/selftests/vfio/vfio_pci_sriov_uapi_test.c
@@ -90,6 +90,8 @@ FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(null_uuid, NULL);
FIXTURE_SETUP(vfio_pci_sriov_uapi_test)
{
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, variant->iommu_mode);
+
self->iommu = iommu_init(variant->iommu_mode);
self->pf_token = UUID_1;
@@ -163,6 +165,8 @@ TEST(failed_second_open_does_not_clobber_token)
struct iommu *iommu;
int ret;
+ SKIP_IF_IOMMU_MODE_UNAVAILABLE(return, MODE_IOMMUFD);
+
iommu = iommu_init(MODE_IOMMUFD);
/* Create and bind PF using UUID_1 */
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] vfio: selftests: Print the known IOMMU modes on an unrecognized mode
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
2026-11-03 0:22 ` [PATCH v2 1/5] vfio: selftests: Automatically detect the IOMMU mode in iommu_init() David Matlack
2026-11-03 0:22 ` [PATCH v2 2/5] vfio: selftests: Skip tests when the IOMMU mode is not available David Matlack
@ 2026-11-03 0:22 ` David Matlack
2026-11-03 0:22 ` [PATCH v2 4/5] KVM: selftests: Use VFIO selftests library to pick IOMMU mode in irq_test David Matlack
2026-11-03 0:22 ` [PATCH v2 5/5] KVM: selftests: List the known IOMMU modes in irq_test's help output David Matlack
4 siblings, 0 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
Print the names of all known IOMMU modes when iommu_init() is passed an
unrecognized IOMMU mode, and expose the list of names via
iommu_mode_names() so that tests can also print it, e.g. in their help
output.
Users can specify the IOMMU mode for some tests on the command line (e.g.
irq_test -t), and so a typo or unsupported mode should tell the user what
the valid options are rather than leaving them to go read the library.
Suggested-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/kvm/auit0kVkAaWcNUvk@google.com/
Signed-off-by: David Matlack <dmatlack@google.com>
---
.../vfio/lib/include/libvfio/iommu.h | 3 +++
tools/testing/selftests/vfio/lib/iommu.c | 20 ++++++++++++++++++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
index f204c71494fe..42d1de742c0c 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iommu.h
@@ -51,6 +51,9 @@ bool iommu_mode_is_available(const char *iommu_mode);
*/
const char *iommu_mode_unavailable_msg(const char *iommu_mode);
+/* Returns a comma-separated list of the names of all IOMMU modes. */
+const char *iommu_mode_names(void);
+
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 526bb21f2766..64614325c49b 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -90,6 +90,23 @@ static const struct iommu_mode *iommu_mode_detect(void)
return NULL;
}
+const char *iommu_mode_names(void)
+{
+ static char names[256];
+ int i, len = 0;
+
+ if (names[0])
+ return names;
+
+ for (i = 0; i < ARRAY_SIZE(iommu_modes); i++) {
+ len += snprintf(names + len, sizeof(names) - len, "%s%s",
+ i ? ", " : "", iommu_modes[i].name);
+ VFIO_ASSERT_LT(len, (int)sizeof(names));
+ }
+
+ return names;
+}
+
/*
* Returns the IOMMU mode with the given name, or if iommu_mode is NULL, the
* most preferred IOMMU mode that is available (or NULL if none).
@@ -108,7 +125,8 @@ static const struct iommu_mode *iommu_mode_lookup(const char *iommu_mode)
return &iommu_modes[i];
}
- VFIO_FAIL("Unrecognized IOMMU mode: %s\n", iommu_mode);
+ VFIO_FAIL("Unrecognized IOMMU mode: %s (known modes: %s)\n",
+ iommu_mode, iommu_mode_names());
}
bool iommu_mode_is_available(const char *iommu_mode)
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] KVM: selftests: Use VFIO selftests library to pick IOMMU mode in irq_test
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
` (2 preceding siblings ...)
2026-11-03 0:22 ` [PATCH v2 3/5] vfio: selftests: Print the known IOMMU modes on an unrecognized mode David Matlack
@ 2026-11-03 0:22 ` David Matlack
2026-11-03 0:22 ` [PATCH v2 5/5] KVM: selftests: List the known IOMMU modes in irq_test's help output David Matlack
4 siblings, 0 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
Use the VFIO selftests library to pick the IOMMU mode in irq_test and drop
probe_iommu_type(). Pass NULL to iommu_init() when the user does not
specify a mode with -t, and skip the test if the requested mode (or, if
NULL, any mode) is not available.
The VFIO selftests library now automatically picks the IOMMU mode that is
most likely to work on the current system, so there is no need for each
test to probe for a mode itself.
Suggested-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/kvm/aiIG2L_KdPwuxYA1@google.com/
Signed-off-by: David Matlack <dmatlack@google.com>
---
tools/testing/selftests/kvm/irq_test.c | 20 ++------------------
1 file changed, 2 insertions(+), 18 deletions(-)
diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
index 791e576c334c..8a345472df5f 100644
--- a/tools/testing/selftests/kvm/irq_test.c
+++ b/tools/testing/selftests/kvm/irq_test.c
@@ -148,22 +148,6 @@ static void kvm_set_empty_gsi_routing(struct kvm_vm *vm)
vm_ioctl(vm, KVM_SET_GSI_ROUTING, &routing);
}
-static const char *probe_iommu_type(void)
-{
- int io_fd;
-
- io_fd = open("/dev/iommu", O_RDONLY);
- if (io_fd >= 0) {
- close(io_fd);
- return MODE_IOMMUFD;
- }
-
- io_fd = __open_path_or_exit("/dev/vfio/vfio", O_RDONLY,
- "Is VFIO (or IOMMUFD) loaded and enabled?");
- close(io_fd);
- return MODE_VFIO_TYPE1_IOMMU;
-}
-
static void help(const char *name)
{
printf("Usage: %s [-a] [-d <segment:bus:device.function>] [-e] [-h] [-i nr_irqs] [-m] [-n] [-t iommu_type] [-v nr_vcpus] [-x]\n", name);
@@ -266,8 +250,8 @@ int main(int argc, char **argv)
}
if (device_bdf) {
- if (!iommu_type)
- iommu_type = probe_iommu_type();
+ __TEST_REQUIRE(iommu_mode_is_available(iommu_type), "%s",
+ iommu_mode_unavailable_msg(iommu_type));
iommu = iommu_init(iommu_type);
device = vfio_pci_device_init(device_bdf, iommu);
msix = vfio_setup_msi(device);
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 5/5] KVM: selftests: List the known IOMMU modes in irq_test's help output
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
` (3 preceding siblings ...)
2026-11-03 0:22 ` [PATCH v2 4/5] KVM: selftests: Use VFIO selftests library to pick IOMMU mode in irq_test David Matlack
@ 2026-11-03 0:22 ` David Matlack
4 siblings, 0 replies; 6+ messages in thread
From: David Matlack @ 2026-11-03 0:22 UTC (permalink / raw)
To: kvm, linux-kernel, linux-kselftest
Cc: Alex Williamson, David Matlack, Paolo Bonzini,
Sean Christopherson, Shuah Khan
List the names of all known IOMMU modes in the help output for irq_test's
-t option, using iommu_mode_names() from the VFIO selftests library, and
clarify that the IOMMU mode is auto-detected by default.
The help output currently claims that the only valid modes are
vfio_type1_iommu and iommufd, which was never true, and would get stale
any time a mode is added to the VFIO selftests library.
Signed-off-by: David Matlack <dmatlack@google.com>
---
tools/testing/selftests/kvm/irq_test.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/irq_test.c b/tools/testing/selftests/kvm/irq_test.c
index 8a345472df5f..ef69f9d7ac3d 100644
--- a/tools/testing/selftests/kvm/irq_test.c
+++ b/tools/testing/selftests/kvm/irq_test.c
@@ -159,7 +159,8 @@ static void help(const char *name)
printf("-i The number of IRQs to generate during the test\n");
printf("-m Pin target vCPU to random physical CPU before triggering interrupt\n");
printf("-n Deliver 50 percent of IRQs as non-maskable interrupts\n");
- printf("-t Override the IOMMU type to use (vfio_type1_iommu or iommufd)\n");
+ printf("-t Override the IOMMU mode to use instead of auto-detecting it (%s)\n",
+ iommu_mode_names());
printf("-v Number of vCPUS to run\n");
printf("-x Use xAPIC mode instead of x2APIC mode in the guest\n");
printf("\n");
--
2.56.0.385.gac671c819a-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-03 0:22 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 0:22 [PATCH v2 0/5] vfio: selftests: Automatically detect the IOMMU mode David Matlack
2026-11-03 0:22 ` [PATCH v2 1/5] vfio: selftests: Automatically detect the IOMMU mode in iommu_init() David Matlack
2026-11-03 0:22 ` [PATCH v2 2/5] vfio: selftests: Skip tests when the IOMMU mode is not available David Matlack
2026-11-03 0:22 ` [PATCH v2 3/5] vfio: selftests: Print the known IOMMU modes on an unrecognized mode David Matlack
2026-11-03 0:22 ` [PATCH v2 4/5] KVM: selftests: Use VFIO selftests library to pick IOMMU mode in irq_test David Matlack
2026-11-03 0:22 ` [PATCH v2 5/5] KVM: selftests: List the known IOMMU modes in irq_test's help output David Matlack
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®