casaroli opened a new pull request, #19774: URL: https://github.com/apache/nuttx/pull/19774
> **Draft.** The evidence is emulation only. I keep this as a draft until `fork()` runs on RISC-V 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 RISC-V. `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 was already in the tree before #19562. `riscv_swint.c` stores the exception frame of the caller in `xcp.sregs`, and `riscv_fork.c` builds the child from it. RISC-V was the architecture the other ports copied for that. `riscv_fork.c` also loses a duplicate branch. The review round of #19562 added the same-virtual-address shortcut to that file, and this commit added its own copy of it. One remains. ## Impact The change is specific to RISC-V. It adds capability and removes none. `ARCH_HAVE_FORK` takes `default y if ARCH_RISCV`. That is broader than the condition the other architectures use, so the guard matters: `depends on ARCH_ADDRENV && !ARCH_STACK_DYNAMIC`. A configuration without address environments is unaffected, and a protected build is excluded, MPU and MMU alike. A protected build has one address space, protected by a fixed set of regions, and a second copy of a process at the same virtual addresses has no meaning there. `vfork()` does not change. No board configuration changes. Nine RISC-V chips select `ARCH_HAVE_ADDRENV` today: MPFS, QEMU_RV, JH7110, BL808, K230, SG2000, EIC7700X and two LiteX cores. `fork()` becomes available on those, in a kernel build. ## Testing Emulation only. QEMU 11.0.3 on macOS 15 with Apple Silicon, xPack `riscv-none-elf-gcc` 14.2.0-3. | configuration | width | result | |---|---|---| | `rv-virt:knsh_romfs` | 32-bit | `vfork()` and `fork()` pass, status 0 | | `rv-virt:knsh64` | 64-bit | `vfork()` and `fork()` pass, status 0 | ``` qemu-system-riscv32 -M virt,aclint=on -cpu rv32 -kernel nuttx -nographic qemu-system-riscv64 -semihosting -M virt,aclint=on -cpu rv64 -kernel nuttx -nographic ``` Do not add `-bios none` to the 32-bit command. Without OpenSBI the guest prints nothing at all, which reads as a boot failure and is not one. The 64-bit configuration loads its applications over hostfs and needs `-semihosting`. ``` 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. ### What is not tested No RISC-V hardware. This is the reason for the draft status. `rv-virt:knsh` does not boot here, and it does not boot at the merge base either, so I used `rv-virt:knsh_romfs` for the 32-bit row. **A report from a RISC-V 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. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
