Skip to content

zpoline nommu - #1

Draft
thehajime wants to merge 65 commits into
uml-nextfrom
zpoline-nommu-v6.10
Draft

zpoline nommu#1
thehajime wants to merge 65 commits into
uml-nextfrom
zpoline-nommu-v6.10

Conversation

@thehajime

Copy link
Copy Markdown
Owner

No description provided.

Comment thread arch/um/include/asm/mmu.h Outdated
Comment thread arch/um/include/asm/tlbflush.h Outdated
Comment thread arch/x86/um/zpoline.c Outdated
Comment thread arch/x86/um/zpoline.c Outdated
Comment thread arch/x86/um/zpoline.c Outdated
Comment thread arch/x86/um/syscalls_64.c Outdated
Comment thread tools/testing/selftests/vDSO/Makefile Outdated
Comment thread arch/x86/um/syscalls_64.c Outdated
Comment thread arch/x86/um/Makefile
@thehajime
thehajime force-pushed the zpoline-nommu-v6.10 branch 19 times, most recently from 9b86626 to a754e79 Compare September 17, 2024 10:28
Comment thread arch/x86/um/do_syscall_64.c Outdated
Comment thread arch/x86/um/do_syscall_64.c Outdated
Comment thread arch/x86/um/nommu/entry_64.S
Comment thread arch/x86/um/asm/elf.h
Comment thread arch/x86/um/zpoline.c Outdated
Comment thread arch/x86/um/zpoline.c Outdated
@thehajime
thehajime force-pushed the zpoline-nommu-v6.10 branch 2 times, most recently from 90042db to 3496039 Compare September 18, 2024 06:18
@thehajime thehajime changed the title Zpoline nommu v6.10 zpoline nommu Sep 18, 2024
@thehajime
thehajime force-pushed the zpoline-nommu-v6.10 branch 2 times, most recently from 3e8124f to ddc2ef9 Compare September 19, 2024 05:17
@thehajime

thehajime commented Sep 21, 2024

Copy link
Copy Markdown
Owner Author

for the record:

lmbench (usec)

native um um-nommu
select-10 0.2584 28.7245 0.2751
select-100 0.7548 31.3977 0.9887
select-1000 5.7399 60.8596 8.4134
syscall 0.0806 11.4508 0.0780
read 0.1464 19.6901 0.1166
write 0.1110 27.3296 0.1140
stat 1.5114 46.2612 0.4372
open/close 283.9560 101.4579 0.7859
fork+sh 3539.0000 15725.0000 38561.0000
fork+execve 1679.5714 5462.0000 9611.0000

do_getpid bench (nsec)

native um um-nommu
getpid 117 24733 83

image

thehajime and others added 13 commits August 8, 2026 09:26
sometimes fs register is referenced before __kernel_vsyscall, resulitng
an invalid access as it's on different value.  this commit fixes this
issue.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
WIP/FIXME

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
…nd_for_mapping()

ramfs_nommu_expand_for_mapping() sets the new i_size before it has
allocated or inserted any of the contiguous backing pages.

If alloc_pages() or add_to_page_cache_lru() fails, the inode is left
with an inflated i_size and possibly a partial run of pages.  As
ramfs_nommu_setattr() treats a truncate to the current i_size as a
no-op, the expansion cannot be retried and shared mmap() of the file
fails with -ENOSYS.

Setting i_size early also races with lockless readers: buffered reads
and splice do not take i_rwsem, so once the new size is visible a
concurrent read can instantiate a zero-filled folio, making the
expansion's add_to_page_cache_lru() fail with -EEXIST.

Fix this by taking mapping->invalidate_lock around the insertion,
evicting any stray folios first, and only publishing i_size once
every page is in place.

On failure, after freeing the pages that were allocated but
not inserted truncate the mapping back to empty so already inserted
pages are also disposed of.

Fixes: 642fb4d ("[PATCH] NOMMU: Provide shared-writable mmap support on ramfs")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/message/20260523130445.1101818-1-daniel%40thingy.jp
Assisted-by: Claude:claude-5-fable # expanded my fix to address the reader race etc.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
Currently trying to use memfd_create() on nommu returns
an error with errno set to EFBIG. The manpage memfd_create()
doesn't have EFBIG as a possible error value.

Doing some digging this is coming from 0 getting passed as
newsize to ramfs_nommu_expand_for_mapping() and that getting
into get_order() and there "The result is undefined if the size is 0".

Whatever comes out of get_order() is then used in the following
logic and that results in the EFBIG that causes the syscall
to fail and the errno in userspace.

If newsize is 0 there is nothing to do so just return.

Roughly tested on m68k nommu by creating a process, creating
an memfd, forking another process, mmap()ing the memfd in the
child, writing into the mapping, then mmap()ing in the parent
and checking that the right data is there.

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
Acked-by: Lorenzo Stoakes <ljs@kernel.org>
@github-actions

Copy link
Copy Markdown

lmbench (usec)

native um um-mmu(s) um-nommu um-nommu(sas-s) um-nommu(sas-z) um-nommu(s)
select-10 0.9271 33.6971 25.2691 24.8756 4.2938 0.3645 36.7134
select-100 2.0369 33.4325 26.1035 24.6362 4.8961 1.2694 36.9874
select-1000 13.3839 37.5261 34.3402 25.2143 13.1078 10.1844 51.2207
syscall 0.5785 29.6874 26.0291 23.3166 3.8021 0.1593 30.3575
read 0.7574 26.8670 29.6246 20.8436 3.9042 0.2281 30.2980
write 0.7047 27.3199 31.2559 22.9221 3.9122 0.2129 29.3384
stat 2.4164 60.9426 33.0458 29.8187 32.1100 25.5973 56.6621
open/close 4.2296 108.0509 62.6881 59.0429 47.7871 36.1742 119.9733
fork+sh 1258.6667 6565.0000 3322.5000 1738.3333 1494.7143 19901.0000 2788.5000
fork+execve 578.9444 2678.7500 1280.3333 682.1250 663.4118 5351.0000 1148.6000

do_getpid bench (nsec)

native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
getpid 572 30365 27968 19957 36378 3796 165

iperf3 bench (Mbps)

native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
iperf3(f) 24555 4935 8662 10951 4604
iperf3(r) 24431 6975 10141 11783 6336

netperf bench (TCP_STREAM) (Mbps)

psize native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)

netperf bench (TCP_MAERTS) (Mbps)

psize native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)

Imgur Images Imgur Images Imgur Images

LTP results

passed failed broken skipped warnings
native 9883 80 19 241 0
mmu 9077 69 20 513 2
mmu-s 9076 70 20 513 2
nommu 6755 71 4 1039 4
nommu-s 6758 70 4 1039 4
nommu-sas-seccomp 6770 81 4 1039 4
nommu-sas-zpoline 6757 69 4 1039 4
riscv-nommu 4067 137 53 653 5

native report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127779054
um-mmu report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127990362
um-mmu-seccomp report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127947542
um-nommu report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127457035
um-nommu-seccomp report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127438970
um-nommu-sas-seccomp report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127392136
um-nommu-sas-zpoline report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127438148
riscv-nommu report: https://github.com/thehajime/linux/actions/runs/31557789951/artifacts/9127405196

@github-actions

Copy link
Copy Markdown

lmbench (usec)

native um um-mmu(s) um-nommu um-nommu(sas-s) um-nommu(sas-z) um-nommu(s)
select-10 0.9262 26.8309 27.5499 32.7021 4.0507 0.3633 28.6601
select-100 2.0356 27.9132 30.6145 28.5309 4.8820 1.2352 29.8583
select-1000 13.3919 35.6206 48.3333 37.7750 13.1241 9.8639 36.7319
syscall 0.5780 27.9293 29.9995 29.7698 3.7823 0.1588 33.2600
read 0.7568 30.8259 33.6236 28.3201 3.8818 0.2395 27.8352
write 0.7016 28.9476 28.8489 31.3233 3.8527 0.2111 28.5236
stat 2.4268 39.4915 56.2526 57.2710 31.7648 25.5745 36.4928
open/close 4.2303 67.8811 112.8637 101.3019 46.7856 35.8696 65.0563
fork+sh 1265.1111 6034.5000 4216.0000 2524.4000 1495.1250 20014.0000 1698.1429
fork+execve 573.3333 2388.6000 1726.0000 1004.9091 656.0588 5379.5000 792.3571

do_getpid bench (nsec)

native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
getpid 572 32660 27909 29563 28134 3781 179

iperf3 bench (Mbps)

native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
iperf3(f) 23876 9459 4471 4847 9171 5737 4969
iperf3(r) 20576 10172 6193 6945 9559 9968 11865

netperf bench (TCP_STREAM) (Mbps)

psize native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
64 253.29 10.26 5.00 5.99 10.06 11.97 14.78
128 725.49 20.89 10.42 11.61 19.68 21.55 15.62
256 1389.61 41.60 21.00 23.01 39.74 45.80 42.07
512 2567.46 82.97 42.22 46.74 80.23 96.90 115.15
1024 4311.35 164.24 83.16 95.88 159.51 217.49 132.93
1500 5613.57 217.06 128.29 133.19 220.06 311.73 197.27
65507 20122.17 6491.30 3477.02 3573.14 6225.89 5346.78 4379.58

netperf bench (TCP_MAERTS) (Mbps)

psize native um um-mmu(s) um-nommu um-nommu(s) um-nommu(sas-s) um-nommu(sas-z)
64 252.43 905.87 323.26 330.07 834.57 281.78 295.76
128 713.33 1421.69 525.47 566.44 1268.74 371.57 356.64
256 1369.23 2751.46 843.02 832.20 2583.23 556.21 594.98
512 2534.92 3340.06 1420.83 1316.75 3828.17 824.21 800.71
1024 4277.19 5444.19 1922.41 1927.22 4934.98 1351.02 1084.75
1500 5615.28 9800.84 2420.98 2247.24 7358.21 1820.51 1777.22
65507 20120.25 28078.87 23117.68 24175.82 27125.66 26883.46 26863.96

Imgur Images Imgur Images Imgur Images

LTP results

passed failed broken skipped warnings
native 9884 79 19 241 0
mmu 9077 69 20 512 2
mmu-s 9079 67 20 513 2
nommu 6757 69 4 1039 4
nommu-s 6757 69 4 1039 4
nommu-sas-seccomp 6770 81 4 1039 4
nommu-sas-zpoline 6757 69 4 1039 4
riscv-nommu 4067 137 53 653 5

native report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165723601
um-mmu report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165912306
um-mmu-seccomp report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165858301
um-nommu report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165351206
um-nommu-seccomp report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165344857
um-nommu-sas-seccomp report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165281358
um-nommu-sas-zpoline report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165331108
riscv-nommu report: https://github.com/thehajime/linux/actions/runs/31656195135/artifacts/9165278267

Upon a private file mapping request to /dev/zero, it calls
kernel_read() in do_mmap_private(), getting a failure with the message
like: "kernel reads not supported for file /dev/zero", which is because
zero_fops defined in drivers/char/mem.c has both .read and .read_iter
definitions.

Even fixing this issue, the map request to /dev/zero works fine without
errors but the allocated vma isn't marked with anonymous because
mmap_zero_prepare() isn't called under nommu platform, resulting
vma_desc_set_anonymous() isn't called either.

This commit fixes those issues by:
1) use vfs_iter_read() instead to avoid failure at kernel_read()
2) calls .mmap_prepare on private mapping in do_mmap() so that required
   preparations are done even in private mapping.

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-mm@kvack.org (open list:PAGE CACHE)
Fixes: 4d03e3c ("fs: don't allow kernel reads and writes without iter ops")
Assisted-by: cubic.dev:unspecified
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
When shrinking a VMA via mremap, the bounds are modified directly:
mm/nommu.c:do_mremap() {
    ...
    vma->vm_end = vma->vm_start + new_len;
    ...
}
This shrinks the VMA without updating its bounds in the maple tree.
If the maple tree (mm->mm_mt) still contains the old bounds, a user
process could access the freed portion. The stale maple tree would
incorrectly return the shrunk VMA for an address past its new vm_end.

This commit fixes this issue by calling vmi_shrink_vma() when shrink
happens.  Additionally, if a file-backed, non-anonymous map is to be
shrunk, it reports -EINVAL like do_munmap() does.

Moreover, to maintain i_mmap interval tree, two functions,
add_vma_to_mapping() and remove_vma_from_mapping(), are decoupled from
setup_vma_to_mm() and cleanup_vma_from_mm() respectively.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: linux-mm@kvack.org
Closes: https://sashiko.dev/#/patchset/20260702012546.665383-1-thehajime@gmail.com
Closes: https://sashiko.dev/#/patchset/20260710021028.892645-1-thehajime%40gmail.com
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>

--

v1 -> v2:
- handle error when vmi_shrink_vma() failed (reported by Sashiko)
- prevents mremap() with being shrunk for file-backed one like munmap()
- consider i_mmap updates on shrink/expand by calling newly decoupled
  functions, add_vma_to_mapping()/remove_vma_from_mapping()

v1: https://lore.kernel.org/linux-mm/20260710021028.892645-1-thehajime@gmail.com/
Then update split_vma() so both the old and newly created VMA remain covered by the same mapping lock:
 For vmi_shrink_vma(), keep the mapping lock held through the Maple-tree operation and reinsert the VMA before releasing it:
And apply the same pattern to the growth branch:
response to sashiko review:
This does not produce incorrect contents for /dev/zero, since reading
/dev/zero also returns zeroes. However, private /dev/zero mappings are
semantically anonymous, so the growth path now zero-fills them directly
rather than performing unnecessary device I/O.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Private file mappings (like those from /dev/zero) can have vma->vm_file
set but remain structurally anonymous since they lack vm_ops. Testing
vma->vm_file instead of vma_is_anonymous(vma) might cause mremap to
return a spurious -EINVAL when userspace attempts to shrink these
mappings.

This commit fixes this issue by using vma_is_anonymous() instead of
testing vma->vm_file to address the case of /dev/zero.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: linux-mm@kvack.org
Closes: https://sashiko.dev/#/patchset/20260710054648.924005-1-thehajime%40gmail.com
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Some nommu architectures only work on Alpine Linux, which doesn't use
glibc for the standard library.  It uses musl-libc and is implemented in
a different way as glibc, resulting build failures.

This commit fixes this issue by adding missing definitions. The fixes
are now only covered to TARGETS=mm which was tested for the moment;
future contributions are needed to fully build/execute tests on nommu
platforms.

Cc: Shuah Khan <shuah@kernel.org>
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: linux-kselftest@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-um@lists.infradead.org
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Architectures lacks MMU doesn'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 build stage, add -DCONFIG_NOMMU to CFLAGS when NOMMU=1 variable
  added to the build/make argument.
- 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.
- kselftest_harness.h warns if the file is include when building for
  NOMMU platform, as there is no fork(2) syscall.
- replace "cd -" use as it is not available a shell supported on nommu
  (e.g., busybox hush), use cd "$OLDDIR" instead.
- 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
 $ make ARCH=um NOMMU=1 -C tools/testing/selftests/mm run_tests
 $ NOMMU=1 /tmp/kselftest_install/run_kselftest.sh -s -c mm

Cc: Shuah Khan <shuah@kernel.org>
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 <jackmanb@google.com>
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
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
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. MAP_UNINITIALIZED allocations via optional kernel configurations.
4. Regular file mappings via standard filesystem storage.
5. Memory-backed file mapping with /dev/zero
6. Block device subsystem mappings (gracefully skipping if node is
   missing).
7. Shared vs Private backing discrepancies under nommu conditions.
8. 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
Assisted-by: Gemini:Pro [AI_Reviewer] [Sashiko_Linter]
Assisted-by: cubic.dev:unspecified
Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

uml + veth for docker

5 participants