Skip to content

feat(system): source linux page_size from AT_PAGESZ (#336)#343

Merged
octalide merged 3 commits into
devfrom
feat/336-auxv-pagesz
Jul 2, 2026
Merged

feat(system): source linux page_size from AT_PAGESZ (#336)#343
octalide merged 3 commits into
devfrom
feat/336-auxv-pagesz

Conversation

@octalide

@octalide octalide commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Closes #336.

What

std.system.os.linux.{aarch64,riscv64,x86_64}.page_size() hardcoded ret 4096, wrong on aarch64 kernels configured for 16 KiB or 64 KiB pages. This sources the page size from AT_PAGESZ in the auxiliary vector instead.

  • shared (src/system/os/linux/shared.mach): add _pagesz (the runtime page size, 0 = unavailable), pagesz_from_auxv(envp) (walks envp to its NULL terminator, then scans the auxv for AT_PAGESZ), and capture_pagesz() (publishes the walk result into _pagesz, reading the already-set _envp).
  • per-arch page_size(): read shared._pagesz, falling back to 4096 only when the auxv genuinely lacked AT_PAGESZ. All three linux arches converge on the one source.
  • entrypoints (src/runtime/linux/*): each _rt_init calls os.capture_pagesz() right after os._envp = _rt_envp.

Capture / ordering design

_rt_init runs, in order: (--pie only) reloc._rt_relocate(...), then os._envp = _rt_envp, then os.capture_pagesz(). So the capture happens after relocation and after _envp is set — it is ordinary post-relocation code that may freely touch globals.

std.runtime.linux.reloc keeps its own private pre-relocation read of AT_PAGESZ (for the RELRO mprotect): that pass runs before any global is safe to reference and is deliberately position-independent, so it cannot consume the OS-layer global. The two reads serve different constraints at different times; the OS layer is the single consumer-facing page-size source of truth, which is what #336 asked for.

Verification

  • mach build . and mach test . — 571 passed, 0 failed.
  • test/riscv64/verify.sh (repo smoke test) — passes under qemu-riscv64.
  • A probe that independently walks its own auxv for AT_PAGESZ and asserts os.page_size() == AT_PAGESZ, shared._pagesz != 0 (capture ran), and shared._pagesz == page_size() — exits 0 on x86_64 native, riscv64/qemu, aarch64/qemu, both default and --pie builds. (This qemu-user build presents a fixed 4 KiB page and cannot override it, so a live 16 KiB/64 KiB run is not reproducible locally; the probe proves the value is auxv-sourced rather than a literal.)

🤖 Generated with Claude Code

octalide added 2 commits July 2, 2026 11:27
page_size() on linux hardcoded 4096, wrong on aarch64 kernels running 16 KiB
or 64 KiB pages. Capture AT_PAGESZ from the auxiliary vector once at startup
into a shared OS-layer global (_pagesz) and have each arch's page_size() read
it, falling back to 4096 only when the auxv genuinely lacks it.

The entrypoint publishes the value via capture_pagesz() right after _envp, and
(under --pie) after _rt_relocate has applied the relocations, so it is ordinary
post-relocation code that may touch globals. std.runtime.linux.reloc keeps its
own private pre-relocation read of AT_PAGESZ for the RELRO mprotect, since that
runs before any global is safe to reference; the OS layer is the single
consumer-facing page-size source of truth.

Closes #336
@octalide octalide marked this pull request as ready for review July 2, 2026 15:32
page_size() fell back to 4096 when the captured _pagesz was 0. AT_PAGESZ is
mandatory on linux, so a 0 at call time means the auxv lacked it (broken or
nonstandard environment) or a caller ran before _rt_init published — and on a
large-page kernel the fallback would hand that early caller 4096 while later
callers see 16K, an inconsistency worse than either constant. Panic naming the
invariant rather than fabricating a value; no in-tree caller runs before the
startup capture, so the normal path is unaffected.
@octalide octalide merged commit f5fa077 into dev Jul 2, 2026
2 checks passed
@octalide octalide deleted the feat/336-auxv-pagesz branch July 2, 2026 15:45
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.

runtime: surface AT_PAGESZ to the OS layer (page_size() hardcodes 4096)

1 participant