[GH-ISSUE #43] kernel: mlock/munlock, MAP_ANON (and msync/madvise/mincore) are unimplemented #35

Closed
opened 2026-11-03 22:02:42 -07:00 by gitea-mirror · 1 comment
Owner

Originally created by @raynorpat on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/43

Summary

Several standard BSD memory calls are unimplemented in kernel-7. The new stress suite (src/Commands/stress, ffs-perf branch) reports them as UNSUP:

Call Where Behaviour
mlock bsd/kern/kern_mman.c:575-582 /* Not yet implemented */, returns EOPNOTSUPP
munlock bsd/kern/kern_mman.c:589-596 same
mmap(..., MAP_ANON, ...) bsd/kern/kern_mman.c:224-228 "Anonymous mapping not supported, for now." Returns EINVAL

Related stubs in the same file, worth fixing alongside:

  • msync (kern_mman.c:442-449), also disabled in init_sysent.c (#warning stubbed out msync).
  • madvise (kern_mman.c:545-552) and mincore (kern_mman.c:561-568).
  • sbrk and sstk (kern_mman.c:100-124).

User space: the v2 image's installed Libc had no mlock/munlock entry points, so the suite binds them through dyld at runtime. src/Libc-1/sys.subproj/SYSCALL-LIST lists them, but there are no mlock.s/munlock.s stubs next to mprotect.s/msync.s in i386.subproj and ppc.subproj.

What the stress suite sees

  • stress-vm wire: UNSUP reason="mlock: ENOSYS", because Libc has no symbol, and the kernel call returns EOPNOTSUPP anyway. Nothing can wire user memory.
  • stress-mmap anon: UNSUP because MAP_ANON returns EINVAL. Programs that expect anonymous mmap fail or need a /dev/zero or vm_allocate fallback. Note that /dev/zero mapping support is its own question.
  • stress-mmap sync: UNSUP reason="msync: ENOSYS".

Proposed work

  1. MAP_ANON: back it with vm_allocate/vm_map of anonymous memory honouring prot, MAP_SHARED/MAP_PRIVATE and MAP_FIXED. The Mach VM already does this for vm_allocate, so this is mostly plumbing in mmap().
  2. mlock/munlock: implement with vm_map_pageable() (wire/unwire the range, KERN_RESOURCE_SHORTAGE → EAGAIN). Also enforce RLIMIT_MEMLOCK and allow it for root only, or within the limit. Add Libc syscall stubs for i386 and ppc.
  3. msync: flush dirty pages of the range to the pager (vm_object_sync/memory_object_lock_request, depending on what kernel-7 exposes), then re-enable the syscall entry.
  4. madvise/mincore: low priority. madvise can return 0 as a hint, and mincore can report residency from the pmap.

Once each lands, the matching stress tests (vm wire, mmap anon, mmap sync) switch from UNSUP to PASS/FAIL automatically and become regression tests for it.

Related: #41 (mapped-file truncation), also from the stress suite.

Originally created by @raynorpat on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/43 ## Summary Several standard BSD memory calls are unimplemented in kernel-7. The new stress suite (`src/Commands/stress`, ffs-perf branch) reports them as UNSUP: | Call | Where | Behaviour | |---|---|---| | `mlock` | `bsd/kern/kern_mman.c:575-582` | `/* Not yet implemented */`, returns `EOPNOTSUPP` | | `munlock` | `bsd/kern/kern_mman.c:589-596` | same | | `mmap(..., MAP_ANON, ...)` | `bsd/kern/kern_mman.c:224-228` | "Anonymous mapping not supported, for now." Returns `EINVAL` | Related stubs in the same file, worth fixing alongside: - `msync` (`kern_mman.c:442-449`), also disabled in `init_sysent.c` (`#warning stubbed out msync`). - `madvise` (`kern_mman.c:545-552`) and `mincore` (`kern_mman.c:561-568`). - `sbrk` and `sstk` (`kern_mman.c:100-124`). User space: the v2 image's installed Libc had no `mlock`/`munlock` entry points, so the suite binds them through dyld at runtime. `src/Libc-1/sys.subproj/SYSCALL-LIST` lists them, but there are no `mlock.s`/`munlock.s` stubs next to `mprotect.s`/`msync.s` in `i386.subproj` and `ppc.subproj`. ## What the stress suite sees - **`stress-vm wire`:** `UNSUP reason="mlock: ENOSYS"`, because Libc has no symbol, and the kernel call returns `EOPNOTSUPP` anyway. Nothing can wire user memory. - **`stress-mmap anon`:** `UNSUP` because `MAP_ANON` returns `EINVAL`. Programs that expect anonymous `mmap` fail or need a `/dev/zero` or `vm_allocate` fallback. Note that `/dev/zero` mapping support is its own question. - **`stress-mmap sync`:** `UNSUP reason="msync: ENOSYS"`. ## Proposed work 1. **`MAP_ANON`:** back it with `vm_allocate`/`vm_map` of anonymous memory honouring `prot`, `MAP_SHARED`/`MAP_PRIVATE` and `MAP_FIXED`. The Mach VM already does this for `vm_allocate`, so this is mostly plumbing in `mmap()`. 2. **`mlock`/`munlock`:** implement with `vm_map_pageable()` (wire/unwire the range, `KERN_RESOURCE_SHORTAGE` → `EAGAIN`). Also enforce `RLIMIT_MEMLOCK` and allow it for root only, or within the limit. Add Libc syscall stubs for i386 and ppc. 3. **`msync`:** flush dirty pages of the range to the pager (`vm_object_sync`/`memory_object_lock_request`, depending on what kernel-7 exposes), then re-enable the syscall entry. 4. **`madvise`/`mincore`:** low priority. `madvise` can return 0 as a hint, and `mincore` can report residency from the pmap. Once each lands, the matching stress tests (`vm wire`, `mmap anon`, `mmap sync`) switch from UNSUP to PASS/FAIL automatically and become regression tests for it. Related: #41 (mapped-file truncation), also from the stress suite.
gitea-mirror 2026-11-03 22:02:42 -07:00
Author
Owner

@raynorpat commented on GitHub (Oct 15, 2026):

Fixed on the ffs-perf branch (merge b148fd5be of issue-43):

  • 87848c750 kernel: MAP_ANON (zero-fill, honours prot, MAP_SHARED shared across fork); mlock/munlock as new syscalls 177/178 (root only, ENOMEM for unmapped or unreadable ranges, EAGAIN past a third of memory wired); msync re-enabled at syscall 65 via vm_synchronize; madvise accepts the standard hints; mincore reports pages entered in the pmap. Also fixes vm_synchronize leaving pagerless pages busy forever (msync of a private or anonymous mapping would hang) and its share-map range translation.
  • 12607a01b Libc: mlock/munlock stubs for i386 and ppc.

mlock/munlock numbers: Mac OS X Server 1.2 never had these calls, and 4.4BSD's 203 is NeXT's getdtablesize here, so they use the unused slots 177/178.

Tested on a snapshot v2 guest with the new kernel: a direct-syscall test passes for every call (anon private/shared/PROT_READ/PROT_NONE, mincore, madvise, mlock/munlock incl. exit while locked, msync of shared, private and anonymous mappings). stress-mmap anon PASS; with syscall shims for the missing Libc symbols, stress-vm wire and stress-mmap sync PASS. No panics. On installed systems wire/sync stay UNSUP until a Libc with the new stubs is installed.

sbrk/sstk stay unimplemented, as in 4.4BSD. It reaches master when ffs-perf is merged.

<!-- gh-comment-id:6193416644 --> @raynorpat commented on GitHub (Oct 15, 2026): Fixed on the ffs-perf branch (merge b148fd5be of issue-43): - 87848c750 kernel: MAP_ANON (zero-fill, honours prot, MAP_SHARED shared across fork); mlock/munlock as new syscalls 177/178 (root only, ENOMEM for unmapped or unreadable ranges, EAGAIN past a third of memory wired); msync re-enabled at syscall 65 via vm_synchronize; madvise accepts the standard hints; mincore reports pages entered in the pmap. Also fixes vm_synchronize leaving pagerless pages busy forever (msync of a private or anonymous mapping would hang) and its share-map range translation. - 12607a01b Libc: mlock/munlock stubs for i386 and ppc. mlock/munlock numbers: Mac OS X Server 1.2 never had these calls, and 4.4BSD's 203 is NeXT's getdtablesize here, so they use the unused slots 177/178. Tested on a snapshot v2 guest with the new kernel: a direct-syscall test passes for every call (anon private/shared/PROT_READ/PROT_NONE, mincore, madvise, mlock/munlock incl. exit while locked, msync of shared, private and anonymous mappings). stress-mmap anon PASS; with syscall shims for the missing Libc symbols, stress-vm wire and stress-mmap sync PASS. No panics. On installed systems wire/sync stay UNSUP until a Libc with the new stubs is installed. sbrk/sstk stay unimplemented, as in 4.4BSD. It reaches master when ffs-perf is merged.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
github-starred/RhapsodiOS#35
No description provided.