arch/arm64: Implement up_addrenv_fork() and provide POSIX fork() - #19773
Draft
casaroli wants to merge 3 commits into
Draft
arch/arm64: Implement up_addrenv_fork() and provide POSIX fork()#19773casaroli wants to merge 3 commits into
casaroli wants to merge 3 commits into
Conversation
Duplicate an address environment into freshly allocated pages mapped at the same virtual addresses, which is what POSIX fork() is built on. It lives in arm64_addrenv_mmu.c: an MPU address environment is a set of protection regions over one physical address space, not a mapping that can be duplicated at the same virtual addresses, so ARCH_HAVE_FORK is conditioned on ARCH_USE_MMU and excludes the protected configurations. arm64_fork_stack() 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. With a zero offset arm64_fork_reloc() is then the identity, so the register context needs no further special casing. Verified on qemu-armv8a:knsh under qemu-system-aarch64: ostest's fork_test reports "Parent and child had independent memory", and vfork_test passes. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The kernel mode section shows the QEMU command but does not say why -semihosting is there. Without it the guest traps in smh_call and stops in AppBringUp, which reads as a kernel defect and is not one. It cost me a session once. Also state that a kernel build is the only mode on this board with POSIX fork(), and that vfork() is available in every mode. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
|
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fork()was withdrawn from every architecture by #19562, and each architecture restores it with the correct behaviour. This pull request restores it for ARM64.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 other half is already in master. #19562 added the saved-syscall-frame path, where
dispatch_syscall()stores the exception frame of the caller inxcp.sregsandarm64_fork()builds the child from it.arm64_fork.calso already takes both paths: a child that keeps the stack addresses of the parent needs no relocation, which is what a duplicated address environment gives it. Only the hook and the Kconfig default were missing.Impact
The change is specific to ARM64. It adds capability and removes none.
fork()becomes available on ARM64 in a kernel build over an MMU.ARCH_HAVE_FORKkeepsdepends on ARCH_ADDRENV, so a configuration without address environments is not affected. A protected build is excluded.vfork()does not change. No board configuration changes.Testing
Emulation only.
qemu-armv8a:knsh, a kernel build, under QEMU 11.0.3 on macOS 15 with Apple Silicon,aarch64-none-elf-gcc14.2.rel1.-semihostingis necessary. A kernel build loads its applications over hostfs, and without the flag the guest traps insmh_calland panics inAppBringUp, which looks like a kernel defect and is not one.ostestruns to the end:tools/checkpatch.sh -c -u -m -ggives no errors.What is not tested
No ARM64 hardware. This is the reason for the draft status.
The protected build is not tested at run time either. The only ARM64 protected configurations in the tree are the ARMv8-R FVPs, and QEMU has no Cortex-R82.
fork()is excluded from a protected build in any case.A report from an ARM64 board is welcome. Take this branch with apache/nuttx-apps#3685, build a kernel configuration and run
ostest. The fork tests are the first output.