* [PATCH v4 0/2] support kselftest on nommu platform
@ 2026-09-29 23:57 Hajime Tazaki
2026-09-29 23:57 ` [PATCH v4 1/2] selftests: run tests on nommu architecture Hajime Tazaki
2026-09-29 23:57 ` [PATCH v4 2/2] selftests/nommu: add nommu mmap and mremap behavior tests Hajime Tazaki
0 siblings, 2 replies; 14+ messages in thread
From: Hajime Tazaki @ 2026-09-29 23:57 UTC (permalink / raw)
To: linux-mm, liam, rbm, akpm, luto, brendan.jackman, david,
liuhangbin, corbet, kees, ljs, broonie, mhocko, rppt, shuah,
surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um
Cc: geert, daniel, Hajime Tazaki
This patchset adds an ability to execute kselftest on nommu platforms.
Currently there are several issues if we wish to run kselftests on nommu
targets:
- it cannot compile/build test binaries because the current files mainly
assume to build with glibc,
- some of the tests are not able to run on nommu targets as there are no
fork(2) syscall.
The first issue can be avoided if we can build static PIE binaries (if
targets support it), but in our case (build on ubuntu/glibc and run on
alpine/musl-libc), it fails to invoke due to lack of the GNU ifunc
mechanism. Thus, we need to cross-compile with musl toolchain, which
needs to be solved the first issue.
The second issue is the lack of fork(2) syscall on those platforms.
Especially the test harness helper (kselftest_harness.h) uses the
syscall, which cannot be simply with vfork(2). `timeout` command used
in `runner.sh` never works for nommu platform as it uses fork(2).
nommu component in the mm subsystem has several known issues and having
test cases should help this situation, thus this patchset is very first
step toward enriching test environment which has not been well tested
for a while. The test cases is implemented based on the document
(Documentation/admin-guide/mm/nommu-mmap.rst).
Initial shape for this patches is implemented as an opt-in TARGET, not
built/invoked automatically if users don't specify this nommu target.
- v3:
https://lore.kernel.org/linux-mm/20260926010819.604346-1-thehajime@gmail.com/
- v2:
https://lore.kernel.org/linux-mm/20260825015945.141739-1-thehajime@gmail.com/
- rfc:
https://lore.kernel.org/linux-mm/20260813063401.1786548-1-thehajime@gmail.com/
Hajime Tazaki (2):
selftests: run tests on nommu architecture
selftests/nommu: add nommu mmap and mremap behavior tests
Documentation/dev-tools/kselftest.rst | 14 +
tools/testing/selftests/kselftest/runner.sh | 6 +-
tools/testing/selftests/nommu/Makefile | 8 +
tools/testing/selftests/nommu/local.mk | 7 +
.../testing/selftests/nommu/nommu_mmap_test.c | 261 +++++++++++++
.../selftests/nommu/nommu_mremap_test.c | 366 ++++++++++++++++++
6 files changed, 661 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/nommu/Makefile
create mode 100644 tools/testing/selftests/nommu/local.mk
create mode 100644 tools/testing/selftests/nommu/nommu_mmap_test.c
create mode 100644 tools/testing/selftests/nommu/nommu_mremap_test.c
base-commit: e8d0f6a1b2a447d02845984fa6288787543cb03c
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-09-29 23:57 [PATCH v4 0/2] support kselftest on nommu platform Hajime Tazaki
@ 2026-09-29 23:57 ` Hajime Tazaki
2026-09-30 9:17 ` Lorenzo Stoakes (ARM)
2026-10-01 7:08 ` David Hildenbrand (Arm)
2026-09-29 23:57 ` [PATCH v4 2/2] selftests/nommu: add nommu mmap and mremap behavior tests Hajime Tazaki
1 sibling, 2 replies; 14+ messages in thread
From: Hajime Tazaki @ 2026-09-29 23:57 UTC (permalink / raw)
To: linux-mm, liam, rbm, akpm, luto, brendan.jackman, david,
liuhangbin, corbet, kees, ljs, broonie, mhocko, rppt, shuah,
surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um
Cc: geert, daniel, Hajime Tazaki
Architectures lacking MMU don't support fork(2) syscall and only
vfork(2) is available with limitations. Thus, we cannot run kselftest
on nommu architecture as is.
This commit addresses this issue with the following changes:
- on test run stage, avoid calling timeout command when NOMMU=1 variable
added to environmental variable, since timeout command uses fork
syscall which nommu platform doesn't support.
- describe the difference of nommu tests in the document.
So command line to build/execute tests for nommu should be like below:
$ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
$ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
$ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
-c nommu
Cc: Shuah Khan <shuah@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Kees Cook <kees@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Will Drewry <wad@chromium.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Brendan Jackman <brendan.jackman@linux.dev>
Cc: Hangbin Liu <liuhangbin@gmail.com>
Cc: "Ricardo B. Marliere" <rbm@suse.com>
Cc: linux-kselftest@vger.kernel.org
Cc: linux-um@lists.infradead.org
Cc: linux-mm@kvack.org
Cc: linux-doc@vger.kernel.org
Closes: https://sashiko.dev/#/patchset/20260813063401.1786548-1-thehajime%40gmail.com
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
--
v3 => v4
- fix typos in commit message
v2 => v3
- remove unnecessary modification
- new target is moved from TARGETS=mm/nommu to TARGETS=nommu
- rename CONFIG_NOMMU to NOMMU to avoid confusion to kernel config
rfc => v2
- reformat ktap header, reported by Sashiko review
- https://lore.kernel.org/linux-mm/20260825015945.141739-2-thehajime@gmail.com/
rfc: https://lore.kernel.org/linux-mm/20260813063401.1786548-1-thehajime@gmail.com/
---
Documentation/dev-tools/kselftest.rst | 14 ++++++++++++++
tools/testing/selftests/kselftest/runner.sh | 6 +++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index 64c0ec7428a2..c35b819947b7 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -230,6 +230,20 @@ section::
.. _tar's auto-compress: https://www.gnu.org/software/tar/manual/html_node/gzip.html#auto_002dcompress
+Build and test on nommu target
+==============================
+
+If you (cross-)build kselftests for nommu targets, or run tests on nommu targets, use
+``NOMMU=1`` as a make variable/environment setting to tell build system to do the additional
+checks. These nommu targets may differ in several ways, such as not supporting fork(2) or
+using musl or another libc. Set this variable to apply the necessary build and test adjustments.
+
+::
+
+ $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu # <= build-only
+ $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
+ $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p -c nommu
+
Contributing new tests
======================
diff --git a/tools/testing/selftests/kselftest/runner.sh b/tools/testing/selftests/kselftest/runner.sh
index 311811dc55a0..ee2c1f0403d9 100644
--- a/tools/testing/selftests/kselftest/runner.sh
+++ b/tools/testing/selftests/kselftest/runner.sh
@@ -38,8 +38,12 @@ tap_prefix()
tap_timeout()
{
+ # nommu doesn't support timeout command (missing fork(2))
+ if [ "$NOMMU" = "1" ] ; then
+ echo "timeout isn't supported for NOMMU"
+ $1
# Make sure tests will time out if utility is available.
- if [ -x /usr/bin/timeout ] ; then
+ elif [ -x /usr/bin/timeout ] ; then
/usr/bin/timeout --foreground "$kselftest_timeout" \
/usr/bin/timeout "$kselftest_timeout" $1
else
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v4 2/2] selftests/nommu: add nommu mmap and mremap behavior tests
2026-09-29 23:57 [PATCH v4 0/2] support kselftest on nommu platform Hajime Tazaki
2026-09-29 23:57 ` [PATCH v4 1/2] selftests: run tests on nommu architecture Hajime Tazaki
@ 2026-09-29 23:57 ` Hajime Tazaki
1 sibling, 0 replies; 14+ messages in thread
From: Hajime Tazaki @ 2026-09-29 23:57 UTC (permalink / raw)
To: linux-mm, liam, rbm, akpm, luto, brendan.jackman, david,
liuhangbin, corbet, kees, ljs, broonie, mhocko, rppt, shuah,
surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um
Cc: geert, daniel, Hajime Tazaki
Introduce a kselftest utility to validate memory mapping capabilities
under nommu kernels, aligned with
Documentation/admin-guide/mm/nommu-mmap.rst.
The test implements basic checks into a generic architecture-agnostic
test matrix applicable across nommu targets. It evaluates:
1. MAP_FIXED allocation rejections.
2. Standard MAP_PRIVATE and MAP_ANONYMOUS allocation resilience.
3. Regular file mappings via standard filesystem storage.
4. Block device subsystem mappings (gracefully skipping if node is
missing).
5. Shared vs Private backing discrepancies under nommu conditions.
6. mremap limits, ensuring non-expandable restrictions behave properly.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-um@lists.infradead.org
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260825015945.141739-1-thehajime@gmail.com
Assisted-by: Gemini:Pro [AI_Reviewer] [Sashiko_Linter]
Assisted-by: cubic.dev:unspecified
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
--
v3 => v4
- clean up messages
v2 => v3
- remove unnecessary modifications
- address Sashiko review
rfc => v2
- prepare a different TARGETS for tests (mm/nommu)
- drop shrink fix tests
- drop mmap /dev/zero tests
- https://lore.kernel.org/linux-mm/20260825015945.141739-3-thehajime@gmail.com/
rfc:
- https://lore.kernel.org/linux-mm/20260813063401.1786548-1-thehajime@gmail.com/
---
tools/testing/selftests/nommu/Makefile | 8 +
tools/testing/selftests/nommu/local.mk | 7 +
.../testing/selftests/nommu/nommu_mmap_test.c | 261 +++++++++++++
.../selftests/nommu/nommu_mremap_test.c | 366 ++++++++++++++++++
4 files changed, 642 insertions(+)
create mode 100644 tools/testing/selftests/nommu/Makefile
create mode 100644 tools/testing/selftests/nommu/local.mk
create mode 100644 tools/testing/selftests/nommu/nommu_mmap_test.c
create mode 100644 tools/testing/selftests/nommu/nommu_mremap_test.c
diff --git a/tools/testing/selftests/nommu/Makefile b/tools/testing/selftests/nommu/Makefile
new file mode 100644
index 000000000000..8e7cd7315c53
--- /dev/null
+++ b/tools/testing/selftests/nommu/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for nommu selftests
+
+TEST_GEN_PROGS += nommu_mmap_test
+TEST_GEN_PROGS += nommu_mremap_test
+
+include ../lib.mk
+include local.mk
diff --git a/tools/testing/selftests/nommu/local.mk b/tools/testing/selftests/nommu/local.mk
new file mode 100644
index 000000000000..0bd1300f00f4
--- /dev/null
+++ b/tools/testing/selftests/nommu/local.mk
@@ -0,0 +1,7 @@
+# detect if users request NOMMU build or not
+# User can set NOMMU to 1 to build/test for NOMMU platforms
+NOMMU ?= 0
+ifeq ($(NOMMU),1)
+CFLAGS += -DNOMMU
+export NOMMU
+endif
diff --git a/tools/testing/selftests/nommu/nommu_mmap_test.c b/tools/testing/selftests/nommu/nommu_mmap_test.c
new file mode 100644
index 000000000000..a1f5fdda554a
--- /dev/null
+++ b/tools/testing/selftests/nommu/nommu_mmap_test.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include "kselftest.h"
+
+#include <sys/vfs.h>
+#ifndef RAMFS_MAGIC
+#define RAMFS_MAGIC 0x858458f6
+#endif
+
+static size_t ps;
+
+struct test_case_t {
+ const char *name;
+ const char *pathname;
+ int open_flags;
+ int mmap_prot;
+ int mmap_flags;
+ int exp_err;
+ int (*resolve_exp_err)(const char *path);
+};
+
+static int get_shm_expected_error(const char *path)
+{
+ struct statfs fs;
+
+ if (statfs(path, &fs) == 0) {
+ if (fs.f_type == RAMFS_MAGIC)
+ return 0; /* ramfs succeed with contiguous memory */
+ }
+ /* hostfs, etc returns ENODEV due to lack of contiguous allocation */
+ return ENODEV;
+}
+
+static struct test_case_t test_cases[] = {
+ {
+ .name = "anonymous private allocation",
+ .pathname = NULL,
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ | PROT_WRITE,
+ .mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE,
+ .exp_err = 0,
+ .resolve_exp_err = NULL,
+ },
+ {
+ .name = "non-anonymous private file mapping (rw-)",
+ .pathname = "/tmp/ksft.nommu-reg-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ | PROT_WRITE,
+ .mmap_flags = MAP_PRIVATE,
+ .exp_err = 0,
+ .resolve_exp_err = NULL,
+ },
+ {
+ .name = "non-anonymous private file mapping (r--)",
+ .pathname = "/tmp/ksft.nommu-reg-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_PRIVATE,
+ .exp_err = 0,
+ .resolve_exp_err = NULL,
+ },
+ {
+ .name = "non-anonymous shared file mapping (rw-)",
+ .pathname = "/tmp/ksft.nommu-shm-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ | PROT_WRITE,
+ .mmap_flags = MAP_SHARED,
+ .exp_err = 0,
+#ifdef NOMMU
+ .resolve_exp_err = get_shm_expected_error,
+#else
+ .resolve_exp_err = NULL,
+#endif
+ },
+ {
+ .name = "non-anonymous shared file mapping (r--)",
+ .pathname = "/tmp/ksft.nommu-shm-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_SHARED,
+ .exp_err = 0,
+#ifdef NOMMU
+ .resolve_exp_err = get_shm_expected_error,
+#else
+ .resolve_exp_err = 0,
+#endif
+ },
+};
+
+static int run_mapping_matrix_test(struct test_case_t *tcase)
+{
+ int fd;
+ void *ptr;
+ char path_buf[PATH_MAX];
+ const char *path = tcase->pathname;
+ int rc = KSFT_PASS;
+ int expected_error;
+
+ ksft_print_msg("[RUN] %s\n", tcase->name);
+
+ if (tcase->pathname == NULL) {
+ fd = -1;
+ } else if (strstr(tcase->pathname, "XXXXXX")) {
+ strncpy(path_buf, tcase->pathname, sizeof(path_buf) - 1);
+ path_buf[sizeof(path_buf) - 1] = '\0';
+ fd = mkstemp(path_buf);
+ if (fd < 0) {
+ ksft_print_msg("Failed to setup temp node: %s\n",
+ tcase->pathname);
+ ksft_test_result_skip("%s\n", tcase->name);
+ return KSFT_SKIP;
+ }
+ if (ftruncate(fd, ps) != 0) {
+ ksft_print_msg("ftruncate failed for: %s\n", tcase->pathname);
+ ksft_test_result_fail("%s\n", tcase->name);
+ close(fd);
+ unlink(path_buf);
+ return KSFT_FAIL;
+ }
+ path = path_buf;
+ } else {
+ fd = open(tcase->pathname, tcase->open_flags, 0600);
+ if (fd < 0) {
+ ksft_print_msg("Device node not accessible: %s\n",
+ tcase->pathname);
+ ksft_test_result_skip("%s\n", tcase->name);
+ return KSFT_SKIP;
+ }
+ }
+
+ expected_error = tcase->exp_err;
+ if (tcase->resolve_exp_err && fd >= 0)
+ expected_error = tcase->resolve_exp_err(path);
+
+ ptr = mmap(NULL, ps, tcase->mmap_prot, tcase->mmap_flags, fd, 0);
+
+ if (expected_error != 0) {
+ if (ptr != MAP_FAILED) {
+ ksft_print_msg("mmap unexpectedly succeeded (exp error %d)\n",
+ expected_error);
+ ksft_test_result_fail("%s\n", tcase->name);
+ munmap(ptr, ps);
+ rc = KSFT_FAIL;
+ goto cleanup;
+ }
+ if (errno != expected_error) {
+ ksft_print_msg("mmap failed with %d (%s), but expected %d\n",
+ errno, strerror(errno), expected_error);
+ ksft_test_result_fail("%s\n", tcase->name);
+ rc = KSFT_FAIL;
+ goto cleanup;
+ }
+ ksft_print_msg("Correctly rejected with expected error %s(%d)\n",
+ strerror(expected_error), expected_error);
+ ksft_test_result_pass("%s\n", tcase->name);
+ rc = KSFT_PASS;
+ goto cleanup;
+ }
+
+ if (ptr == MAP_FAILED) {
+ ksft_print_msg("mmap failed unexpectedly: %s\n", strerror(errno));
+ ksft_test_result_fail("%s\n", tcase->name);
+ rc = KSFT_FAIL;
+ goto cleanup;
+ }
+
+ ksft_test_result_pass("%s\n", tcase->name);
+ munmap(ptr, ps);
+
+cleanup:
+ if (fd >= 0) {
+ close(fd);
+ if (tcase->pathname && strstr(tcase->pathname, "XXXXXX"))
+ unlink(path_buf);
+ }
+ return rc;
+}
+
+static int test_map_fixed(void)
+{
+ void *fixed_addr;
+ void *ptr;
+
+ ksft_print_msg("[RUN] %s\n", __func__);
+
+ fixed_addr = mmap(NULL, ps, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (fixed_addr == MAP_FAILED) {
+ ksft_print_msg("Unable to reserve test address: %s\n",
+ strerror(errno));
+ ksft_test_result_skip("MAP_FIXED behavior\n");
+ return KSFT_SKIP;
+ }
+
+ if (munmap(fixed_addr, ps)) {
+ ksft_print_msg("Unable to release test address: %s\n",
+ strerror(errno));
+ ksft_test_result_fail("MAP_FIXED behavior\n");
+ return KSFT_FAIL;
+ }
+
+ ptr = mmap(fixed_addr, ps, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+#ifdef NOMMU
+ if (ptr == MAP_FAILED && (errno == ENODEV || errno == EINVAL)) {
+ ksft_print_msg("MAP_FIXED correctly rejected under nommu\n");
+ ksft_test_result_pass("MAP_FIXED behavior\n");
+ return KSFT_PASS;
+ }
+ if (ptr != MAP_FAILED) {
+ ksft_print_msg("MAP_FIXED unexpectedly allowed under nommu\n");
+ ksft_test_result_fail("MAP_FIXED behavior\n");
+ munmap(ptr, ps);
+ return KSFT_FAIL;
+ }
+ ksft_print_msg("MAP_FIXED failed under NOMMU: %s\n",
+ strerror(errno));
+ ksft_test_result_fail("MAP_FIXED behavior\n");
+ return KSFT_FAIL;
+#else
+ if (ptr != MAP_FAILED) {
+ ksft_print_msg("MAP_FIXED successfully allocated under MMU\n");
+ ksft_test_result_pass("MAP_FIXED behavior\n");
+ munmap(ptr, ps);
+ return KSFT_PASS;
+ }
+ ksft_print_msg("MAP_FIXED failed allocation under MMU\n");
+ ksft_test_result_fail("MAP_FIXED behavior\n");
+ return KSFT_FAIL;
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ ps = sysconf(_SC_PAGESIZE);
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(test_cases) + 1);
+
+#ifdef NOMMU
+ ksft_print_msg("Running strict MMAP test criteria under nommu architecture\n");
+#else
+ ksft_print_msg("Running MMAP test criteria under MMU architecture\n");
+#endif
+
+ test_map_fixed();
+ for (i = 0; i < (int)ARRAY_SIZE(test_cases); i++)
+ run_mapping_matrix_test(&test_cases[i]);
+
+ ksft_finished();
+}
diff --git a/tools/testing/selftests/nommu/nommu_mremap_test.c b/tools/testing/selftests/nommu/nommu_mremap_test.c
new file mode 100644
index 000000000000..7ccdf65b675f
--- /dev/null
+++ b/tools/testing/selftests/nommu/nommu_mremap_test.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include "kselftest.h"
+
+#include <sys/vfs.h>
+#ifndef RAMFS_MAGIC
+#define RAMFS_MAGIC 0x858458f6
+#endif
+
+static size_t ps;
+
+static long get_fs_type(const char *path)
+{
+ struct statfs fs;
+
+ if (statfs(path, &fs) == 0)
+ return fs.f_type;
+
+ return 0;
+}
+
+static void munmap_shrink_test(void)
+{
+ void *addr;
+ int ret;
+
+ /* munmap shrink test */
+ for (int i = 0; i < 4; i++) {
+ addr = mmap(NULL, ps * 4, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (addr == MAP_FAILED) {
+ ksft_print_msg("mmap failed: %s(%d)\n", strerror(errno), errno);
+ ksft_test_result_fail("munmap shrink\n");
+ return;
+ }
+ ret = munmap((char *)addr + ps * i, ps);
+ if (ret != 0) {
+ ksft_print_msg("memory %p isn't unmapped at %p\n",
+ addr, (char *)addr + ps * i);
+ ksft_test_result_fail("munmap shrink\n");
+ return;
+ }
+
+ if (i == 0) {
+ if (munmap(addr + ps, ps * 3))
+ goto error;
+ } else if (i == 1) {
+ if (munmap(addr, ps) || munmap(addr + (ps * 2), ps * 2))
+ goto error;
+ } else if (i == 2) {
+ if (munmap(addr, ps * 2) || munmap(addr + (ps * 3), ps))
+ goto error;
+ } else if (i == 3) {
+ if (munmap(addr, ps * 3))
+ goto error;
+ }
+ }
+
+ ksft_test_result_pass("munmap shrink\n");
+ return;
+error:
+ for (int j = 0; j < 4; j++)
+ munmap((char *)addr + j * ps, ps);
+ ksft_print_msg("clean up failures\n");
+ ksft_test_result_fail("munmap shrink\n");
+}
+
+static size_t page_align(size_t len)
+{
+ return (len + ps - 1) / ps * ps;
+}
+
+static void mremap_shrink_test(void)
+{
+ void *addr, *addr2;
+ size_t current_len;
+ size_t old_len, new_len;
+ struct param {
+ size_t old;
+ size_t new;
+ } params[] = {
+ /* should not happen any shrink */
+ { .old = ps * 4 - 1, .new = ps * 4 - 2 },
+ /* should not happen any shrink */
+ { .old = ps * 4 - 1, .new = ps * 4 },
+ { .old = ps * 4, .new = ps * 2 },
+ /* should not happen any shrink */
+ { .old = ps * 2, .new = ps * 2 - 2 },
+ { .old = ps * 2 - 2, .new = ps * 1 },
+ };
+
+ /* mremap shrink test */
+ current_len = page_align(ps * 4 - 1);
+ addr = mmap(NULL, ps * 4 - 1, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (addr == MAP_FAILED) {
+ ksft_print_msg("mmap failed: %s(%d)\n", strerror(errno), errno);
+ ksft_test_result_fail("mremap shrink\n");
+ return;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(params); i++) {
+ old_len = params[i].old;
+ new_len = params[i].new;
+ current_len = page_align(new_len);
+ addr2 = mremap(addr, old_len, new_len, MREMAP_MAYMOVE);
+ if (addr2 == MAP_FAILED) {
+ ksft_print_msg("memory %p isn't remapped at %p\n", addr, addr2);
+ ksft_test_result_fail("mremap shrink\n");
+ munmap(addr, page_align(old_len));
+ return;
+ }
+
+ addr = addr2;
+ }
+
+ if (munmap(addr, current_len)) {
+ ksft_print_msg("cleanup failed: %s\n", strerror(errno));
+ ksft_test_result_fail("mremap shrink\n");
+ return;
+ }
+ ksft_test_result_pass("mremap shrink\n");
+}
+
+static int get_shared_writable_file_expected_error(const char *path)
+{
+ if (get_fs_type(path) == RAMFS_MAGIC)
+ return EPERM; /* ramfs failed */
+
+ return 0;
+}
+
+struct mremap_case_t {
+ const char *name;
+ const char *pathname;
+ int open_flags;
+ int mmap_prot;
+ int mmap_flags;
+ int exp_err;
+ int (*resolve_exp_err)(const char *path);
+ unsigned int old_pages;
+ unsigned int new_pages;
+};
+
+static struct mremap_case_t mremap_cases[] = {
+ {
+ .name = "anonymous shrink (r--)",
+ .pathname = NULL,
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE,
+ .exp_err = 0,
+ .resolve_exp_err = 0,
+ },
+ {
+ .name = "shared file shrink (r--)",
+ .pathname = "/tmp/ksft.nommu-remap-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_SHARED,
+ .exp_err = 0,
+#ifdef NOMMU
+ .resolve_exp_err = get_shared_writable_file_expected_error,
+#else
+ .resolve_exp_err = 0,
+#endif
+ },
+ {
+ .name = "private file unchanged length (r-)",
+ .pathname = "/tmp/ksft.nommu-remap-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_PRIVATE,
+#ifdef NOMMU
+ .exp_err = EPERM,
+#else
+ .exp_err = 0,
+#endif
+ .resolve_exp_err = 0,
+ .old_pages = 4,
+ .new_pages = 4,
+ },
+ {
+ .name = "private file unchanged length (rw-)",
+ .pathname = "/tmp/ksft.nommu-remap-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ | PROT_WRITE,
+ .mmap_flags = MAP_PRIVATE,
+ .exp_err = 0,
+ .resolve_exp_err = 0,
+ .old_pages = 4,
+ .new_pages = 4,
+ },
+ {
+ .name = "private file growth (r-)",
+ .pathname = "/tmp/ksft.nommu-remap-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ,
+ .mmap_flags = MAP_PRIVATE,
+#ifdef NOMMU
+ .exp_err = EPERM,
+#else
+ .exp_err = 0,
+#endif
+ .resolve_exp_err = 0,
+ .old_pages = 4,
+ .new_pages = 8,
+ },
+ {
+ .name = "private file growth (rw-)",
+ .pathname = "/tmp/ksft.nommu-remap-XXXXXX",
+ .open_flags = O_CREAT | O_RDWR | O_EXCL,
+ .mmap_prot = PROT_READ | PROT_WRITE,
+ .mmap_flags = MAP_PRIVATE,
+#ifdef NOMMU
+ .exp_err = ENOMEM,
+#else
+ .exp_err = 0,
+#endif
+ .resolve_exp_err = 0,
+ .old_pages = 4,
+ .new_pages = 8,
+ },
+};
+
+static int run_mremap_test(struct mremap_case_t *tcase)
+{
+ int fd = -1;
+ void *addr, *addr2;
+ char pb[PATH_MAX];
+ const char *path = tcase->pathname;
+ int rc = KSFT_PASS;
+ int expected_error;
+ unsigned int old_pages = tcase->old_pages ?: 4;
+ unsigned int new_pages = tcase->new_pages ?: 2;
+ unsigned int file_pages = old_pages > new_pages ?
+ old_pages : new_pages;
+
+ ksft_print_msg("[RUN] Testing mremap: %s\n", tcase->name);
+
+ if (tcase->pathname && strstr(tcase->pathname, "XXXXXX")) {
+ strncpy(pb, tcase->pathname, sizeof(pb) - 1);
+ pb[sizeof(pb) - 1] = '\0';
+ fd = mkstemp(pb);
+ if (fd < 0) {
+ ksft_print_msg("Failed to setup file backing\n");
+ ksft_test_result_skip("%s\n", tcase->name);
+ return KSFT_SKIP;
+ }
+ if (ftruncate(fd, ps * file_pages) != 0) {
+ ksft_print_msg("Failed to setup file backing\n");
+ ksft_test_result_fail("%s\n", tcase->name);
+ close(fd);
+ unlink(pb);
+ return KSFT_FAIL;
+ }
+
+#ifdef NOMMU
+ if ((tcase->mmap_flags & MAP_SHARED) && get_fs_type(pb) != RAMFS_MAGIC) {
+ ksft_print_msg("Skip the test under non-ramfs filesystem (%s)\n",
+ pb);
+ ksft_test_result_skip("%s\n", tcase->name);
+ close(fd);
+ unlink(pb);
+ return KSFT_SKIP;
+ }
+#endif
+ path = pb;
+ } else if (tcase->pathname) {
+ fd = open(tcase->pathname, tcase->open_flags, 0600);
+ if (fd < 0) {
+ ksft_print_msg("Backing node not accessible\n");
+ ksft_test_result_skip("%s\n", tcase->name);
+ return KSFT_SKIP;
+ }
+
+#ifdef NOMMU
+ if ((tcase->mmap_flags & MAP_SHARED) &&
+ get_fs_type(tcase->pathname) != RAMFS_MAGIC) {
+ ksft_print_msg("Skip the test under non-ramfs filesystem (%s)\n",
+ tcase->pathname);
+ ksft_test_result_skip("%s\n", tcase->name);
+ close(fd);
+ return KSFT_SKIP;
+ }
+#endif
+ }
+
+ addr = mmap(NULL, ps * old_pages, tcase->mmap_prot,
+ tcase->mmap_flags, fd, 0);
+ if (addr == MAP_FAILED) {
+ ksft_print_msg("mmap mapping failed %s(%d)\n", strerror(errno), errno);
+ rc = KSFT_FAIL;
+ goto out;
+ }
+
+ expected_error = tcase->exp_err;
+ if (tcase->resolve_exp_err && fd >= 0)
+ expected_error = tcase->resolve_exp_err(path);
+
+ addr2 = mremap(addr, ps * old_pages, ps * new_pages,
+ MREMAP_MAYMOVE);
+
+ if (expected_error != 0) {
+ if (addr2 != MAP_FAILED) {
+ ksft_print_msg("Expected error %d, but mremap unexpectedly succeeded\n",
+ expected_error);
+ rc = KSFT_FAIL;
+ } else if (errno != expected_error) {
+ ksft_print_msg("Expected error %d, got %s(%d)\n",
+ expected_error, strerror(errno), errno);
+ rc = KSFT_FAIL;
+ } else {
+ ksft_print_msg("%s: Handled expected error path (errno=%d)\n",
+ tcase->name, expected_error);
+ }
+ } else if (addr2 == MAP_FAILED) {
+ ksft_print_msg("mremap shrink failed unexpectedly: %s\n",
+ strerror(errno));
+ rc = KSFT_FAIL;
+ } else {
+ ksft_print_msg("%s step successful\n", tcase->name);
+ }
+
+ /* clean up */
+ if (munmap(addr2 == MAP_FAILED ? addr : addr2,
+ addr2 == MAP_FAILED ? ps * old_pages : ps * new_pages)) {
+ ksft_print_msg("munmap failed: %s\n", strerror(errno));
+ rc = KSFT_FAIL;
+ }
+
+out:
+ if (fd >= 0) {
+ close(fd);
+ if (tcase->pathname && strstr(tcase->pathname, "XXXXXX"))
+ unlink(pb);
+ }
+
+ ksft_test_result_report(rc, "%s\n", tcase->name);
+ return rc;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ ps = sysconf(_SC_PAGESIZE);
+ ksft_print_header();
+ ksft_set_plan(ARRAY_SIZE(mremap_cases) + 2);
+
+ munmap_shrink_test();
+ mremap_shrink_test();
+
+ for (i = 0; i < (int)ARRAY_SIZE(mremap_cases); i++)
+ run_mremap_test(&mremap_cases[i]);
+
+ ksft_finished();
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-09-29 23:57 ` [PATCH v4 1/2] selftests: run tests on nommu architecture Hajime Tazaki
@ 2026-09-30 9:17 ` Lorenzo Stoakes (ARM)
2026-10-01 7:08 ` David Hildenbrand (Arm)
1 sibling, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-09-30 9:17 UTC (permalink / raw)
To: Hajime Tazaki
Cc: linux-mm, liam, rbm, akpm, luto, brendan.jackman, david,
liuhangbin, corbet, kees, broonie, mhocko, rppt, shuah, surenb,
vbabka, wad, linux-doc, linux-kselftest, linux-um, geert, daniel
On Wed, Sep 30, 2026 at 08:57:10AM +0900, Hajime Tazaki wrote:
> Architectures lacking MMU don't support fork(2) syscall and only
> vfork(2) is available with limitations. Thus, we cannot run kselftest
> on nommu architecture as is.
>
> This commit addresses this issue with the following changes:
>
> - on test run stage, avoid calling timeout command when NOMMU=1 variable
> added to environmental variable, since timeout command uses fork
> syscall which nommu platform doesn't support.
> - describe the difference of nommu tests in the document.
>
> So command line to build/execute tests for nommu should be like below:
>
> $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
> $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
> $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
> -c nommu
>
> Cc: Shuah Khan <shuah@kernel.org>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Kees Cook <kees@kernel.org>
> Cc: Andy Lutomirski <luto@amacapital.net>
> Cc: Will Drewry <wad@chromium.org>
> Cc: Mark Brown <broonie@kernel.org>
> Cc: Brendan Jackman <brendan.jackman@linux.dev>
> Cc: Hangbin Liu <liuhangbin@gmail.com>
> Cc: "Ricardo B. Marliere" <rbm@suse.com>
> Cc: linux-kselftest@vger.kernel.org
> Cc: linux-um@lists.infradead.org
> Cc: linux-mm@kvack.org
> Cc: linux-doc@vger.kernel.org
Not sure we need all the Cc's explicitly :) Andrew adds them in (I'm actually
not sure in general if they're really all that useful, some of my series sent to
hoards of people due to touching multiple bits scroll off the screen :P)
> Closes: https://sashiko.dev/#/patchset/20260813063401.1786548-1-thehajime%40gmail.com
> Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
LGTM so:
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
--
Cheers, Lorenzo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-09-29 23:57 ` [PATCH v4 1/2] selftests: run tests on nommu architecture Hajime Tazaki
2026-09-30 9:17 ` Lorenzo Stoakes (ARM)
@ 2026-10-01 7:08 ` David Hildenbrand (Arm)
2026-10-01 8:42 ` Lorenzo Stoakes (ARM)
1 sibling, 1 reply; 14+ messages in thread
From: David Hildenbrand (Arm) @ 2026-10-01 7:08 UTC (permalink / raw)
To: Hajime Tazaki, linux-mm, liam, rbm, akpm, luto, brendan.jackman,
liuhangbin, corbet, kees, ljs, broonie, mhocko, rppt, shuah,
surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um
Cc: geert, daniel
On 9/30/26 01:57, Hajime Tazaki wrote:
> Architectures lacking MMU don't support fork(2) syscall and only
> vfork(2) is available with limitations. Thus, we cannot run kselftest
> on nommu architecture as is.
>
> This commit addresses this issue with the following changes:
>
> - on test run stage, avoid calling timeout command when NOMMU=1 variable
> added to environmental variable, since timeout command uses fork
> syscall which nommu platform doesn't support.
> - describe the difference of nommu tests in the document.
>
> So command line to build/execute tests for nommu should be like below:
>
> $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
> $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
> $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
> -c nommu
Is there a way we could derive that from the environment in one of these cases?
I'd assume once could compile and run the nommu um variant, and within there
simply build the selftests and run them?
--
Cheers,
David
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-01 7:08 ` David Hildenbrand (Arm)
@ 2026-10-01 8:42 ` Lorenzo Stoakes (ARM)
2026-10-01 10:01 ` Johannes Berg
0 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-10-01 8:42 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Hajime Tazaki, linux-mm, liam, rbm, akpm, luto, brendan.jackman,
liuhangbin, corbet, kees, broonie, mhocko, rppt, shuah, surenb,
vbabka, wad, linux-doc, linux-kselftest, linux-um, geert, daniel
On Thu, Oct 01, 2026 at 09:08:33AM +0200, David Hildenbrand (Arm) wrote:
> On 9/30/26 01:57, Hajime Tazaki wrote:
> > Architectures lacking MMU don't support fork(2) syscall and only
> > vfork(2) is available with limitations. Thus, we cannot run kselftest
> > on nommu architecture as is.
> >
> > This commit addresses this issue with the following changes:
> >
> > - on test run stage, avoid calling timeout command when NOMMU=1 variable
> > added to environmental variable, since timeout command uses fork
> > syscall which nommu platform doesn't support.
> > - describe the difference of nommu tests in the document.
> >
> > So command line to build/execute tests for nommu should be like below:
> >
> > $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
> > $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
> > $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
> > -c nommu
>
> Is there a way we could derive that from the environment in one of these cases?
I thought maybe uname could help but our LLM overlords tell me no.
It pointed at something though.
In fs/proc/meminfo.c:
#ifndef CONFIG_MMU
show_val_kb(m, "MmapCopy: ",
(unsigned long)atomic_long_read(&mmap_pages_allocated));
#endif
So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
Therefore you could have:
function is_nommu()
{
grep -q "^MmapCopy:" /proc/meminfo
}
if is_nommu; then
...
fi
>
> I'd assume once could compile and run the nommu um variant, and within there
> simply build the selftests and run them?
Yeah be nice to have something that made it easy.
I'm quite excited about nommu uml in general for the purposes of easily testing
nommu stuff!
>
> --
> Cheers,
>
> David
--
Cheers, Lorenzo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-01 8:42 ` Lorenzo Stoakes (ARM)
@ 2026-10-01 10:01 ` Johannes Berg
2026-10-02 2:38 ` Hajime Tazaki
0 siblings, 1 reply; 14+ messages in thread
From: Johannes Berg @ 2026-10-01 10:01 UTC (permalink / raw)
To: Lorenzo Stoakes (ARM), David Hildenbrand (Arm)
Cc: Hajime Tazaki, linux-mm, liam, rbm, akpm, luto, brendan.jackman,
liuhangbin, corbet, kees, broonie, mhocko, rppt, shuah, surenb,
vbabka, wad, linux-doc, linux-kselftest, linux-um, geert, daniel
On Thu, 2026-10-01 at 09:42 +0100, Lorenzo Stoakes (ARM) wrote:
> On Thu, Oct 01, 2026 at 09:08:33AM +0200, David Hildenbrand (Arm) wrote:
> > On 9/30/26 01:57, Hajime Tazaki wrote:
> > > Architectures lacking MMU don't support fork(2) syscall and only
> > > vfork(2) is available with limitations. Thus, we cannot run kselftest
> > > on nommu architecture as is.
> > >
> > > This commit addresses this issue with the following changes:
> > >
> > > - on test run stage, avoid calling timeout command when NOMMU=1 variable
> > > added to environmental variable, since timeout command uses fork
> > > syscall which nommu platform doesn't support.
> > > - describe the difference of nommu tests in the document.
> > >
> > > So command line to build/execute tests for nommu should be like below:
> > >
> > > $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
> > > $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
> > > $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
> > > -c nommu
> >
> > Is there a way we could derive that from the environment in one of these cases?
>
> I thought maybe uname could help but our LLM overlords tell me no.
Hajime originally wanted uname to indicate it, but that caused
regressions elsewhere, so we dropped that commit. I guess we could put
_something_ back?
> It pointed at something though.
>
> In fs/proc/meminfo.c:
>
> #ifndef CONFIG_MMU
> show_val_kb(m, "MmapCopy: ",
> (unsigned long)atomic_long_read(&mmap_pages_allocated));
> #endif
>
> So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
Hyrum's law and all that, but I guess it's not highly likely to (want
to) change :)
johannes
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-01 10:01 ` Johannes Berg
@ 2026-10-02 2:38 ` Hajime Tazaki
2026-10-02 6:08 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 14+ messages in thread
From: Hajime Tazaki @ 2026-10-02 2:38 UTC (permalink / raw)
To: johannes
Cc: ljs, david, linux-mm, liam, rbm, akpm, luto, brendan.jackman,
liuhangbin, corbet, kees, broonie, mhocko, rppt, shuah, surenb,
vbabka, wad, linux-doc, linux-kselftest, linux-um, geert, daniel
David, Lorenzo, Johannes,
thanks for the comments and inputs.
On Thu, 01 Oct 2026 19:01:45 +0900,
Johannes Berg wrote:
> > > $ make ARCH=um NOMMU=1 O=build kselftest-all TARGETS=nommu
> > > > $ make ARCH=um NOMMU=1 O=build kselftest-install TARGETS=nommu
> > > > $ NOMMU=1 ./build/kselftest/kselftest_install/run_kselftest.sh -p \
> > > > -c nommu
> > >
> > > Is there a way we could derive that from the environment in one of these cases?
> >
> > I thought maybe uname could help but our LLM overlords tell me no.
>
> Hajime originally wanted uname to indicate it, but that caused
> regressions elsewhere, so we dropped that commit. I guess we could put
> _something_ back?
systemd uses uname information and our (old) patch changing the format
triggered the regression. thus, we dropped it.
> > It pointed at something though.
> >
> > In fs/proc/meminfo.c:
> >
> > #ifndef CONFIG_MMU
> > show_val_kb(m, "MmapCopy: ",
> > (unsigned long)atomic_long_read(&mmap_pages_allocated));
> > #endif
> >
> > So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
>
> Hyrum's law and all that, but I guess it's not highly likely to (want
> to) change :)
a runtime detection is nice.
scanning /proc/meminfo might be useful. although it requires to mount
procfs (we can actually skip procfs mount as it is optional) so, this
is not 100% portable.
checking ENOSYS like syscall(SYS_mprotect) might be useful but I
wasn't sure if this is always the case of NOMMU or not.
My original attempt was to use include/generated/autoconf.h; with that
we can omit environmental variable or command argument of NOMMU=1,
but gave up with handling standalone build/test case which might miss
the generated file (and complicate the patch only for the NOMMU
detection).
So, specifying NOMMU=1 is my previous, though dirty, conclusion.
-- Hajime
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 2:38 ` Hajime Tazaki
@ 2026-10-02 6:08 ` David Hildenbrand (Arm)
2026-10-02 8:10 ` Lorenzo Stoakes (ARM)
0 siblings, 1 reply; 14+ messages in thread
From: David Hildenbrand (Arm) @ 2026-10-02 6:08 UTC (permalink / raw)
To: Hajime Tazaki, johannes
Cc: ljs, linux-mm, liam, rbm, akpm, luto, brendan.jackman, liuhangbin,
corbet, kees, broonie, mhocko, rppt, shuah, surenb, vbabka, wad,
linux-doc, linux-kselftest, linux-um, geert, daniel
On 10/2/26 04:38, Hajime Tazaki wrote:
>
> David, Lorenzo, Johannes,
>
> thanks for the comments and inputs.
>
> On Thu, 01 Oct 2026 19:01:45 +0900,
> Johannes Berg wrote:
>>>
>>> I thought maybe uname could help but our LLM overlords tell me no.
>>
>> Hajime originally wanted uname to indicate it, but that caused
>> regressions elsewhere, so we dropped that commit. I guess we could put
>> _something_ back?
>
> systemd uses uname information and our (old) patch changing the format
> triggered the regression. thus, we dropped it.
>
>>> It pointed at something though.
>>>
>>> In fs/proc/meminfo.c:
>>>
>>> #ifndef CONFIG_MMU
>>> show_val_kb(m, "MmapCopy: ",
>>> (unsigned long)atomic_long_read(&mmap_pages_allocated));
>>> #endif
>>>
>>> So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
>>
>> Hyrum's law and all that, but I guess it's not highly likely to (want
>> to) change :)
>
> a runtime detection is nice.
>
> scanning /proc/meminfo might be useful. although it requires to mount
> procfs (we can actually skip procfs mount as it is optional) so, this
> is not 100% portable.
>
> checking ENOSYS like syscall(SYS_mprotect) might be useful but I
> wasn't sure if this is always the case of NOMMU or not.
>
I assume there are plenty of other mechanisms. Like testing if fork isn't allowed.
> My original attempt was to use include/generated/autoconf.h; with that
> we can omit environmental variable or command argument of NOMMU=1,
> but gave up with handling standalone build/test case which might miss
> the generated file (and complicate the patch only for the NOMMU
> detection).
>
> So, specifying NOMMU=1 is my previous, though dirty, conclusion.
Let's avoid making it harder on users by doing some runtime detection.
--
Cheers,
David
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 6:08 ` David Hildenbrand (Arm)
@ 2026-10-02 8:10 ` Lorenzo Stoakes (ARM)
2026-10-02 11:38 ` Geert Uytterhoeven
0 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-10-02 8:10 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Hajime Tazaki, johannes, linux-mm, liam, rbm, akpm, luto,
brendan.jackman, liuhangbin, corbet, kees, broonie, mhocko, rppt,
shuah, surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um,
geert, daniel
On Fri, Oct 02, 2026 at 08:08:44AM +0200, David Hildenbrand (Arm) wrote:
> On 10/2/26 04:38, Hajime Tazaki wrote:
> >
> > David, Lorenzo, Johannes,
> >
> > thanks for the comments and inputs.
> >
> > On Thu, 01 Oct 2026 19:01:45 +0900,
> > Johannes Berg wrote:
> >>>
> >>> I thought maybe uname could help but our LLM overlords tell me no.
> >>
> >> Hajime originally wanted uname to indicate it, but that caused
> >> regressions elsewhere, so we dropped that commit. I guess we could put
> >> _something_ back?
> >
> > systemd uses uname information and our (old) patch changing the format
> > triggered the regression. thus, we dropped it.
> >
> >>> It pointed at something though.
> >>>
> >>> In fs/proc/meminfo.c:
> >>>
> >>> #ifndef CONFIG_MMU
> >>> show_val_kb(m, "MmapCopy: ",
> >>> (unsigned long)atomic_long_read(&mmap_pages_allocated));
> >>> #endif
> >>>
> >>> So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
> >>
> >> Hyrum's law and all that, but I guess it's not highly likely to (want
> >> to) change :)
> >
> > a runtime detection is nice.
> >
> > scanning /proc/meminfo might be useful. although it requires to mount
> > procfs (we can actually skip procfs mount as it is optional) so, this
> > is not 100% portable.
> >
> > checking ENOSYS like syscall(SYS_mprotect) might be useful but I
> > wasn't sure if this is always the case of NOMMU or not.
> >
>
> I assume there are plenty of other mechanisms. Like testing if fork isn't allowed.
Yup that's an obvious candidate!
You actually need to check for both -EINVAL and -ENOSYS since, of course, we are
inconsistent with this.
Some nommu arches specify __ARCH_WANT_SYS_FORK unconditionally for both
mmu/nommu variants meaning you get -EINVAL in that case:
https://elixir.bootlin.com/linux/v7.2.8/source/kernel/fork.c#L2830
Otherwise you get -ENOSYS because it's not defined.
But fork() -> -EINVAL or -ENOSYS = nommu, then just have the child quit and
etc. should do it.
But then that'd need some C... ah fun :)
Crazy to me that we don't expose it in uname...
>
> > My original attempt was to use include/generated/autoconf.h; with that
> > we can omit environmental variable or command argument of NOMMU=1,
> > but gave up with handling standalone build/test case which might miss
> > the generated file (and complicate the patch only for the NOMMU
> > detection).
> >
> > So, specifying NOMMU=1 is my previous, though dirty, conclusion.
> Let's avoid making it harder on users by doing some runtime detection.
Yeah it'd be preferable.
I see a bunch of usage of procfs in selftests.
So can we just please require that the selftests have the user mount /proc, then
the /proc/meminfo grep is the easiest + quickest way.
>
> --
> Cheers,
>
> David
--
Cheers, Lorenzo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 8:10 ` Lorenzo Stoakes (ARM)
@ 2026-10-02 11:38 ` Geert Uytterhoeven
2026-10-02 11:53 ` Lorenzo Stoakes (ARM)
0 siblings, 1 reply; 14+ messages in thread
From: Geert Uytterhoeven @ 2026-10-02 11:38 UTC (permalink / raw)
To: Lorenzo Stoakes (ARM)
Cc: David Hildenbrand (Arm), Hajime Tazaki, johannes, linux-mm, liam,
rbm, akpm, luto, brendan.jackman, liuhangbin, corbet, kees,
broonie, mhocko, rppt, shuah, surenb, vbabka, wad, linux-doc,
linux-kselftest, linux-um, daniel
Hi Lorenzo,
On Fri, 2 Oct 2026 at 10:10, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
> On Fri, Oct 02, 2026 at 08:08:44AM +0200, David Hildenbrand (Arm) wrote:
> > On 10/2/26 04:38, Hajime Tazaki wrote:
> > > On Thu, 01 Oct 2026 19:01:45 +0900,
> > > Johannes Berg wrote:
> > >>>
> > >>> I thought maybe uname could help but our LLM overlords tell me no.
> > >>
> > >> Hajime originally wanted uname to indicate it, but that caused
> > >> regressions elsewhere, so we dropped that commit. I guess we could put
> > >> _something_ back?
> > >
> > > systemd uses uname information and our (old) patch changing the format
> > > triggered the regression. thus, we dropped it.
> > >
> > >>> It pointed at something though.
> > >>>
> > >>> In fs/proc/meminfo.c:
> > >>>
> > >>> #ifndef CONFIG_MMU
> > >>> show_val_kb(m, "MmapCopy: ",
> > >>> (unsigned long)atomic_long_read(&mmap_pages_allocated));
> > >>> #endif
> > >>>
> > >>> So MmapCopy in /proc/meminfo tells us definitively, weirdly enough.
> > >>
> > >> Hyrum's law and all that, but I guess it's not highly likely to (want
> > >> to) change :)
> > >
> > > a runtime detection is nice.
> > >
> > > scanning /proc/meminfo might be useful. although it requires to mount
> > > procfs (we can actually skip procfs mount as it is optional) so, this
> > > is not 100% portable.
> > >
> > > checking ENOSYS like syscall(SYS_mprotect) might be useful but I
> > > wasn't sure if this is always the case of NOMMU or not.
> > >
> >
> > I assume there are plenty of other mechanisms. Like testing if fork isn't allowed.
>
> Yup that's an obvious candidate!
>
> You actually need to check for both -EINVAL and -ENOSYS since, of course, we are
> inconsistent with this.
>
> Some nommu arches specify __ARCH_WANT_SYS_FORK unconditionally for both
> mmu/nommu variants meaning you get -EINVAL in that case:
>
> https://elixir.bootlin.com/linux/v7.2.8/source/kernel/fork.c#L2830
>
> Otherwise you get -ENOSYS because it's not defined.
>
> But fork() -> -EINVAL or -ENOSYS = nommu, then just have the child quit and
> etc. should do it.
fork() is not strictly an MMU-feature (you can implement fork on nommu
if all memory accesses are done relative to a base address register),
while I think mprotect() is an MMU-feature. Unless it can also be used
to change the protection using the one or two BARs most MCU haves?
Anything else that is a real MMU-feature? Non-identity mmap()?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 11:38 ` Geert Uytterhoeven
@ 2026-10-02 11:53 ` Lorenzo Stoakes (ARM)
2026-10-02 12:21 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-10-02 11:53 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: David Hildenbrand (Arm), Hajime Tazaki, johannes, linux-mm, liam,
rbm, akpm, luto, brendan.jackman, liuhangbin, corbet, kees,
broonie, mhocko, rppt, shuah, surenb, vbabka, wad, linux-doc,
linux-kselftest, linux-um, daniel
On Fri, Oct 02, 2026 at 01:38:31PM +0200, Geert Uytterhoeven wrote:
> On Fri, 2 Oct 2026 at 10:10, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
> > But fork() -> -EINVAL or -ENOSYS = nommu, then just have the child quit and
> > etc. should do it.
>
> fork() is not strictly an MMU-feature (you can implement fork on nommu
> if all memory accesses are done relative to a base address register),
> while I think mprotect() is an MMU-feature. Unless it can also be used
> to change the protection using the one or two BARs most MCU haves?
> Anything else that is a real MMU-feature? Non-identity mmap()?
Does any nommu arch implement fork() in linux?
--
Cheers, Lorenzo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 11:53 ` Lorenzo Stoakes (ARM)
@ 2026-10-02 12:21 ` David Hildenbrand (Arm)
2026-10-03 22:39 ` Hajime Tazaki
0 siblings, 1 reply; 14+ messages in thread
From: David Hildenbrand (Arm) @ 2026-10-02 12:21 UTC (permalink / raw)
To: Lorenzo Stoakes (ARM), Geert Uytterhoeven
Cc: Hajime Tazaki, johannes, linux-mm, liam, rbm, akpm, luto,
brendan.jackman, liuhangbin, corbet, kees, broonie, mhocko, rppt,
shuah, surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um,
daniel
On 10/2/26 13:53, Lorenzo Stoakes (ARM) wrote:
> On Fri, Oct 02, 2026 at 01:38:31PM +0200, Geert Uytterhoeven wrote:
>
>> On Fri, 2 Oct 2026 at 10:10, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
>
>>> But fork() -> -EINVAL or -ENOSYS = nommu, then just have the child quit and
>>> etc. should do it.
>>
>> fork() is not strictly an MMU-feature (you can implement fork on nommu
>> if all memory accesses are done relative to a base address register),
>> while I think mprotect() is an MMU-feature. Unless it can also be used
>> to change the protection using the one or two BARs most MCU haves?
>> Anything else that is a real MMU-feature? Non-identity mmap()?
>
> Does any nommu arch implement fork() in linux?
I was about to say, that sounds a bit too theoretical for me. IIUC that is not
implemented, and if someone would propose it we would likely just nak it.
In the unlikely event that this would see the light of day, we could always
change our detection in the selftests.
--
Cheers,
David
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 1/2] selftests: run tests on nommu architecture
2026-10-02 12:21 ` David Hildenbrand (Arm)
@ 2026-10-03 22:39 ` Hajime Tazaki
0 siblings, 0 replies; 14+ messages in thread
From: Hajime Tazaki @ 2026-10-03 22:39 UTC (permalink / raw)
To: david
Cc: ljs, geert, johannes, linux-mm, liam, rbm, akpm, luto,
brendan.jackman, liuhangbin, corbet, kees, broonie, mhocko, rppt,
shuah, surenb, vbabka, wad, linux-doc, linux-kselftest, linux-um,
daniel
Hello,
On Fri, 02 Oct 2026 21:21:53 +0900,
David Hildenbrand (Arm) wrote:
>
> On 10/2/26 13:53, Lorenzo Stoakes (ARM) wrote:
> > On Fri, Oct 02, 2026 at 01:38:31PM +0200, Geert Uytterhoeven wrote:
> >
> >> On Fri, 2 Oct 2026 at 10:10, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote:
> >
> >>> But fork() -> -EINVAL or -ENOSYS = nommu, then just have the child quit and
> >>> etc. should do it.
> >>
> >> fork() is not strictly an MMU-feature (you can implement fork on nommu
> >> if all memory accesses are done relative to a base address register),
> >> while I think mprotect() is an MMU-feature. Unless it can also be used
> >> to change the protection using the one or two BARs most MCU haves?
> >> Anything else that is a real MMU-feature? Non-identity mmap()?
> >
> > Does any nommu arch implement fork() in linux?
>
> I was about to say, that sounds a bit too theoretical for me. IIUC that is not
> implemented, and if someone would propose it we would likely just nak it.
>
> In the unlikely event that this would see the light of day, we could always
> change our detection in the selftests.
thanks all for the inputs and review.
I will try to implement the detection with /proc/meminfo.
-- Hajime
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-03 22:40 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29 23:57 [PATCH v4 0/2] support kselftest on nommu platform Hajime Tazaki
2026-09-29 23:57 ` [PATCH v4 1/2] selftests: run tests on nommu architecture Hajime Tazaki
2026-09-30 9:17 ` Lorenzo Stoakes (ARM)
2026-10-01 7:08 ` David Hildenbrand (Arm)
2026-10-01 8:42 ` Lorenzo Stoakes (ARM)
2026-10-01 10:01 ` Johannes Berg
2026-10-02 2:38 ` Hajime Tazaki
2026-10-02 6:08 ` David Hildenbrand (Arm)
2026-10-02 8:10 ` Lorenzo Stoakes (ARM)
2026-10-02 11:38 ` Geert Uytterhoeven
2026-10-02 11:53 ` Lorenzo Stoakes (ARM)
2026-10-02 12:21 ` David Hildenbrand (Arm)
2026-10-03 22:39 ` Hajime Tazaki
2026-09-29 23:57 ` [PATCH v4 2/2] selftests/nommu: add nommu mmap and mremap behavior tests Hajime Tazaki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox