From: Mostafa Saleh <smostafa@google.com>
To: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: robin.murphy@arm.com, will@kernel.org, joro@8bytes.org,
jgg@ziepe.ca, praan@google.com,
Mostafa Saleh <smostafa@google.com>,
Jason Gunthorpe <jgg@nvidia.com>
Subject: [PATCH v4 4/4] iommu/io-pgtable-arm-selftests: Use KUnit
Date: Mon, 22 Sep 2025 08:59:28 +0000 [thread overview]
Message-ID: <20250922090003.686704-5-smostafa@google.com> (raw)
In-Reply-To: <20250922090003.686704-1-smostafa@google.com>
Integrate the selftests as part of kunit.
Now instead of the test only being run at boot, it can run:
- With CONFIG_IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST=y
It will automatically run at boot as before.
- Otherwise with CONFIG_IOMMU_IO_PGTABLE_KUNIT_TEST=m:
1) on module load:
Once the module load the self test will run
# modprobe io-pgtable-arm-selftests
2) debugfs
With CONFIG_KUNIT_DEBUGFS=y You can run the test with
# echo 1 > /sys/kernel/debug/kunit/io-pgtable-arm-test/run
3) Using kunit.py
You can also use the helper script which uses Qemu in the background
# ./tools/testing/kunit/kunit.py run --build_dir build_kunit_arm64 --arch arm64 \
--make_options LLVM=1 --kunitconfig ./kunit/kunitconfig
[18:01:09] ============= io-pgtable-arm-test (1 subtest) ==============
[18:01:09] [PASSED] arm_lpae_do_selftests
[18:01:09] =============== [PASSED] io-pgtable-arm-test ===============
[18:01:09] ============================================================
Suggested-by: Jason Gunthorpe <jgg@ziepe.ca>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
drivers/iommu/Kconfig | 11 ++--
drivers/iommu/Makefile | 2 +-
drivers/iommu/io-pgtable-arm-selftests.c | 82 +++++++++++++-----------
3 files changed, 51 insertions(+), 44 deletions(-)
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 553522ef3ca9..d50685433347 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -40,12 +40,13 @@ config IOMMU_IO_PGTABLE_LPAE
sizes at both stage-1 and stage-2, as well as address spaces
up to 48-bits in size.
-config IOMMU_IO_PGTABLE_LPAE_SELFTEST
- tristate "LPAE selftests"
- depends on IOMMU_IO_PGTABLE_LPAE
+config IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST
+ tristate "KUnit tests for LPAE"
+ depends on IOMMU_IO_PGTABLE_LPAE && KUNIT
+ default KUNIT_ALL_TESTS
help
- Enable self-tests for LPAE page table allocator. This performs
- a series of page-table consistency checks during boot.
+ Enable kunit tests for LPAE page table allocator. This performs
+ a series of page-table consistency checks.
If unsure, say N here.
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 5250a2eea13f..ac3851570303 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
-obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST) += io-pgtable-arm-selftests.o
+obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST) += io-pgtable-arm-selftests.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_DART) += io-pgtable-dart.o
obj-$(CONFIG_IOMMU_IOVA) += iova.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
diff --git a/drivers/iommu/io-pgtable-arm-selftests.c b/drivers/iommu/io-pgtable-arm-selftests.c
index 50350e88d9b4..fc18bd54a315 100644
--- a/drivers/iommu/io-pgtable-arm-selftests.c
+++ b/drivers/iommu/io-pgtable-arm-selftests.c
@@ -6,7 +6,8 @@
*
* Author: Will Deacon <will.deacon@arm.com>
*/
-#include <linux/device/faux.h>
+#include <kunit/device.h>
+#include <kunit/test.h>
#include <linux/io-pgtable.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -48,13 +49,14 @@ static void arm_lpae_dump_ops(struct io_pgtable_ops *ops)
cfg->pgsize_bitmap, cfg->ias, cfg->oas);
}
-#define __FAIL(ops, i) ({ \
- WARN(1, "selftest: test failed for fmt idx %d\n", (i)); \
- arm_lpae_dump_ops(ops); \
- -EFAULT; \
+#define __FAIL(test, ops, i) ({ \
+ KUNIT_FAIL(test, ""); \
+ kunit_err(test, "selftest: test failed for fmt idx %d\n", (i)); \
+ arm_lpae_dump_ops(ops); \
+ -EFAULT; \
})
-static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
+static int arm_lpae_run_tests(struct kunit *test, struct io_pgtable_cfg *cfg)
{
static const enum io_pgtable_fmt fmts[] = {
ARM_64_LPAE_S1,
@@ -70,7 +72,7 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
cfg_cookie = cfg;
ops = alloc_io_pgtable_ops(fmts[i], cfg, cfg);
if (!ops) {
- pr_err("selftest: failed to allocate io pgtable ops\n");
+ kunit_err(test, "selftest: failed to allocate io pgtable ops\n");
return -ENOMEM;
}
@@ -79,13 +81,13 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
* Empty page tables shouldn't provide any translations.
*/
if (ops->iova_to_phys(ops, 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->iova_to_phys(ops, SZ_1G + 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->iova_to_phys(ops, SZ_2G + 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
/*
* Distinct mappings of different granule sizes.
@@ -98,16 +100,16 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
IOMMU_READ | IOMMU_WRITE |
IOMMU_NOEXEC | IOMMU_CACHE,
GFP_KERNEL, &mapped))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
/* Overlapping mappings */
if (!ops->map_pages(ops, iova, iova + size, size, 1,
IOMMU_READ | IOMMU_NOEXEC,
GFP_KERNEL, &mapped))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
iova += SZ_1G;
}
@@ -118,18 +120,18 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
size = 1UL << j;
if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->iova_to_phys(ops, iova + 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
/* Remap full block */
if (ops->map_pages(ops, iova, iova, size, 1,
IOMMU_WRITE, GFP_KERNEL, &mapped))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
iova += SZ_1G;
}
@@ -145,11 +147,11 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
IOMMU_READ | IOMMU_WRITE |
IOMMU_NOEXEC | IOMMU_CACHE,
GFP_KERNEL, &mapped))
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (mapped != size)
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
- return __FAIL(ops, i);
+ return __FAIL(test, ops, i);
free_io_pgtable_ops(ops);
}
@@ -157,7 +159,7 @@ static int arm_lpae_run_tests(struct io_pgtable_cfg *cfg)
return 0;
}
-static int arm_lpae_do_selftests(void)
+static void arm_lpae_do_selftests(struct kunit *test)
{
static const unsigned long pgsize[] = {
SZ_4K | SZ_2M | SZ_1G,
@@ -170,18 +172,19 @@ static int arm_lpae_do_selftests(void)
};
int i, j, k, pass = 0, fail = 0;
- struct faux_device *dev;
+ struct device *dev;
struct io_pgtable_cfg cfg = {
.tlb = &dummy_tlb_ops,
.coherent_walk = true,
.quirks = IO_PGTABLE_QUIRK_NO_WARN,
};
- dev = faux_device_create("io-pgtable-test", NULL, 0);
- if (!dev)
- return -ENOMEM;
+ dev = kunit_device_register(test, "io-pgtable-test");
+ KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
+ if (IS_ERR_OR_NULL(dev))
+ return;
- cfg.iommu_dev = &dev->dev;
+ cfg.iommu_dev = dev;
for (i = 0; i < ARRAY_SIZE(pgsize); ++i) {
for (j = 0; j < ARRAY_SIZE(address_size); ++j) {
@@ -190,9 +193,9 @@ static int arm_lpae_do_selftests(void)
cfg.pgsize_bitmap = pgsize[i];
cfg.ias = address_size[k];
cfg.oas = address_size[j];
- pr_info("selftest: pgsize_bitmap 0x%08lx, IAS %u OAS %u\n",
- pgsize[i], cfg.ias, cfg.oas);
- if (arm_lpae_run_tests(&cfg))
+ kunit_info(test, "selftest: pgsize_bitmap 0x%08lx, IAS %u OAS %u\n",
+ pgsize[i], cfg.ias, cfg.oas);
+ if (arm_lpae_run_tests(test, &cfg))
fail++;
else
pass++;
@@ -200,17 +203,20 @@ static int arm_lpae_do_selftests(void)
}
}
- pr_info("selftest: completed with %d PASS %d FAIL\n", pass, fail);
- faux_device_destroy(dev);
-
- return fail ? -EFAULT : 0;
+ kunit_info(test, "selftest: completed with %d PASS %d FAIL\n", pass, fail);
}
-static void arm_lpae_exit_selftests(void)
-{
-}
+static struct kunit_case io_pgtable_arm_test_cases[] = {
+ KUNIT_CASE(arm_lpae_do_selftests),
+ {},
+};
+
+static struct kunit_suite io_pgtable_arm_test = {
+ .name = "io-pgtable-arm-test",
+ .test_cases = io_pgtable_arm_test_cases,
+};
+
+kunit_test_suite(io_pgtable_arm_test);
-subsys_initcall(arm_lpae_do_selftests);
-module_exit(arm_lpae_exit_selftests);
MODULE_DESCRIPTION("io-pgtable-arm library selftest");
MODULE_LICENSE("GPL");
--
2.51.0.534.gc79095c0ca-goog
next prev parent reply other threads:[~2025-09-22 9:00 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-22 8:59 [PATCH v4 0/4] Move io-pgtable-arm selftest to KUnit Mostafa Saleh
2025-09-22 8:59 ` [PATCH v4 1/4] iommu/io-pgtable-arm: Simplify error prints for selftests Mostafa Saleh
2025-09-22 13:30 ` Jason Gunthorpe
2025-09-23 19:02 ` Pranjal Shrivastava
2025-09-22 8:59 ` [PATCH v4 2/4] iommu/io-pgtable-arm: Move selftests to a separate file Mostafa Saleh
2025-09-22 13:30 ` Jason Gunthorpe
2025-09-23 19:04 ` Pranjal Shrivastava
2025-09-22 8:59 ` [PATCH v4 3/4] iommu/io-pgtable-arm-selftests: Modularize the test Mostafa Saleh
2025-09-23 19:05 ` Pranjal Shrivastava
2025-09-22 8:59 ` Mostafa Saleh [this message]
2025-09-23 19:34 ` [PATCH v4 4/4] iommu/io-pgtable-arm-selftests: Use KUnit Pranjal Shrivastava
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=20250922090003.686704-5-smostafa@google.com \
--to=smostafa@google.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=praan@google.com \
--cc=robin.murphy@arm.com \
--cc=will@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.