tools/testing/selftests/mm/.gitignore | 1 - tools/testing/selftests/mm/Makefile | 3 - tools/testing/selftests/mm/run_vmtests.sh | 12 - .../selftests/mm/virtual_address_range.c | 260 ------------------ 4 files changed, 276 deletions(-) delete mode 100644 tools/testing/selftests/mm/virtual_address_range.c
This self test is asserting internal implementation details and is highly
vulnerable to internal kernel changes as a result.
It is currently failing locally from at least v6.17, and it seems that it
may have been failing for longer in many configurations/hardware as it
skips if e.g. CONFIG_ANON_VMA_NAME is not specified.
With these skips and the fact that run_vmtests.sh won't run the tests in
certain configurations it is likely we have simply missed this test being
broken in CI for a long while.
I have tried multiple versions of these tests and am unable to find a
working bisect as previous versions of the test fail also.
The tests are essentially mmap()'ing a series of mappings with no hint and
asserting what the get_unmapped_area*() functions will come up with, with
seemingly few checks for what other mappings may already be in place.
It then appears to be mmap()'ing with a hint, and making a series of
similar assertions about the internal implementation details of the hinting
logic.
Commit 0ef3783d7558 ("selftests/mm: add support to test 4PB VA on PPC64"),
commit 3bd6137220bb ("selftests/mm: virtual_address_range: avoid reading
from VM_IO mappings"), and especially commit a005145b9c96 ("selftests/mm:
virtual_address_range: mmap() without PROT_WRITE") are good examples of the
whack-a-mole nature of maintaining this test.
The last commit there being particularly pertinent as it was accounting for
an internal implementation detail change that really should have no bearing
on self-tests, that is commit e93d2521b27f ("x86/vdso: Split virtual clock
pages into dedicated mapping").
The purpose of the mm self-tests are to assert attributes about the API
exposed to users, and to ensure that expectations are met.
This test is emphatically not doing this, rather making a series of
assumptions about internal implementation details and asserting them.
It therefore, sadly, seems that the best course is to remove this test
altogether.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
tools/testing/selftests/mm/.gitignore | 1 -
tools/testing/selftests/mm/Makefile | 3 -
tools/testing/selftests/mm/run_vmtests.sh | 12 -
.../selftests/mm/virtual_address_range.c | 260 ------------------
4 files changed, 276 deletions(-)
delete mode 100644 tools/testing/selftests/mm/virtual_address_range.c
diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore
index c2a8586e51a1..702e5723c35d 100644
--- a/tools/testing/selftests/mm/.gitignore
+++ b/tools/testing/selftests/mm/.gitignore
@@ -32,7 +32,6 @@ uffd-unit-tests
uffd-wp-mremap
mlock-intersect-test
mlock-random-test
-virtual_address_range
gup_test
va_128TBswitch
map_fixed_noreplace
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index de4afc34e3b1..2fdb05e5a56a 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -136,9 +136,6 @@ endif
ifneq (,$(filter $(ARCH),arm64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64 s390))
TEST_GEN_FILES += va_high_addr_switch
-ifneq ($(ARCH),riscv64)
-TEST_GEN_FILES += virtual_address_range
-endif
TEST_GEN_FILES += write_to_hugetlbfs
endif
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
index 2dadbfc6e535..452875db532c 100755
--- a/tools/testing/selftests/mm/run_vmtests.sh
+++ b/tools/testing/selftests/mm/run_vmtests.sh
@@ -399,18 +399,6 @@ CATEGORY="hugetlb" run_test ./hugetlb-read-hwpoison
fi
if [ $VADDR64 -ne 0 ]; then
-
- # set overcommit_policy as OVERCOMMIT_ALWAYS so that kernel
- # allows high virtual address allocation requests independent
- # of platform's physical memory.
-
- if [ -x ./virtual_address_range ]; then
- prev_policy=$(cat /proc/sys/vm/overcommit_memory)
- echo 1 > /proc/sys/vm/overcommit_memory
- CATEGORY="hugevm" run_test ./virtual_address_range
- echo $prev_policy > /proc/sys/vm/overcommit_memory
- fi
-
# va high address boundary switch test
CATEGORY="hugevm" run_test bash ./va_high_addr_switch.sh
fi # VADDR64
diff --git a/tools/testing/selftests/mm/virtual_address_range.c b/tools/testing/selftests/mm/virtual_address_range.c
deleted file mode 100644
index 4f0923825ed7..000000000000
--- a/tools/testing/selftests/mm/virtual_address_range.c
+++ /dev/null
@@ -1,260 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2017, Anshuman Khandual, IBM Corp.
- *
- * Works on architectures which support 128TB virtual
- * address range and beyond.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/prctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <fcntl.h>
-
-#include "vm_util.h"
-#include "kselftest.h"
-
-/*
- * Maximum address range mapped with a single mmap()
- * call is little bit more than 1GB. Hence 1GB is
- * chosen as the single chunk size for address space
- * mapping.
- */
-
-#define SZ_1GB (1024 * 1024 * 1024UL)
-#define SZ_1TB (1024 * 1024 * 1024 * 1024UL)
-
-#define MAP_CHUNK_SIZE SZ_1GB
-
-/*
- * Address space till 128TB is mapped without any hint
- * and is enabled by default. Address space beyond 128TB
- * till 512TB is obtained by passing hint address as the
- * first argument into mmap() system call.
- *
- * The process heap address space is divided into two
- * different areas one below 128TB and one above 128TB
- * till it reaches 512TB. One with size 128TB and the
- * other being 384TB.
- *
- * On Arm64 the address space is 256TB and support for
- * high mappings up to 4PB virtual address space has
- * been added.
- *
- * On PowerPC64, the address space up to 128TB can be
- * mapped without a hint. Addresses beyond 128TB, up to
- * 4PB, can be mapped with a hint.
- *
- */
-
-#define NR_CHUNKS_128TB ((128 * SZ_1TB) / MAP_CHUNK_SIZE) /* Number of chunks for 128TB */
-#define NR_CHUNKS_256TB (NR_CHUNKS_128TB * 2UL)
-#define NR_CHUNKS_384TB (NR_CHUNKS_128TB * 3UL)
-#define NR_CHUNKS_3840TB (NR_CHUNKS_128TB * 30UL)
-#define NR_CHUNKS_3968TB (NR_CHUNKS_128TB * 31UL)
-
-#define ADDR_MARK_128TB (1UL << 47) /* First address beyond 128TB */
-#define ADDR_MARK_256TB (1UL << 48) /* First address beyond 256TB */
-
-#ifdef __aarch64__
-#define HIGH_ADDR_MARK ADDR_MARK_256TB
-#define HIGH_ADDR_SHIFT 49
-#define NR_CHUNKS_LOW NR_CHUNKS_256TB
-#define NR_CHUNKS_HIGH NR_CHUNKS_3840TB
-#elif defined(__PPC64__)
-#define HIGH_ADDR_MARK ADDR_MARK_128TB
-#define HIGH_ADDR_SHIFT 48
-#define NR_CHUNKS_LOW NR_CHUNKS_128TB
-#define NR_CHUNKS_HIGH NR_CHUNKS_3968TB
-#else
-#define HIGH_ADDR_MARK ADDR_MARK_128TB
-#define HIGH_ADDR_SHIFT 48
-#define NR_CHUNKS_LOW NR_CHUNKS_128TB
-#define NR_CHUNKS_HIGH NR_CHUNKS_384TB
-#endif
-
-static char *hint_addr(void)
-{
- int bits = HIGH_ADDR_SHIFT + rand() % (63 - HIGH_ADDR_SHIFT);
-
- return (char *) (1UL << bits);
-}
-
-static void validate_addr(char *ptr, int high_addr)
-{
- unsigned long addr = (unsigned long) ptr;
-
- if (high_addr) {
- if (addr < HIGH_ADDR_MARK)
- ksft_exit_fail_msg("Bad address %lx\n", addr);
- return;
- }
-
- if (addr > HIGH_ADDR_MARK)
- ksft_exit_fail_msg("Bad address %lx\n", addr);
-}
-
-static void mark_range(char *ptr, size_t size)
-{
- if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "virtual_address_range") == -1) {
- if (errno == EINVAL) {
- /* Depends on CONFIG_ANON_VMA_NAME */
- ksft_test_result_skip("prctl(PR_SET_VMA_ANON_NAME) not supported\n");
- ksft_finished();
- } else {
- ksft_exit_fail_perror("prctl(PR_SET_VMA_ANON_NAME) failed\n");
- }
- }
-}
-
-static int is_marked_vma(const char *vma_name)
-{
- return vma_name && !strcmp(vma_name, "[anon:virtual_address_range]\n");
-}
-
-static int validate_lower_address_hint(void)
-{
- char *ptr;
-
- ptr = mmap((void *) (1UL << 45), MAP_CHUNK_SIZE, PROT_READ |
- PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- if (ptr == MAP_FAILED)
- return 0;
-
- return 1;
-}
-
-static int validate_complete_va_space(void)
-{
- unsigned long start_addr, end_addr, prev_end_addr;
- char line[400];
- char prot[6];
- FILE *file;
- int fd;
-
- fd = open("va_dump", O_CREAT | O_WRONLY, 0600);
- unlink("va_dump");
- if (fd < 0) {
- ksft_test_result_skip("cannot create or open dump file\n");
- ksft_finished();
- }
-
- file = fopen("/proc/self/maps", "r");
- if (file == NULL)
- ksft_exit_fail_msg("cannot open /proc/self/maps\n");
-
- prev_end_addr = 0;
- while (fgets(line, sizeof(line), file)) {
- const char *vma_name = NULL;
- int vma_name_start = 0;
- unsigned long hop;
-
- if (sscanf(line, "%lx-%lx %4s %*s %*s %*s %n",
- &start_addr, &end_addr, prot, &vma_name_start) != 3)
- ksft_exit_fail_msg("cannot parse /proc/self/maps\n");
-
- if (vma_name_start)
- vma_name = line + vma_name_start;
-
- /* end of userspace mappings; ignore vsyscall mapping */
- if (start_addr & (1UL << 63))
- return 0;
-
- /* /proc/self/maps must have gaps less than MAP_CHUNK_SIZE */
- if (start_addr - prev_end_addr >= MAP_CHUNK_SIZE)
- return 1;
-
- prev_end_addr = end_addr;
-
- if (prot[0] != 'r')
- continue;
-
- if (check_vmflag_io((void *)start_addr))
- continue;
-
- /*
- * Confirm whether MAP_CHUNK_SIZE chunk can be found or not.
- * If write succeeds, no need to check MAP_CHUNK_SIZE - 1
- * addresses after that. If the address was not held by this
- * process, write would fail with errno set to EFAULT.
- * Anyways, if write returns anything apart from 1, exit the
- * program since that would mean a bug in /proc/self/maps.
- */
- hop = 0;
- while (start_addr + hop < end_addr) {
- if (write(fd, (void *)(start_addr + hop), 1) != 1)
- return 1;
- lseek(fd, 0, SEEK_SET);
-
- if (is_marked_vma(vma_name))
- munmap((char *)(start_addr + hop), MAP_CHUNK_SIZE);
-
- hop += MAP_CHUNK_SIZE;
- }
- }
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- char *ptr[NR_CHUNKS_LOW];
- char **hptr;
- char *hint;
- unsigned long i, lchunks, hchunks;
-
- ksft_print_header();
- ksft_set_plan(1);
-
- for (i = 0; i < NR_CHUNKS_LOW; i++) {
- ptr[i] = mmap(NULL, MAP_CHUNK_SIZE, PROT_READ,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- if (ptr[i] == MAP_FAILED) {
- if (validate_lower_address_hint())
- ksft_exit_fail_msg("mmap unexpectedly succeeded with hint\n");
- break;
- }
-
- mark_range(ptr[i], MAP_CHUNK_SIZE);
- validate_addr(ptr[i], 0);
- }
- lchunks = i;
- hptr = (char **) calloc(NR_CHUNKS_HIGH, sizeof(char *));
- if (hptr == NULL) {
- ksft_test_result_skip("Memory constraint not fulfilled\n");
- ksft_finished();
- }
-
- for (i = 0; i < NR_CHUNKS_HIGH; i++) {
- hint = hint_addr();
- hptr[i] = mmap(hint, MAP_CHUNK_SIZE, PROT_READ,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- if (hptr[i] == MAP_FAILED)
- break;
-
- mark_range(hptr[i], MAP_CHUNK_SIZE);
- validate_addr(hptr[i], 1);
- }
- hchunks = i;
- if (validate_complete_va_space()) {
- ksft_test_result_fail("BUG in mmap() or /proc/self/maps\n");
- ksft_finished();
- }
-
- for (i = 0; i < lchunks; i++)
- munmap(ptr[i], MAP_CHUNK_SIZE);
-
- for (i = 0; i < hchunks; i++)
- munmap(hptr[i], MAP_CHUNK_SIZE);
-
- free(hptr);
-
- ksft_test_result_pass("Test\n");
- ksft_finished();
-}
--
2.52.0
On 1/16/26 14:20, Lorenzo Stoakes wrote:
> This self test is asserting internal implementation details and is highly
> vulnerable to internal kernel changes as a result.
>
> It is currently failing locally from at least v6.17, and it seems that it
> may have been failing for longer in many configurations/hardware as it
> skips if e.g. CONFIG_ANON_VMA_NAME is not specified.
>
> With these skips and the fact that run_vmtests.sh won't run the tests in
> certain configurations it is likely we have simply missed this test being
> broken in CI for a long while.
>
> I have tried multiple versions of these tests and am unable to find a
> working bisect as previous versions of the test fail also.
>
> The tests are essentially mmap()'ing a series of mappings with no hint and
> asserting what the get_unmapped_area*() functions will come up with, with
> seemingly few checks for what other mappings may already be in place.
>
> It then appears to be mmap()'ing with a hint, and making a series of
> similar assertions about the internal implementation details of the hinting
> logic.
>
> Commit 0ef3783d7558 ("selftests/mm: add support to test 4PB VA on PPC64"),
> commit 3bd6137220bb ("selftests/mm: virtual_address_range: avoid reading
> from VM_IO mappings"), and especially commit a005145b9c96 ("selftests/mm:
> virtual_address_range: mmap() without PROT_WRITE") are good examples of the
> whack-a-mole nature of maintaining this test.
>
> The last commit there being particularly pertinent as it was accounting for
> an internal implementation detail change that really should have no bearing
> on self-tests, that is commit e93d2521b27f ("x86/vdso: Split virtual clock
> pages into dedicated mapping").
>
> The purpose of the mm self-tests are to assert attributes about the API
> exposed to users, and to ensure that expectations are met.
>
> This test is emphatically not doing this, rather making a series of
> assumptions about internal implementation details and asserting them.
>
> It therefore, sadly, seems that the best course is to remove this test
> altogether.
>
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
On
$ uname -r
6.18.4-200.fc43.x86_64
I am getting
$ ./va_high_addr_switch
mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d7000 - OK
mmap(addr_switch_hint - pagesize, (2 * pagesize)): 0x7fe7de6d6000 - OK
mmap(addr_switch_hint, pagesize): 0x7fe7de6d7000 - OK
mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED
mmap(NULL): 0x7fe7de6d5000 - OK
mmap(low_addr): 0x40000000 - OK
mmap(high_addr): 0x7fe7de6d5000 - OK
mmap(high_addr) again: 0x7fe7de6d3000 - OK
mmap(high_addr, MAP_FIXED): 0xffffffffffffffff - FAILED
mmap(-1): 0x7fe7de6d1000 - OK
mmap(-1) again: 0x7fe7de6cf000 - OK
mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d0000 - OK
mmap(addr_switch_hint - pagesize, 2 * pagesize): 0x7fe7de6cf000 - OK
mmap(addr_switch_hint - pagesize/2 , 2 * pagesize): 0x7fe7de6cd000 - OK
mmap(addr_switch_hint, pagesize): 0x7fe7de6cc000 - OK
mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED
Are these the same issues you see?
--
Cheers
David
On Mon, Jan 19, 2026 at 11:39:51AM +0100, David Hildenbrand (Red Hat) wrote: > On > > $ uname -r > 6.18.4-200.fc43.x86_64 > > I am getting > > $ ./va_high_addr_switch > mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d7000 - OK > mmap(addr_switch_hint - pagesize, (2 * pagesize)): 0x7fe7de6d6000 - OK > mmap(addr_switch_hint, pagesize): 0x7fe7de6d7000 - OK > mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED > mmap(NULL): 0x7fe7de6d5000 - OK > mmap(low_addr): 0x40000000 - OK > mmap(high_addr): 0x7fe7de6d5000 - OK > mmap(high_addr) again: 0x7fe7de6d3000 - OK > mmap(high_addr, MAP_FIXED): 0xffffffffffffffff - FAILED > mmap(-1): 0x7fe7de6d1000 - OK > mmap(-1) again: 0x7fe7de6cf000 - OK > mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d0000 - OK > mmap(addr_switch_hint - pagesize, 2 * pagesize): 0x7fe7de6cf000 - OK > mmap(addr_switch_hint - pagesize/2 , 2 * pagesize): 0x7fe7de6cd000 - OK > mmap(addr_switch_hint, pagesize): 0x7fe7de6cc000 - OK > mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED > > > Are these the same issues you see? No, that's entirely separate bug it seems :) Seems to work locally for me on 6.18.3, and also in VM with tip mm-unstable, strange. The issue here is with virtual_address_space.c which seems to just to be generally broken, I couldn't even bisect to a working one, and I really did try. Actually hang on, isn't va_high_addr_space already then testing what virtual_address_space should be testing anyway if it were sensible?? That suggests then that just removing virtual_address_space without replacement (since this already exists) is the right way (...!) Thanks, Lorenzo
On 1/19/26 12:06, Lorenzo Stoakes wrote: > On Mon, Jan 19, 2026 at 11:39:51AM +0100, David Hildenbrand (Red Hat) wrote: >> On >> >> $ uname -r >> 6.18.4-200.fc43.x86_64 >> >> I am getting >> >> $ ./va_high_addr_switch >> mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d7000 - OK >> mmap(addr_switch_hint - pagesize, (2 * pagesize)): 0x7fe7de6d6000 - OK >> mmap(addr_switch_hint, pagesize): 0x7fe7de6d7000 - OK >> mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED >> mmap(NULL): 0x7fe7de6d5000 - OK >> mmap(low_addr): 0x40000000 - OK >> mmap(high_addr): 0x7fe7de6d5000 - OK >> mmap(high_addr) again: 0x7fe7de6d3000 - OK >> mmap(high_addr, MAP_FIXED): 0xffffffffffffffff - FAILED >> mmap(-1): 0x7fe7de6d1000 - OK >> mmap(-1) again: 0x7fe7de6cf000 - OK >> mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d0000 - OK >> mmap(addr_switch_hint - pagesize, 2 * pagesize): 0x7fe7de6cf000 - OK >> mmap(addr_switch_hint - pagesize/2 , 2 * pagesize): 0x7fe7de6cd000 - OK >> mmap(addr_switch_hint, pagesize): 0x7fe7de6cc000 - OK >> mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED >> >> >> Are these the same issues you see? > > No, that's entirely separate bug it seems :) > Oh, lol, I ran the wrong test. Yes, on Fedora config I just get $ ./virtual_address_range TAP version 13 1..1 ok 1 # SKIP prctl(PR_SET_VMA_ANON_NAME) not supported # 1 skipped test(s) detected. Consider enabling relevant config options to improve coverage. # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:1 error:0 > Seems to work locally for me on 6.18.3, and also in VM with tip mm-unstable, > strange. Maybe a hardware thing (notebook not supporting 5 level page tables, maybe?) > > The issue here is with virtual_address_space.c which seems to just to be > generally broken, I couldn't even bisect to a working one, and I really did > try. > > Actually hang on, isn't va_high_addr_space already then testing what > virtual_address_space should be testing anyway if it were sensible?? > > That suggests then that just removing virtual_address_space without > replacement (since this already exists) is the right way (...!) I cannot really judge, I would have to decipher the details of the tests ... -- Cheers David
On Mon, Jan 19, 2026 at 12:11:39PM +0100, David Hildenbrand (Red Hat) wrote: > On 1/19/26 12:06, Lorenzo Stoakes wrote: > > On Mon, Jan 19, 2026 at 11:39:51AM +0100, David Hildenbrand (Red Hat) wrote: > > > On > > > > > > $ uname -r > > > 6.18.4-200.fc43.x86_64 > > > > > > I am getting > > > > > > $ ./va_high_addr_switch > > > mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d7000 - OK > > > mmap(addr_switch_hint - pagesize, (2 * pagesize)): 0x7fe7de6d6000 - OK > > > mmap(addr_switch_hint, pagesize): 0x7fe7de6d7000 - OK > > > mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED > > > mmap(NULL): 0x7fe7de6d5000 - OK > > > mmap(low_addr): 0x40000000 - OK > > > mmap(high_addr): 0x7fe7de6d5000 - OK > > > mmap(high_addr) again: 0x7fe7de6d3000 - OK > > > mmap(high_addr, MAP_FIXED): 0xffffffffffffffff - FAILED > > > mmap(-1): 0x7fe7de6d1000 - OK > > > mmap(-1) again: 0x7fe7de6cf000 - OK > > > mmap(addr_switch_hint - pagesize, pagesize): 0x7fe7de6d0000 - OK > > > mmap(addr_switch_hint - pagesize, 2 * pagesize): 0x7fe7de6cf000 - OK > > > mmap(addr_switch_hint - pagesize/2 , 2 * pagesize): 0x7fe7de6cd000 - OK > > > mmap(addr_switch_hint, pagesize): 0x7fe7de6cc000 - OK > > > mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED): 0xffffffffffffffff - FAILED > > > > > > > > > Are these the same issues you see? > > > > No, that's entirely separate bug it seems :) > > > > Oh, lol, I ran the wrong test. :)) but found another bug... > > Yes, on Fedora config I just get > > $ ./virtual_address_range > TAP version 13 > 1..1 > ok 1 # SKIP prctl(PR_SET_VMA_ANON_NAME) not supported > # 1 skipped test(s) detected. Consider enabling relevant config options to > improve coverage. > # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:1 error:0 Yeah and the test runners seem to be the same, so this test has just _not been running_ for a long while. Then if you configure a kernel that _does_ support this, it fails with a test assertion. I tried to dig in and it seemed that the logic just got confused rather than it being a legit failure as it's making odd impl detail asserts about lengths of gaps between VMA regions... > > > > Seems to work locally for me on 6.18.3, and also in VM with tip mm-unstable, > > strange. > > Maybe a hardware thing (notebook not supporting 5 level page tables, maybe?) Yeah and that's something that should probably be addressed... you'd think it'd pass anyway? > > > > > The issue here is with virtual_address_space.c which seems to just to be > > generally broken, I couldn't even bisect to a working one, and I really did > > try. > > > > Actually hang on, isn't va_high_addr_space already then testing what > > virtual_address_space should be testing anyway if it were sensible?? > > > > That suggests then that just removing virtual_address_space without > > replacement (since this already exists) is the right way (...!) > > I cannot really judge, I would have to decipher the details of the tests ... Yup, in any case removal of a test that is fundamentally broken to the point of not being able to bisect it, that doesn't mmake any sense, that risks timeout due to it taking so long doing something crazy (it tries to map across ALL of the VA address space), that relies on implementation details of the kernel/libc (i.e. how the space is laid out in the first place), etc. makes sense. It is just not useful, and needs to be replaced with something that is. If we want to unit test get_unmapped_area(), then we should unit test get_unmapped_area() in isolation. It's actively broken and harmful to keep a broken test case around. A replacement that works can be added later. > > -- > Cheers > > David Thanks, Lorenzo
On 16/01/26 6:50 pm, Lorenzo Stoakes wrote:
> This self test is asserting internal implementation details and is highly
> vulnerable to internal kernel changes as a result.
>
> It is currently failing locally from at least v6.17, and it seems that it
> may have been failing for longer in many configurations/hardware as it
> skips if e.g. CONFIG_ANON_VMA_NAME is not specified.
True, the test gets skipped for me since the mark_range function was added.
>
> With these skips and the fact that run_vmtests.sh won't run the tests in
> certain configurations it is likely we have simply missed this test being
> broken in CI for a long while.
>
> I have tried multiple versions of these tests and am unable to find a
> working bisect as previous versions of the test fail also.
Does the test fail for you even for commit 13e860961fd4 ("selftests/mm: virtual_address_range: Switch to ksft_exit_fail_msg").
I have never observed failure at this.
>
> The tests are essentially mmap()'ing a series of mappings with no hint and
> asserting what the get_unmapped_area*() functions will come up with, with
> seemingly few checks for what other mappings may already be in place.
>
> It then appears to be mmap()'ing with a hint, and making a series of
> similar assertions about the internal implementation details of the hinting
> logic.
The revelation of internal detail starts at 010409649885 ("selftests/mm: confirm VA exhaustion without reliance on correctness of mmap()").
All that does is to check whether mmap failure actually means exhaustion. This can reveal bugs in maple tree,
if it cannot find a 1G chunk in it, even when the gap is present. This is an internal detail which is not
expected to change - no one reports any breakage (AFAIK, please correct if I am wrong) until after 10 months, at
commit a005145b9c96 ("selftests/mm: virtual_address_range: mmap() without PROT_WRITE"), that too not at the
gap assertion code - the breakage happens at the while (start_addr + hop < end_addr) chunk of code. In retrospect I should
not have added this chunk - the purpose was to check whether the VMAs being advertised in procfs are actually usable, testing
something which, in case breaks, is extremely easy to figure out and fix, without putting this functionality in the test. And, I
had no knowledge at the time that this will cause pagetable allocation and will touch physical memory. So commits
b2a79f62133a and 3bd6137220bb could have simply been avoided by removing the bit of code I mentioned.
>
> Commit 0ef3783d7558 ("selftests/mm: add support to test 4PB VA on PPC64"),
> commit 3bd6137220bb ("selftests/mm: virtual_address_range: avoid reading
> from VM_IO mappings"), and especially commit a005145b9c96 ("selftests/mm:
> virtual_address_range: mmap() without PROT_WRITE") are good examples of the
> whack-a-mole nature of maintaining this test.
>
> The last commit there being particularly pertinent as it was accounting for
> an internal implementation detail change that really should have no bearing
> on self-tests, that is commit e93d2521b27f ("x86/vdso: Split virtual clock
> pages into dedicated mapping").
>
> The purpose of the mm self-tests are to assert attributes about the API
> exposed to users, and to ensure that expectations are met.
>
> This test is emphatically not doing this, rather making a series of
> assumptions about internal implementation details and asserting them.
>
> It therefore, sadly, seems that the best course is to remove this test
> altogether.
The objective of the test is to exhaust VA space and find out bugs in mmap(). It has
been useful in discovering a bug at [1].
[1] https://lore.kernel.org/all/20240123171420.3970220-1-ryan.roberts@arm.com/
>
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
> tools/testing/selftests/mm/.gitignore | 1 -
> tools/testing/selftests/mm/Makefile | 3 -
> tools/testing/selftests/mm/run_vmtests.sh | 12 -
> .../selftests/mm/virtual_address_range.c | 260 ------------------
> 4 files changed, 276 deletions(-)
> delete mode 100644 tools/testing/selftests/mm/virtual_address_range.c
>
> diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore
> index c2a8586e51a1..702e5723c35d 100644
> --- a/tools/testing/selftests/mm/.gitignore
> +++ b/tools/testing/selftests/mm/.gitignore
> @@ -32,7 +32,6 @@ uffd-unit-tests
> uffd-wp-mremap
> mlock-intersect-test
> mlock-random-test
> -virtual_address_range
> gup_test
> va_128TBswitch
> map_fixed_noreplace
> diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
> index de4afc34e3b1..2fdb05e5a56a 100644
> --- a/tools/testing/selftests/mm/Makefile
> +++ b/tools/testing/selftests/mm/Makefile
> @@ -136,9 +136,6 @@ endif
>
> ifneq (,$(filter $(ARCH),arm64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64 s390))
> TEST_GEN_FILES += va_high_addr_switch
> -ifneq ($(ARCH),riscv64)
> -TEST_GEN_FILES += virtual_address_range
> -endif
> TEST_GEN_FILES += write_to_hugetlbfs
> endif
>
> diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh
> index 2dadbfc6e535..452875db532c 100755
> --- a/tools/testing/selftests/mm/run_vmtests.sh
> +++ b/tools/testing/selftests/mm/run_vmtests.sh
> @@ -399,18 +399,6 @@ CATEGORY="hugetlb" run_test ./hugetlb-read-hwpoison
> fi
>
> if [ $VADDR64 -ne 0 ]; then
> -
> - # set overcommit_policy as OVERCOMMIT_ALWAYS so that kernel
> - # allows high virtual address allocation requests independent
> - # of platform's physical memory.
> -
> - if [ -x ./virtual_address_range ]; then
> - prev_policy=$(cat /proc/sys/vm/overcommit_memory)
> - echo 1 > /proc/sys/vm/overcommit_memory
> - CATEGORY="hugevm" run_test ./virtual_address_range
> - echo $prev_policy > /proc/sys/vm/overcommit_memory
> - fi
> -
> # va high address boundary switch test
> CATEGORY="hugevm" run_test bash ./va_high_addr_switch.sh
> fi # VADDR64
> diff --git a/tools/testing/selftests/mm/virtual_address_range.c b/tools/testing/selftests/mm/virtual_address_range.c
> deleted file mode 100644
> index 4f0923825ed7..000000000000
> --- a/tools/testing/selftests/mm/virtual_address_range.c
> +++ /dev/null
> @@ -1,260 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * Copyright 2017, Anshuman Khandual, IBM Corp.
> - *
> - * Works on architectures which support 128TB virtual
> - * address range and beyond.
> - */
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <unistd.h>
> -#include <errno.h>
> -#include <sys/prctl.h>
> -#include <sys/mman.h>
> -#include <sys/time.h>
> -#include <fcntl.h>
> -
> -#include "vm_util.h"
> -#include "kselftest.h"
> -
> -/*
> - * Maximum address range mapped with a single mmap()
> - * call is little bit more than 1GB. Hence 1GB is
> - * chosen as the single chunk size for address space
> - * mapping.
> - */
> -
> -#define SZ_1GB (1024 * 1024 * 1024UL)
> -#define SZ_1TB (1024 * 1024 * 1024 * 1024UL)
> -
> -#define MAP_CHUNK_SIZE SZ_1GB
> -
> -/*
> - * Address space till 128TB is mapped without any hint
> - * and is enabled by default. Address space beyond 128TB
> - * till 512TB is obtained by passing hint address as the
> - * first argument into mmap() system call.
> - *
> - * The process heap address space is divided into two
> - * different areas one below 128TB and one above 128TB
> - * till it reaches 512TB. One with size 128TB and the
> - * other being 384TB.
> - *
> - * On Arm64 the address space is 256TB and support for
> - * high mappings up to 4PB virtual address space has
> - * been added.
> - *
> - * On PowerPC64, the address space up to 128TB can be
> - * mapped without a hint. Addresses beyond 128TB, up to
> - * 4PB, can be mapped with a hint.
> - *
> - */
> -
> -#define NR_CHUNKS_128TB ((128 * SZ_1TB) / MAP_CHUNK_SIZE) /* Number of chunks for 128TB */
> -#define NR_CHUNKS_256TB (NR_CHUNKS_128TB * 2UL)
> -#define NR_CHUNKS_384TB (NR_CHUNKS_128TB * 3UL)
> -#define NR_CHUNKS_3840TB (NR_CHUNKS_128TB * 30UL)
> -#define NR_CHUNKS_3968TB (NR_CHUNKS_128TB * 31UL)
> -
> -#define ADDR_MARK_128TB (1UL << 47) /* First address beyond 128TB */
> -#define ADDR_MARK_256TB (1UL << 48) /* First address beyond 256TB */
> -
> -#ifdef __aarch64__
> -#define HIGH_ADDR_MARK ADDR_MARK_256TB
> -#define HIGH_ADDR_SHIFT 49
> -#define NR_CHUNKS_LOW NR_CHUNKS_256TB
> -#define NR_CHUNKS_HIGH NR_CHUNKS_3840TB
> -#elif defined(__PPC64__)
> -#define HIGH_ADDR_MARK ADDR_MARK_128TB
> -#define HIGH_ADDR_SHIFT 48
> -#define NR_CHUNKS_LOW NR_CHUNKS_128TB
> -#define NR_CHUNKS_HIGH NR_CHUNKS_3968TB
> -#else
> -#define HIGH_ADDR_MARK ADDR_MARK_128TB
> -#define HIGH_ADDR_SHIFT 48
> -#define NR_CHUNKS_LOW NR_CHUNKS_128TB
> -#define NR_CHUNKS_HIGH NR_CHUNKS_384TB
> -#endif
> -
> -static char *hint_addr(void)
> -{
> - int bits = HIGH_ADDR_SHIFT + rand() % (63 - HIGH_ADDR_SHIFT);
> -
> - return (char *) (1UL << bits);
> -}
> -
> -static void validate_addr(char *ptr, int high_addr)
> -{
> - unsigned long addr = (unsigned long) ptr;
> -
> - if (high_addr) {
> - if (addr < HIGH_ADDR_MARK)
> - ksft_exit_fail_msg("Bad address %lx\n", addr);
> - return;
> - }
> -
> - if (addr > HIGH_ADDR_MARK)
> - ksft_exit_fail_msg("Bad address %lx\n", addr);
> -}
> -
> -static void mark_range(char *ptr, size_t size)
> -{
> - if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "virtual_address_range") == -1) {
> - if (errno == EINVAL) {
> - /* Depends on CONFIG_ANON_VMA_NAME */
> - ksft_test_result_skip("prctl(PR_SET_VMA_ANON_NAME) not supported\n");
> - ksft_finished();
> - } else {
> - ksft_exit_fail_perror("prctl(PR_SET_VMA_ANON_NAME) failed\n");
> - }
> - }
> -}
> -
> -static int is_marked_vma(const char *vma_name)
> -{
> - return vma_name && !strcmp(vma_name, "[anon:virtual_address_range]\n");
> -}
> -
> -static int validate_lower_address_hint(void)
> -{
> - char *ptr;
> -
> - ptr = mmap((void *) (1UL << 45), MAP_CHUNK_SIZE, PROT_READ |
> - PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> -
> - if (ptr == MAP_FAILED)
> - return 0;
> -
> - return 1;
> -}
> -
> -static int validate_complete_va_space(void)
> -{
> - unsigned long start_addr, end_addr, prev_end_addr;
> - char line[400];
> - char prot[6];
> - FILE *file;
> - int fd;
> -
> - fd = open("va_dump", O_CREAT | O_WRONLY, 0600);
> - unlink("va_dump");
> - if (fd < 0) {
> - ksft_test_result_skip("cannot create or open dump file\n");
> - ksft_finished();
> - }
> -
> - file = fopen("/proc/self/maps", "r");
> - if (file == NULL)
> - ksft_exit_fail_msg("cannot open /proc/self/maps\n");
> -
> - prev_end_addr = 0;
> - while (fgets(line, sizeof(line), file)) {
> - const char *vma_name = NULL;
> - int vma_name_start = 0;
> - unsigned long hop;
> -
> - if (sscanf(line, "%lx-%lx %4s %*s %*s %*s %n",
> - &start_addr, &end_addr, prot, &vma_name_start) != 3)
> - ksft_exit_fail_msg("cannot parse /proc/self/maps\n");
> -
> - if (vma_name_start)
> - vma_name = line + vma_name_start;
> -
> - /* end of userspace mappings; ignore vsyscall mapping */
> - if (start_addr & (1UL << 63))
> - return 0;
> -
> - /* /proc/self/maps must have gaps less than MAP_CHUNK_SIZE */
> - if (start_addr - prev_end_addr >= MAP_CHUNK_SIZE)
> - return 1;
> -
> - prev_end_addr = end_addr;
> -
> - if (prot[0] != 'r')
> - continue;
> -
> - if (check_vmflag_io((void *)start_addr))
> - continue;
> -
> - /*
> - * Confirm whether MAP_CHUNK_SIZE chunk can be found or not.
> - * If write succeeds, no need to check MAP_CHUNK_SIZE - 1
> - * addresses after that. If the address was not held by this
> - * process, write would fail with errno set to EFAULT.
> - * Anyways, if write returns anything apart from 1, exit the
> - * program since that would mean a bug in /proc/self/maps.
> - */
> - hop = 0;
> - while (start_addr + hop < end_addr) {
> - if (write(fd, (void *)(start_addr + hop), 1) != 1)
> - return 1;
> - lseek(fd, 0, SEEK_SET);
> -
> - if (is_marked_vma(vma_name))
> - munmap((char *)(start_addr + hop), MAP_CHUNK_SIZE);
> -
> - hop += MAP_CHUNK_SIZE;
> - }
> - }
> - return 0;
> -}
> -
> -int main(int argc, char *argv[])
> -{
> - char *ptr[NR_CHUNKS_LOW];
> - char **hptr;
> - char *hint;
> - unsigned long i, lchunks, hchunks;
> -
> - ksft_print_header();
> - ksft_set_plan(1);
> -
> - for (i = 0; i < NR_CHUNKS_LOW; i++) {
> - ptr[i] = mmap(NULL, MAP_CHUNK_SIZE, PROT_READ,
> - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> -
> - if (ptr[i] == MAP_FAILED) {
> - if (validate_lower_address_hint())
> - ksft_exit_fail_msg("mmap unexpectedly succeeded with hint\n");
> - break;
> - }
> -
> - mark_range(ptr[i], MAP_CHUNK_SIZE);
> - validate_addr(ptr[i], 0);
> - }
> - lchunks = i;
> - hptr = (char **) calloc(NR_CHUNKS_HIGH, sizeof(char *));
> - if (hptr == NULL) {
> - ksft_test_result_skip("Memory constraint not fulfilled\n");
> - ksft_finished();
> - }
> -
> - for (i = 0; i < NR_CHUNKS_HIGH; i++) {
> - hint = hint_addr();
> - hptr[i] = mmap(hint, MAP_CHUNK_SIZE, PROT_READ,
> - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> -
> - if (hptr[i] == MAP_FAILED)
> - break;
> -
> - mark_range(hptr[i], MAP_CHUNK_SIZE);
> - validate_addr(hptr[i], 1);
> - }
> - hchunks = i;
> - if (validate_complete_va_space()) {
> - ksft_test_result_fail("BUG in mmap() or /proc/self/maps\n");
> - ksft_finished();
> - }
> -
> - for (i = 0; i < lchunks; i++)
> - munmap(ptr[i], MAP_CHUNK_SIZE);
> -
> - for (i = 0; i < hchunks; i++)
> - munmap(hptr[i], MAP_CHUNK_SIZE);
> -
> - free(hptr);
> -
> - ksft_test_result_pass("Test\n");
> - ksft_finished();
> -}
One note - Dev please wrap lines to 75 chars as per standard kernel
practice. It's super hard to read your mail with unwrapped lines, thanks.
On Sun, Jan 18, 2026 at 01:25:25PM +0530, Dev Jain wrote:
>
> On 16/01/26 6:50 pm, Lorenzo Stoakes wrote:
> > This self test is asserting internal implementation details and is highly
> > vulnerable to internal kernel changes as a result.
> >
> > It is currently failing locally from at least v6.17, and it seems that it
> > may have been failing for longer in many configurations/hardware as it
> > skips if e.g. CONFIG_ANON_VMA_NAME is not specified.
>
> True, the test gets skipped for me since the mark_range function was added.
This is underlining the issue with this test.
>
> >
> > With these skips and the fact that run_vmtests.sh won't run the tests in
> > certain configurations it is likely we have simply missed this test being
> > broken in CI for a long while.
> >
> > I have tried multiple versions of these tests and am unable to find a
> > working bisect as previous versions of the test fail also.
>
> Does the test fail for you even for commit 13e860961fd4 ("selftests/mm: virtual_address_range: Switch to ksft_exit_fail_msg").
> I have never observed failure at this.
It fails consistently with everything as I said, I gave up on trying to
bisect it at v6.17.
It's been broken for a whole bunch of commits all over the place so is also
an active bisection hazard.
>
>
> >
> > The tests are essentially mmap()'ing a series of mappings with no hint and
> > asserting what the get_unmapped_area*() functions will come up with, with
> > seemingly few checks for what other mappings may already be in place.
> >
> > It then appears to be mmap()'ing with a hint, and making a series of
> > similar assertions about the internal implementation details of the hinting
> > logic.
>
> The revelation of internal detail starts at 010409649885 ("selftests/mm: confirm VA exhaustion without reliance on correctness of mmap()").
> All that does is to check whether mmap failure actually means exhaustion. This can reveal bugs in maple tree,
> if it cannot find a 1G chunk in it, even when the gap is present. This is an internal detail which is not
> expected to change - no one reports any breakage (AFAIK, please correct if I am wrong) until after 10 months, at
'Internal detail that is not expected to change' is incorrect - you can have no
expectations about internal implementation details.
Another thing I didn't mention is this test takes a LONG time to run, and we are
already having timeout issues with test runs.
> commit a005145b9c96 ("selftests/mm: virtual_address_range: mmap() without PROT_WRITE"), that too not at the
> gap assertion code - the breakage happens at the while (start_addr + hop < end_addr) chunk of code. In retrospect I should
> not have added this chunk - the purpose was to check whether the VMAs being advertised in procfs are actually usable, testing
> something which, in case breaks, is extremely easy to figure out and fix, without putting this functionality in the test. And, I
> had no knowledge at the time that this will cause pagetable allocation and will touch physical memory. So commits
> b2a79f62133a and 3bd6137220bb could have simply been avoided by removing the bit of code I mentioned.
OK thanks for the explanation, but I don't think this changes anything.
>
> >
> > Commit 0ef3783d7558 ("selftests/mm: add support to test 4PB VA on PPC64"),
> > commit 3bd6137220bb ("selftests/mm: virtual_address_range: avoid reading
> > from VM_IO mappings"), and especially commit a005145b9c96 ("selftests/mm:
> > virtual_address_range: mmap() without PROT_WRITE") are good examples of the
> > whack-a-mole nature of maintaining this test.
> >
> > The last commit there being particularly pertinent as it was accounting for
> > an internal implementation detail change that really should have no bearing
> > on self-tests, that is commit e93d2521b27f ("x86/vdso: Split virtual clock
> > pages into dedicated mapping").
> >
> > The purpose of the mm self-tests are to assert attributes about the API
> > exposed to users, and to ensure that expectations are met.
> >
> > This test is emphatically not doing this, rather making a series of
> > assumptions about internal implementation details and asserting them.
> >
> > It therefore, sadly, seems that the best course is to remove this test
> > altogether.
>
> The objective of the test is to exhaust VA space and find out bugs in mmap(). It has
Well no, you're asserting gap lengths repeatedly, you are making assertions
about get_unmapped_area() behaviour that are totally inappropriate in a
self-test.
I would suggest looking into actually writing unit tests for get_unmapped_area()
functions using kunit or similar would be the correct approach.
But again I'm not sure that it's appropriate to just have a test assert
that functions do what they're implemented to do.
> been useful in discovering a bug at [1].
>
> [1] https://lore.kernel.org/all/20240123171420.3970220-1-ryan.roberts@arm.com/
I mean that proves my point that this test is _actually_ a wrongly-abstracted
get_unmapped_area() unit test...
I'm glad it was useful there, but it's just at the wrong level of abstraction.
The test has been broken consistently, right now it's broken and nobody noticed
because it got skipped (!), it simply does not work on my threadripper in any
configuration, nor in virtme-ng, I've looked at the CI and it seems it's not
been running there either, and it's adding maintenance burden and making test
runs slow even if you have CONFIG_ANON_VMA_NAME set up.
Every time somebody changes an internal implementation detail about mmap()
layout, this will fail even though nothing has broken. This alone renders the
test inappropriate.
It reminds me a little of CRIU, which is tooling that makes a bunch of internal
kernel impl detail assumptions to work - we are not obliged to keep these kinds
of things working.
When I first saw this test I felt it was asserting internal impl. details and
thus not suitable as a self-test but let it go as relatively harmless.
Now it's actively harming my work flow (I run mm selftests locally a
lot). I think on the basis of all the above it's appropriate to remove it.
Thanks, Lorenzo
On 18/01/26 6:28 pm, Lorenzo Stoakes wrote:
> One note - Dev please wrap lines to 75 chars as per standard kernel
> practice. It's super hard to read your mail with unwrapped lines, thanks.
> On Sun, Jan 18, 2026 at 01:25:25PM +0530, Dev Jain wrote:
>> On 16/01/26 6:50 pm, Lorenzo Stoakes wrote:
>>> This self test is asserting internal implementation details and is highly
>>> vulnerable to internal kernel changes as a result.
>>>
>>> It is currently failing locally from at least v6.17, and it seems that it
>>> may have been failing for longer in many configurations/hardware as it
>>> skips if e.g. CONFIG_ANON_VMA_NAME is not specified.
>> True, the test gets skipped for me since the mark_range function was added.
> This is underlining the issue with this test.
>
>>> With these skips and the fact that run_vmtests.sh won't run the tests in
>>> certain configurations it is likely we have simply missed this test being
>>> broken in CI for a long while.
>>>
>>> I have tried multiple versions of these tests and am unable to find a
>>> working bisect as previous versions of the test fail also.
>> Does the test fail for you even for commit 13e860961fd4 ("selftests/mm: virtual_address_range: Switch to ksft_exit_fail_msg").
>> I have never observed failure at this.
> It fails consistently with everything as I said, I gave up on trying to
> bisect it at v6.17.
>
> It's been broken for a whole bunch of commits all over the place so is also
> an active bisection hazard.
>
>>> The tests are essentially mmap()'ing a series of mappings with no hint and
>>> asserting what the get_unmapped_area*() functions will come up with, with
>>> seemingly few checks for what other mappings may already be in place.
>>>
>>> It then appears to be mmap()'ing with a hint, and making a series of
>>> similar assertions about the internal implementation details of the hinting
>>> logic.
>> The revelation of internal detail starts at 010409649885 ("selftests/mm: confirm VA exhaustion without reliance on correctness of mmap()").
>> All that does is to check whether mmap failure actually means exhaustion. This can reveal bugs in maple tree,
>> if it cannot find a 1G chunk in it, even when the gap is present. This is an internal detail which is not
>> expected to change - no one reports any breakage (AFAIK, please correct if I am wrong) until after 10 months, at
> 'Internal detail that is not expected to change' is incorrect - you can have no
> expectations about internal implementation details.
>
> Another thing I didn't mention is this test takes a LONG time to run, and we are
> already having timeout issues with test runs.
>
>> commit a005145b9c96 ("selftests/mm: virtual_address_range: mmap() without PROT_WRITE"), that too not at the
>> gap assertion code - the breakage happens at the while (start_addr + hop < end_addr) chunk of code. In retrospect I should
>> not have added this chunk - the purpose was to check whether the VMAs being advertised in procfs are actually usable, testing
>> something which, in case breaks, is extremely easy to figure out and fix, without putting this functionality in the test. And, I
>> had no knowledge at the time that this will cause pagetable allocation and will touch physical memory. So commits
>> b2a79f62133a and 3bd6137220bb could have simply been avoided by removing the bit of code I mentioned.
> OK thanks for the explanation, but I don't think this changes anything.
>
>>> Commit 0ef3783d7558 ("selftests/mm: add support to test 4PB VA on PPC64"),
>>> commit 3bd6137220bb ("selftests/mm: virtual_address_range: avoid reading
>>> from VM_IO mappings"), and especially commit a005145b9c96 ("selftests/mm:
>>> virtual_address_range: mmap() without PROT_WRITE") are good examples of the
>>> whack-a-mole nature of maintaining this test.
>>>
>>> The last commit there being particularly pertinent as it was accounting for
>>> an internal implementation detail change that really should have no bearing
>>> on self-tests, that is commit e93d2521b27f ("x86/vdso: Split virtual clock
>>> pages into dedicated mapping").
>>>
>>> The purpose of the mm self-tests are to assert attributes about the API
>>> exposed to users, and to ensure that expectations are met.
>>>
>>> This test is emphatically not doing this, rather making a series of
>>> assumptions about internal implementation details and asserting them.
>>>
>>> It therefore, sadly, seems that the best course is to remove this test
>>> altogether.
>> The objective of the test is to exhaust VA space and find out bugs in mmap(). It has
> Well no, you're asserting gap lengths repeatedly, you are making assertions
> about get_unmapped_area() behaviour that are totally inappropriate in a
> self-test.
Apologies - so I discussed with Aneesh and Anshuman (CCed) and it turns out that the objective
of the test was to test the switch boundary. Upon exhaustion of the lower VA space, kernel
must not start giving out VMAs in the higher VA space, if the hint address is not given. The
original commit is 4e5ce33ceb32 ("selftests/vm: add a test for virtual address range mapping").
I cannot find this API requirement on the man page (because no one bothered to update it),
but it is mentioned in Documentation/arch/arm64/memory.rst:
"To maintain compatibility with software that relies on the ARMv8.0 VA space maximum size
of 48-bits, the kernel will, by default, return virtual addresses to userspace from
a 48-bit range.
Software can "opt-in" to receiving VAs from a 52-bit space by specifying an mmap hint
parameter that is larger than 48-bit."
So this is a thing that needs to be tested on arm64, and on ppc64 (for which the test
was originally added). Not sure about x86.
> I would suggest looking into actually writing unit tests for get_unmapped_area()
> functions using kunit or similar would be the correct approach.
>
> But again I'm not sure that it's appropriate to just have a test assert
> that functions do what they're implemented to do.
>
>> been useful in discovering a bug at [1].
>>
>> [1] https://lore.kernel.org/all/20240123171420.3970220-1-ryan.roberts@arm.com/
> I mean that proves my point that this test is _actually_ a wrongly-abstracted
> get_unmapped_area() unit test...
>
> I'm glad it was useful there, but it's just at the wrong level of abstraction.
>
> The test has been broken consistently, right now it's broken and nobody noticed
> because it got skipped (!), it simply does not work on my threadripper in any
> configuration, nor in virtme-ng, I've looked at the CI and it seems it's not
> been running there either, and it's adding maintenance burden and making test
> runs slow even if you have CONFIG_ANON_VMA_NAME set up.
>
> Every time somebody changes an internal implementation detail about mmap()
> layout, this will fail even though nothing has broken. This alone renders the
> test inappropriate.
>
> It reminds me a little of CRIU, which is tooling that makes a bunch of internal
> kernel impl detail assumptions to work - we are not obliged to keep these kinds
> of things working.
>
> When I first saw this test I felt it was asserting internal impl. details and
> thus not suitable as a self-test but let it go as relatively harmless.
About internal impl details, how is this test any different from merge.c, cow.c,
etc - which consistently test/depend on whether the VMA splits/merges?
>
> Now it's actively harming my work flow (I run mm selftests locally a
> lot). I think on the basis of all the above it's appropriate to remove it.
>
> Thanks, Lorenzo
On Mon, Jan 19, 2026 at 11:51:47AM +0530, Dev Jain wrote:
> > Well no, you're asserting gap lengths repeatedly, you are making assertions
> > about get_unmapped_area() behaviour that are totally inappropriate in a
> > self-test.
>
> Apologies - so I discussed with Aneesh and Anshuman (CCed) and it turns out that the objective
> of the test was to test the switch boundary. Upon exhaustion of the lower VA space, kernel
> must not start giving out VMAs in the higher VA space, if the hint address is not given. The
> original commit is 4e5ce33ceb32 ("selftests/vm: add a test for virtual address range mapping").
This doesn't change anything, this is still testing get_unmapped_area() which by
definition is what is returning this.
Also exhausting VA space is an inherently silly thing for a test to do, you're
making assumptions about existing VMA layout which is absolutely an
implementation detail and may even be influence by libc...
>
> I cannot find this API requirement on the man page (because no one bothered to update it),
> but it is mentioned in Documentation/arch/arm64/memory.rst:
>
> "To maintain compatibility with software that relies on the ARMv8.0 VA space maximum size
> of 48-bits, the kernel will, by default, return virtual addresses to userspace from
> a 48-bit range.
>
> Software can "opt-in" to receiving VAs from a 52-bit space by specifying an mmap hint
> parameter that is larger than 48-bit."
>
> So this is a thing that needs to be tested on arm64, and on ppc64 (for which the test
> was originally added). Not sure about x86.
Well 'needs' is strong here...
It would be far more efficient to implement this as a kunit test and wouldn't
require a extremely slow test that makes assumptions about VMA layout.
> About internal impl details, how is this test any different from merge.c, cow.c,
> etc - which consistently test/depend on whether the VMA splits/merges?
This is not a hugely civil/productive way of responding here to be honest, it's
what-about-ery and implying something that isn't very kind...
But since I am a reasonable if grumpy maintainer, let me indulge you a second
here.
I thought I'd been clear BUT for avoidance of doubt, I want to remove this test
because of the COMBINATION of:
1. It is completely broken and has been broken for some time and nobody noticed.
2. It is asserting kernel implementation details.
3. It is poorly implemented and breaks often.
4. It takes a very long time to run even on fast machines and is a timeout risk.
So even if you had a point, it wouldn't argue against removal.
But you do not - both VMA merge and CoW impact API. Re: merging certain
user-facing functions, most notably mremap(), have API requirements that the
user must not cross VMA boundaries. It is therefore ENTIRELY a user-facing and
kernel/user API thing that has to be tested from this perspective.
CoW is equally a documented and expected behaviour and also affects merging.
Anyway.
Practically speaking I think there are two ways forward here (not mutually
exclusive):
1. Implement something in kunit or similar that explicitly tests
get_unmapped_area().
2. Add a _new_ selftest, named something sensible like mmap_hint.c or something,
that runs only on relevant arches, and does NOT try to do crazy stuff like
mapping the entire VA space, but instead simply tries some trial unhinted
mappings some hints in 48-bit space, and some hints in 52-bit space and
asserts things are as expected.
If you do point 2, please please use a. use the kselftest_harness.h to write the
tests in a nice way (see e.g. guard-regions.c for an example of how it's used)
and b. use the procmap helpers in vm_util.h to check on VMA ranges, you can see
how they're used in... the merge.c tests you so deride :)
If you or others do both/either I promise to dedicate review resource to the
series(es). That fair enough?
Thanks, Lorenzo
On 19/01/26 2:29 pm, Lorenzo Stoakes wrote:
> On Mon, Jan 19, 2026 at 11:51:47AM +0530, Dev Jain wrote:
>>> Well no, you're asserting gap lengths repeatedly, you are making assertions
>>> about get_unmapped_area() behaviour that are totally inappropriate in a
>>> self-test.
>> Apologies - so I discussed with Aneesh and Anshuman (CCed) and it turns out that the objective
>> of the test was to test the switch boundary. Upon exhaustion of the lower VA space, kernel
>> must not start giving out VMAs in the higher VA space, if the hint address is not given. The
>> original commit is 4e5ce33ceb32 ("selftests/vm: add a test for virtual address range mapping").
> This doesn't change anything, this is still testing get_unmapped_area() which by
> definition is what is returning this.
>
> Also exhausting VA space is an inherently silly thing for a test to do, you're
> making assumptions about existing VMA layout which is absolutely an
> implementation detail and may even be influence by libc...
>
>> I cannot find this API requirement on the man page (because no one bothered to update it),
>> but it is mentioned in Documentation/arch/arm64/memory.rst:
>>
>> "To maintain compatibility with software that relies on the ARMv8.0 VA space maximum size
>> of 48-bits, the kernel will, by default, return virtual addresses to userspace from
>> a 48-bit range.
>>
>> Software can "opt-in" to receiving VAs from a 52-bit space by specifying an mmap hint
>> parameter that is larger than 48-bit."
>>
>> So this is a thing that needs to be tested on arm64, and on ppc64 (for which the test
>> was originally added). Not sure about x86.
> Well 'needs' is strong here...
>
> It would be far more efficient to implement this as a kunit test and wouldn't
> require a extremely slow test that makes assumptions about VMA layout.
>
>> About internal impl details, how is this test any different from merge.c, cow.c,
>> etc - which consistently test/depend on whether the VMA splits/merges?
> This is not a hugely civil/productive way of responding here to be honest, it's
> what-about-ery and implying something that isn't very kind...
>
> But since I am a reasonable if grumpy maintainer, let me indulge you a second
> here.
>
> I thought I'd been clear BUT for avoidance of doubt, I want to remove this test
> because of the COMBINATION of:
>
> 1. It is completely broken and has been broken for some time and nobody noticed.
> 2. It is asserting kernel implementation details.
> 3. It is poorly implemented and breaks often.
> 4. It takes a very long time to run even on fast machines and is a timeout risk.
>
> So even if you had a point, it wouldn't argue against removal.
>
> But you do not - both VMA merge and CoW impact API. Re: merging certain
> user-facing functions, most notably mremap(), have API requirements that the
> user must not cross VMA boundaries. It is therefore ENTIRELY a user-facing and
> kernel/user API thing that has to be tested from this perspective.
>
> CoW is equally a documented and expected behaviour and also affects merging.
>
> Anyway.
>
> Practically speaking I think there are two ways forward here (not mutually
> exclusive):
>
> 1. Implement something in kunit or similar that explicitly tests
> get_unmapped_area().
>
> 2. Add a _new_ selftest, named something sensible like mmap_hint.c or something,
> that runs only on relevant arches, and does NOT try to do crazy stuff like
> mapping the entire VA space, but instead simply tries some trial unhinted
> mappings some hints in 48-bit space, and some hints in 52-bit space and
> asserts things are as expected.
I'll reply to everything here otherwise I'll have to repeat myself at different places.
"Also exhausting VA space is an inherently silly thing for a test to do, you're
making assumptions about existing VMA layout which is absolutely an
implementation detail and may even be influence by libc..."
The original version only uses mmap() and checks whether we got a high address mmap
success when we shouldn't have. There are no assumptions being made here about
VA layout. No matter the VA layout, the test will succeed because the kernel
must enforce the distinction between low and high addresses (but see point 3 below).
"It is therefore ENTIRELY a user-facing and kernel/user API thing that has to be tested from this perspective."
So in merge.c, the statements ASSERT_NE(ptrx, MAP_FAILED) surely assert the
user-visible API - that mremap must not fail. But there are statements which
also assert where a VMA starts and where it ends, testing VMA merging -
I was concerned about these. It is not the goal of userspace to minimize the
number of VMAs while making a syscall - that is a kernel optimization. My point being,
I suspect that the mm selftests *already* test internal details a lot, and I believe
that they *need* to! Running selftests is the most convenient way of testing the mm subsystem.
Hence this should not be a ground for removal of test.
Talking about the recent commits, they can be reverted. So, the ground for
removal should be that the ratio of the time taken by the test (exhausting VA
space), to the coverage of the test (for arm64, it is testing backward compatibility of 48-bit VA
on 52-bit VA, which one can argue is easy to spot if it ever breaks, and easy to fix)
is too large and does not justify a selftest. I tend to agree here.
"Add a _new_ selftest, named something sensible like mmap_hint.c or something ..."
va_high_addr_switch.c tests stuff around the switch boundary. But it does not
exhaust VA space. We *must* exhaust VA space if we are to check that the kernel,
in a situation of "emergency" (i.e exhausted lower VA space), starts giving out
high addresses, when it shouldn't. Again, one may argue that trying to test
this out is not worth it.
I personally opine that besides testing the back compat of 48 bit VA on 52 bit VA,
we are testing something more important here: exhausting the VA space tests whether
the kernel can truly distinguish b/w virtual and physical memory - we stress the virtual
memory subsystem without touching physical memory, something which the kernel should be able
to handle. But again, any such test has the potential for a timeout. I wonder if there is a
faster way of filling up VA space.
To summarize, I will agree with you that currently
1. The test is in a broken state
2. The test is taking too much time to test something trivial
3. It is a maintenance hazard. It turns out that the original version used
MAP_CHUNK_SIZE of 16GB, but then it was changed to 1GB because (this is the bit
where the dependency on VA layout comes) on some systems even a single 16GB mmap
may fail. So now we are stuck in making a tradeoff between the size of a single
mmap versus the time taken by the test
So the better option seems to just remove the test.
A separate question: Do you think that the functionality advertised by validate_complete_va_space,
to check the gaps between VMAs, deserves a test in kunit / tools/testing/vma, or somewhere else?
>
> If you do point 2, please please use a. use the kselftest_harness.h to write the
> tests in a nice way (see e.g. guard-regions.c for an example of how it's used)
> and b. use the procmap helpers in vm_util.h to check on VMA ranges, you can see
> how they're used in... the merge.c tests you so deride :)
>
> If you or others do both/either I promise to dedicate review resource to the
> series(es). That fair enough?
>
> Thanks, Lorenzo
On Tue, Jan 20, 2026 at 10:59:01AM +0530, Dev Jain wrote: > > I'll reply to everything here otherwise I'll have to repeat myself at different places. > > "Also exhausting VA space is an inherently silly thing for a test to do, you're > making assumptions about existing VMA layout which is absolutely an > implementation detail and may even be influence by libc..." > > The original version only uses mmap() and checks whether we got a high address mmap > success when we shouldn't have. There are no assumptions being made here about > VA layout. No matter the VA layout, the test will succeed because the kernel > must enforce the distinction between low and high addresses (but see point 3 below). > > > "It is therefore ENTIRELY a user-facing and kernel/user API thing that has to be tested from this perspective." > > So in merge.c, the statements ASSERT_NE(ptrx, MAP_FAILED) surely assert the > user-visible API - that mremap must not fail. But there are statements which > also assert where a VMA starts and where it ends, testing VMA merging - > I was concerned about these. It is not the goal of userspace to minimize the > number of VMAs while making a syscall - that is a kernel optimization. My point being, > I suspect that the mm selftests *already* test internal details a lot, and I believe > that they *need* to! Running selftests is the most convenient way of testing the mm subsystem. > Hence this should not be a ground for removal of test. Dev I would rather try to be positive not negative in review but again, this isn't constructive, we're not talking about merge.c and even if it contained the comment /* Ha ha I am a contradiction */ it wouldn't impact this discussion. You're not correct, mremap() has an API requirement that you can't cross VMA boundaries for most operations, therefore start/end of VMA's and merging _does_ matter. This also impacts how e.g. madvise() behaves. As I said before: But you do not - both VMA merge and CoW impact API. Re: merging certain user-facing functions, most notably mremap(), have API requirements that the user must not cross VMA boundaries. It is therefore ENTIRELY a user-facing and kernel/user API thing that has to be tested from this perspective. Can we drop the subject please? > > Talking about the recent commits, they can be reverted. So, the ground for > removal should be that the ratio of the time taken by the test (exhausting VA > space), to the coverage of the test (for arm64, it is testing backward compatibility of 48-bit VA > on 52-bit VA, which one can argue is easy to spot if it ever breaks, and easy to fix) > is too large and does not justify a selftest. I tend to agree here. > > "Add a _new_ selftest, named something sensible like mmap_hint.c or something ..." > > va_high_addr_switch.c tests stuff around the switch boundary. But it does not > exhaust VA space. We *must* exhaust VA space if we are to check that the kernel, > in a situation of "emergency" (i.e exhausted lower VA space), starts giving out > high addresses, when it shouldn't. Again, one may argue that trying to test > this out is not worth it. > > I personally opine that besides testing the back compat of 48 bit VA on 52 bit VA, > we are testing something more important here: exhausting the VA space tests whether > the kernel can truly distinguish b/w virtual and physical memory - we stress the virtual > memory subsystem without touching physical memory, something which the kernel should be able > to handle. But again, any such test has the potential for a timeout. I wonder if there is a > faster way of filling up VA space. > > To summarize, I will agree with you that currently > > 1. The test is in a broken state > 2. The test is taking too much time to test something trivial > 3. It is a maintenance hazard. It turns out that the original version used > MAP_CHUNK_SIZE of 16GB, but then it was changed to 1GB because (this is the bit > where the dependency on VA layout comes) on some systems even a single 16GB mmap > may fail. So now we are stuck in making a tradeoff between the size of a single > mmap versus the time taken by the test > > So the better option seems to just remove the test. Right let's just focus on that. > > A separate question: Do you think that the functionality advertised by validate_complete_va_space, > to check the gaps between VMAs, deserves a test in kunit / tools/testing/vma, or somewhere else? I don't think so as it's not a requirement set in stone as far as I understand it. But expectations as to what get_unmapped_area() should be doing makes more sense as a kunit test. Thanks, Lorenzo
On 20/01/26 2:13 pm, Lorenzo Stoakes wrote: > On Tue, Jan 20, 2026 at 10:59:01AM +0530, Dev Jain wrote: >> I'll reply to everything here otherwise I'll have to repeat myself at different places. >> >> "Also exhausting VA space is an inherently silly thing for a test to do, you're >> making assumptions about existing VMA layout which is absolutely an >> implementation detail and may even be influence by libc..." >> >> The original version only uses mmap() and checks whether we got a high address mmap >> success when we shouldn't have. There are no assumptions being made here about >> VA layout. No matter the VA layout, the test will succeed because the kernel >> must enforce the distinction between low and high addresses (but see point 3 below). >> >> >> "It is therefore ENTIRELY a user-facing and kernel/user API thing that has to be tested from this perspective." >> >> So in merge.c, the statements ASSERT_NE(ptrx, MAP_FAILED) surely assert the >> user-visible API - that mremap must not fail. But there are statements which >> also assert where a VMA starts and where it ends, testing VMA merging - >> I was concerned about these. It is not the goal of userspace to minimize the >> number of VMAs while making a syscall - that is a kernel optimization. My point being, >> I suspect that the mm selftests *already* test internal details a lot, and I believe >> that they *need* to! Running selftests is the most convenient way of testing the mm subsystem. >> Hence this should not be a ground for removal of test. > Dev I would rather try to be positive not negative in review but again, > this isn't constructive, we're not talking about merge.c and even if it > contained the comment /* Ha ha I am a contradiction */ it wouldn't impact > this discussion. > > You're not correct, mremap() has an API requirement that you can't cross > VMA boundaries for most operations, therefore start/end of VMA's and > merging _does_ matter. This also impacts how e.g. madvise() behaves. > > As I said before: > > But you do not - both VMA merge and CoW impact API. Re: merging > certain user-facing functions, most notably mremap(), have API > requirements that the user must not cross VMA boundaries. It is > therefore ENTIRELY a user-facing and kernel/user API thing that has > to be tested from this perspective. > > Can we drop the subject please? I think we are talking past each other, and communication by email has not been the greatest thing, so I'll step back. > >> Talking about the recent commits, they can be reverted. So, the ground for >> removal should be that the ratio of the time taken by the test (exhausting VA >> space), to the coverage of the test (for arm64, it is testing backward compatibility of 48-bit VA >> on 52-bit VA, which one can argue is easy to spot if it ever breaks, and easy to fix) >> is too large and does not justify a selftest. I tend to agree here. >> >> "Add a _new_ selftest, named something sensible like mmap_hint.c or something ..." >> >> va_high_addr_switch.c tests stuff around the switch boundary. But it does not >> exhaust VA space. We *must* exhaust VA space if we are to check that the kernel, >> in a situation of "emergency" (i.e exhausted lower VA space), starts giving out >> high addresses, when it shouldn't. Again, one may argue that trying to test >> this out is not worth it. >> >> I personally opine that besides testing the back compat of 48 bit VA on 52 bit VA, >> we are testing something more important here: exhausting the VA space tests whether >> the kernel can truly distinguish b/w virtual and physical memory - we stress the virtual >> memory subsystem without touching physical memory, something which the kernel should be able >> to handle. But again, any such test has the potential for a timeout. I wonder if there is a >> faster way of filling up VA space. >> >> To summarize, I will agree with you that currently >> >> 1. The test is in a broken state >> 2. The test is taking too much time to test something trivial >> 3. It is a maintenance hazard. It turns out that the original version used >> MAP_CHUNK_SIZE of 16GB, but then it was changed to 1GB because (this is the bit >> where the dependency on VA layout comes) on some systems even a single 16GB mmap >> may fail. So now we are stuck in making a tradeoff between the size of a single >> mmap versus the time taken by the test >> >> So the better option seems to just remove the test. > Right let's just focus on that. > >> A separate question: Do you think that the functionality advertised by validate_complete_va_space, >> to check the gaps between VMAs, deserves a test in kunit / tools/testing/vma, or somewhere else? > I don't think so as it's not a requirement set in stone as far as I > understand it. > > But expectations as to what get_unmapped_area() should be doing makes more > sense as a kunit test. > > Thanks, Lorenzo
On Mon, Jan 19, 2026 at 08:59:01AM +0000, Lorenzo Stoakes wrote: > Anyway. > > Practically speaking I think there are two ways forward here (not mutually > exclusive): > > 1. Implement something in kunit or similar that explicitly tests > get_unmapped_area(). > > 2. Add a _new_ selftest, named something sensible like mmap_hint.c or something, > that runs only on relevant arches, and does NOT try to do crazy stuff like > mapping the entire VA space, but instead simply tries some trial unhinted > mappings some hints in 48-bit space, and some hints in 52-bit space and > asserts things are as expected. > > If you do point 2, please please use a. use the kselftest_harness.h to write the > tests in a nice way (see e.g. guard-regions.c for an example of how it's used) > and b. use the procmap helpers in vm_util.h to check on VMA ranges, you can see > how they're used in... the merge.c tests you so deride :) > > If you or others do both/either I promise to dedicate review resource to the > series(es). That fair enough? > > Thanks, Lorenzo It seems to me that the va_high_addr_switch test is already asserting all we need unless I'm missing something, so unless I'm much mistaken I think simply removing this test is the right way forward. A kunit test for get_unmapped_area() (if possible, as not exported) would still be useful, however. Cheers, Lorenzo
On 19/01/26 2:29 pm, Lorenzo Stoakes wrote:
> On Mon, Jan 19, 2026 at 11:51:47AM +0530, Dev Jain wrote:
>>> Well no, you're asserting gap lengths repeatedly, you are making assertions
>>> about get_unmapped_area() behaviour that are totally inappropriate in a
>>> self-test.
>> Apologies - so I discussed with Aneesh and Anshuman (CCed) and it turns out that the objective
>> of the test was to test the switch boundary. Upon exhaustion of the lower VA space, kernel
>> must not start giving out VMAs in the higher VA space, if the hint address is not given. The
>> original commit is 4e5ce33ceb32 ("selftests/vm: add a test for virtual address range mapping").
> This doesn't change anything, this is still testing get_unmapped_area() which by
> definition is what is returning this.
>
> Also exhausting VA space is an inherently silly thing for a test to do, you're
> making assumptions about existing VMA layout which is absolutely an
> implementation detail and may even be influence by libc...
>
>> I cannot find this API requirement on the man page (because no one bothered to update it),
>> but it is mentioned in Documentation/arch/arm64/memory.rst:
>>
>> "To maintain compatibility with software that relies on the ARMv8.0 VA space maximum size
>> of 48-bits, the kernel will, by default, return virtual addresses to userspace from
>> a 48-bit range.
>>
>> Software can "opt-in" to receiving VAs from a 52-bit space by specifying an mmap hint
>> parameter that is larger than 48-bit."
>>
>> So this is a thing that needs to be tested on arm64, and on ppc64 (for which the test
>> was originally added). Not sure about x86.
> Well 'needs' is strong here...
>
> It would be far more efficient to implement this as a kunit test and wouldn't
> require a extremely slow test that makes assumptions about VMA layout.
>
>> About internal impl details, how is this test any different from merge.c, cow.c,
>> etc - which consistently test/depend on whether the VMA splits/merges?
> This is not a hugely civil/productive way of responding here to be honest, it's
> what-about-ery and implying something that isn't very kind...
Sorry if I have offended you, I did not mean to imply "two wrongs make a right", I
meant to understand how the two tests differ...
>
> But since I am a reasonable if grumpy maintainer, let me indulge you a second
> here.
>
> I thought I'd been clear BUT for avoidance of doubt, I want to remove this test
> because of the COMBINATION of:
>
> 1. It is completely broken and has been broken for some time and nobody noticed.
> 2. It is asserting kernel implementation details.
> 3. It is poorly implemented and breaks often.
> 4. It takes a very long time to run even on fast machines and is a timeout risk.
>
> So even if you had a point, it wouldn't argue against removal.
>
> But you do not - both VMA merge and CoW impact API. Re: merging certain
> user-facing functions, most notably mremap(), have API requirements that the
> user must not cross VMA boundaries. It is therefore ENTIRELY a user-facing and
> kernel/user API thing that has to be tested from this perspective.
>
> CoW is equally a documented and expected behaviour and also affects merging.
>
> Anyway.
>
> Practically speaking I think there are two ways forward here (not mutually
> exclusive):
>
> 1. Implement something in kunit or similar that explicitly tests
> get_unmapped_area().
>
> 2. Add a _new_ selftest, named something sensible like mmap_hint.c or something,
> that runs only on relevant arches, and does NOT try to do crazy stuff like
> mapping the entire VA space, but instead simply tries some trial unhinted
> mappings some hints in 48-bit space, and some hints in 52-bit space and
> asserts things are as expected.
>
> If you do point 2, please please use a. use the kselftest_harness.h to write the
> tests in a nice way (see e.g. guard-regions.c for an example of how it's used)
> and b. use the procmap helpers in vm_util.h to check on VMA ranges, you can see
> how they're used in... the merge.c tests you so deride :)
>
> If you or others do both/either I promise to dedicate review resource to the
> series(es). That fair enough?
>
> Thanks, Lorenzo
On Mon, Jan 19, 2026 at 02:36:05PM +0530, Dev Jain wrote: > >> About internal impl details, how is this test any different from merge.c, cow.c, > >> etc - which consistently test/depend on whether the VMA splits/merges? > > This is not a hugely civil/productive way of responding here to be honest, it's > > what-about-ery and implying something that isn't very kind... > > Sorry if I have offended you, I did not mean to imply "two wrongs make a right", I > meant to understand how the two tests differ... > I'm not offended :) just saying it's distracting from the technical conversation - it's better to remain focused on the problem at hand. I've made a couple technical suggestions that are hopefully reasonable - I think introducing a new, clean, test that asserts very specifically what we want to is a good way forwards here. Thanks, Lorenzo
On Fri, 16 Jan 2026 13:20:53 +0000 Lorenzo Stoakes <lorenzo.stoakes@oracle.com> wrote: [...] > It therefore, sadly, seems that the best course is to remove this test > altogether. > > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Acked-by: SeongJae Park <sj@kernel.org> Thanks, SJ [...]
© 2016 - 2026 Red Hat, Inc.