mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH] remoteproc: core: add KUnit tests for rproc_check_carveout_da()
@ 2026-09-27 17:24 Sailesh Nandanavanam
  0 siblings, 0 replies; only message in thread
From: Sailesh Nandanavanam @ 2026-09-27 17:24 UTC (permalink / raw)
  To: andersson, mathieu.poirier
  Cc: linux-remoteproc, linux-kernel, Sailesh Nandanavanam

Add a KUnit test suite covering rproc_check_carveout_da(), the
internal helper that validates a resource-table-requested (da, len)
pair against an already-allocated carveout's bounds.

The test is #include'd directly into remoteproc_core.c (a pattern
already used by mm/damon/) rather than built as a separate module,
since rproc_check_carveout_da() is static and this avoids adding an
exported symbol purely for test visibility.

Six cases are included, exercising every branch of the function:
requested length exceeding the carveout, a specific da requested
against a carveout with none set, a da before the carveout's start,
a (da + len) past the carveout's end, an exact boundary fit, and the
FW_RSC_ADDR_ANY skip-check path.

Verified via:
 - QEMU (x86_64), booting a kernel with CONFIG_REMOTEPROC_KUNIT_TEST=y
 - tools/testing/kunit/kunit.py under UML

All 6 cases pass in both environments:

    # remoteproc_core: pass:6 fail:0 skip:0 total:6

This is posted as an RFC to check whether this structure (test
headers embedded per-file, DAMON-style) is the preferred approach for
remoteproc before expanding coverage to other files in the driver
(remoteproc_virtio.c, remoteproc_sysfs.c, etc.).

Signed-off-by: Sailesh Nandanavanam <saileshnandanavanam@gmail.com>
---
 drivers/remoteproc/Kconfig                    |  10 ++
 drivers/remoteproc/remoteproc_core.c          |   4 +
 .../remoteproc/tests/remoteproc_core-kunit.h  | 130 ++++++++++++++++++
 3 files changed, 144 insertions(+)
 create mode 100644 drivers/remoteproc/tests/remoteproc_core-kunit.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 5b56b2dcc725..dc5a8f483693 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -390,6 +390,16 @@ config XLNX_R5_REMOTEPROC
 
 	  It's safe to say N if not interested in using RPU r5f cores.
 
+config REMOTEPROC_KUNIT_TEST
+	bool "KUnit tests for remoteproc core" if !KUNIT_ALL_TESTS
+	depends on REMOTEPROC && KUNIT=y
+	default KUNIT_ALL_TESTS
+	help
+	  Enable KUnit tests for the remoteproc core, covering internal
+	  helpers such as carveout/address-translation logic.
+
+	  If unsure, say N.
+
 endif # REMOTEPROC
 
 endmenu
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 1ed406714849..4f0ad28305d2 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -2839,3 +2839,7 @@ static void __exit remoteproc_exit(void)
 module_exit(remoteproc_exit);
 
 MODULE_DESCRIPTION("Generic Remote Processor Framework");
+
+#if IS_ENABLED(CONFIG_REMOTEPROC_KUNIT_TEST)
+#include "tests/remoteproc_core-kunit.h"
+#endif
diff --git a/drivers/remoteproc/tests/remoteproc_core-kunit.h b/drivers/remoteproc/tests/remoteproc_core-kunit.h
new file mode 100644
index 000000000000..615a854fffbf
--- /dev/null
+++ b/drivers/remoteproc/tests/remoteproc_core-kunit.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _REMOTEPROC_CORE_KUNIT_H
+#define _REMOTEPROC_CORE_KUNIT_H
+
+#include <kunit/test.h>
+
+/*
+ * Tests for rproc_check_carveout_da().
+ *
+ * The function is static, so this header is #include'd directly at the
+ * bottom of remoteproc_core.c (see CONFIG_REMOTEPROC_KUNIT_TEST), giving
+ * it access to the symbol despite the lack of external linkage.
+ *
+ * rproc_check_carveout_da() only touches &rproc->dev for dev_err() on
+ * its failure paths, so a zeroed struct rproc is sufficient here -- no
+ * device registration needed. dev_err()'s formatting chain
+ * (dev_driver_string() -> "" on NULL driver/bus/class, dev_name() ->
+ * NULL on an unregistered device, and the kernel's own %s NULL guard
+ * in lib/vsprintf.c) is safe end-to-end against a bare zeroed device.
+ */
+
+static void rproc_test_check_carveout_len_exceeds(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/* mem->len = 0x100; request len 0x200 with no da constraint */
+	mem.da = FW_RSC_ADDR_ANY;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, FW_RSC_ADDR_ANY, 0x200);
+	KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+static void rproc_test_check_carveout_da_any_mismatch(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/* caller wants a specific da, but the carveout itself has none set */
+	mem.da = FW_RSC_ADDR_ANY;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, 0x1000, 0x50);
+	KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+static void rproc_test_check_carveout_da_negative_delta(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/* requested da (0x1000) lies before the carveout's da (0x2000) */
+	mem.da = 0x2000;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, 0x1000, 0x10);
+	KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+static void rproc_test_check_carveout_da_exceeds_end(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/* delta (0x80) + len (0x100) = 0x180, one byte over mem->len (0x100) -> 0x180 > 0x100 */
+	mem.da = 0x1000;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, 0x1080, 0x100);
+	KUNIT_EXPECT_EQ(test, ret, -EINVAL);
+}
+
+static void rproc_test_check_carveout_da_exact_fit(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/*
+	 * Boundary case: delta (0xf0) + len (0x10) == mem->len (0x100)
+	 * exactly. The check is "> mem->len", so this must pass -- this
+	 * is exactly the kind of edge an off-by-one would break.
+	 */
+	mem.da = 0x1000;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, 0x10f0, 0x10);
+	KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+static void rproc_test_check_carveout_da_any_skip_check(struct kunit *test)
+{
+	struct rproc rproc = { 0 };
+	struct rproc_mem_entry mem = { 0 };
+	int ret;
+
+	/*
+	 * da == FW_RSC_ADDR_ANY -> address check is skipped entirely,
+	 * only len is validated against mem->len.
+	 */
+	mem.da = 0x1000;
+	mem.len = 0x100;
+
+	ret = rproc_check_carveout_da(&rproc, &mem, FW_RSC_ADDR_ANY, 0x50);
+	KUNIT_EXPECT_EQ(test, ret, 0);
+}
+
+static struct kunit_case rproc_core_test_cases[] = {
+	KUNIT_CASE(rproc_test_check_carveout_len_exceeds),
+	KUNIT_CASE(rproc_test_check_carveout_da_any_mismatch),
+	KUNIT_CASE(rproc_test_check_carveout_da_negative_delta),
+	KUNIT_CASE(rproc_test_check_carveout_da_exceeds_end),
+	KUNIT_CASE(rproc_test_check_carveout_da_exact_fit),
+	KUNIT_CASE(rproc_test_check_carveout_da_any_skip_check),
+	{}
+};
+
+static struct kunit_suite rproc_core_test_suite = {
+	.name = "remoteproc_core",
+	.test_cases = rproc_core_test_cases,
+};
+
+kunit_test_suite(rproc_core_test_suite);
+
+#endif /* _REMOTEPROC_CORE_KUNIT_H */
-- 
2.34.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-27 17:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-27 17:24 [RFC PATCH] remoteproc: core: add KUnit tests for rproc_check_carveout_da() Sailesh Nandanavanam

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®