Skip to content

arch/x86_64: Implement up_addrenv_fork() and provide POSIX fork() - #19776

Draft
casaroli wants to merge 2 commits into
apache:masterfrom
casaroli:x86_64-fork
Draft

arch/x86_64: Implement up_addrenv_fork() and provide POSIX fork()#19776
casaroli wants to merge 2 commits into
apache:masterfrom
casaroli:x86_64-fork

Conversation

@casaroli

Copy link
Copy Markdown
Contributor

Draft. The evidence is emulation only. I keep this as a draft until fork() runs on x86_64 hardware.

Summary

fork() was withdrawn from every architecture by #19562, and each architecture restores it with the correct behaviour. This pull request restores it for x86_64.

up_addrenv_fork() duplicates an address environment into freshly allocated pages mapped at the same virtual addresses. The text, data and heap regions of the source are walked one page at a time and copied into fresh pages hung off the page tables of the child.

The saved-syscall-frame half is already in master. #19562 added it, so x86_64_syscall() stores the exception frame of the caller in xcp.sregs and x86_64_fork() chooses between x86_64_fork_syscall() and x86_64_fork_direct().

Impact

The change is specific to x86_64. It adds capability and removes none.

fork() becomes available on x86_64 outside a protected build. ARCH_HAVE_FORK keeps depends on ARCH_ADDRENV, so a configuration without address environments is unaffected.

vfork() does not change. No board configuration changes.

Testing

Emulation only. QEMU 11.0.3 on macOS 15 with Apple Silicon, x86_64-elf-gcc 16.1.0. There is no hardware x86 acceleration on this host, so this ran under TCG.

qemu-intel64:knsh_romfs, a kernel build:

qemu-system-x86_64 -machine pc,hpet=on -cpu max -m 2G \
  -kernel nuttx -nographic -no-reboot -net none
user_main: vfork() test
vfork_test: Child 6 ran and exited before the parent resumed
user_main: fork() test
fork_test: Child running independently (child)
fork_test: Parent and child had independent memory
ostest_main: Exiting with status 0

tools/checkpatch.sh -c -u -m -g gives no errors.

Two notes for anyone repeating this under TCG. -cpu max is the flag that matters, and a named Intel model is much slower. Three configuration changes are necessary as well: disable ARCH_INTEL64_HAVE_PCID and ARCH_INTEL64_TSC_DEADLINE, and enable ARCH_INTEL64_HPET_ALARM. Without them the console stops after SeaBIOS and looks like a hang.

What is not tested

No x86_64 hardware, and no KVM. This is the reason for the draft status.

The protected build is excluded by the Kconfig condition and is not tested.

A report from real x86_64 hardware is welcome. Take this branch with apache/nuttx-apps#3685, build qemu-intel64:knsh_romfs and run /system/bin/ostest. The fork tests are the first output.

Duplicate an address environment into freshly allocated pages mapped at the
same virtual addresses, which is what POSIX fork() is built on.

x86_64_fork_syscall() then lets the child run at the parent's stack addresses.
A pointer to a stack local taken before fork() must name the same object in
the child that it named in the parent, so the child adopts the parent's stack
geometry rather than being given a relocated copy; the parent's stack is
already in the duplicate, at the parent's address, with its contents.  That
shows up as a zero offset, which also means the copy would have the same
source and destination, so both the copy and the frame-pointer relocation are
skipped.

Build-verified on qemu-intel64:knsh_romfs.  NuttX on qemu-intel64 requires
tsc-deadline and pcid, which TCG does not implement, so it cannot be run on
this host.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Arch: x86_64 Issues related to the x86_64 architecture Size: M The size of the change in this PR is medium labels Aug 10, 2026
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

qemu-armv8a

  • Code: .text.romfs_cachenode +4 B (+0.0%, 316,720 B)

s698pm-dkit

Review of apache#19772 asked for this shape, and it applies to every architecture in
the series.

ARCH_HAVE_FORK described when it was available from inside its own definition,
which put the per-architecture condition somewhere nobody looks.  The
architecture now says so itself.

The condition repeats the ARCH_ADDRENV dependency rather than relying on it,
because a select bypasses depends on:  without that repetition an architecture
could offer fork() where there is no address environment to duplicate.

Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: x86_64 Issues related to the x86_64 architecture Area: Documentation Improvements or additions to documentation Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant