nuttx/Documentation/guides
Marco Casaroli 067e30e14f arch/x86_64: Build fork() children from the caller's syscall frame.
In a kernel build vfork() is reached through a system call, so the return
address and stack pointer the architecture's entry point can see for itself
are the kernel's, not the caller's.  A child built from those resumes at a
kernel address, which is why x86_64 selected the fork family only for the
flat build.

x86_64_syscall() now publishes the caller's frame in xcp.sregs for the
duration of the stub call, and x86_64_fork() builds the child from it:

  x86_64_fork_syscall()  when xcp.sregs is non-NULL, so that the child
                         returns from the very same `syscall' instruction as
                         the parent, in user mode, on its own stack;
  x86_64_fork_direct()   otherwise, which is the flat build and any kernel
                         thread that calls the entry point as a plain
                         function.

The discriminator is xcp.sregs rather than TCB_FLAG_SYSCALL, which arm64 and
RISC-V use:  that flag also defers signal actions, x86_64 has never raised it,
and its kernel-build signal path does not survive being made to -- a
pre-existing problem that does not belong to this work.

Two properties of SYSCALL/SYSRET shape the child's frame.  The instruction
leaves the caller's RIP and RFLAGS in RCX and R11 rather than on a stack, so
they are moved into the RIP and RFLAGS slots of the interrupt frame the child
is resumed from; and the hardware never records the caller's CS and SS at all,
SYSRETQ reconstructing them from IA32_STAR, so the child's are filled in with
the user code and data selectors at RPL 3.  The frame is therefore not copied
wholesale:  the extended state and the general registers are inherited, while
the segment registers and the thread pointer stay as up_initial_state() left
them, the child's stack being a fresh allocation the parent's FS base does not
describe.

x86_64_fork_relocfp() is new and is not optional here.  A function returns
with `leave', which feeds the frame pointer into the stack pointer, so
relocating only the RBP the child resumes with gets it exactly one frame:
the next return loads a saved RBP still pointing into the parent's stack.

With that in place ARCH_X86_64 can select ARCH_HAVE_VFORK unconditionally.

Build-verified on qemu-intel64:knsh_romfs and qemu-intel64:ostest.  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>
2026-08-10 08:57:30 -03:00
..
image docs/guides/bootsequence: Migrate UML diagram to PlantUML 2026-02-15 08:47:23 +01:00
porting-case-studies !arch/arm: Use r9 as the PIC base register. 2026-08-06 01:38:23 +08:00
armv7m_runtimestackcheck.rst style: Fix "the the" typo across the codebase. 2026-03-23 11:07:49 +01:00
automounter.rst
building_nuttx_with_app_out_of_src_tree.rst
building_uclibcpp.rst
changing_systemclockconfig.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
cpp_cmake.rst Documentation/guides: Update CMake C++ guide 2025-09-15 15:30:15 -03:00
custom_app_directories.rst
customapps.rst
customboards.rst docs/guides/customboards: Mention special Kconfig settings 2026-06-18 21:51:48 +08:00
devicetree.rst
drivers.rst
etcromfs.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
fork_vfork_migration.rst arch/x86_64: Build fork() children from the caller's syscall frame. 2026-08-10 08:57:30 -03:00
fortify.rst
fully_linked_elf.rst docs: Update the ELF guides 2025-06-11 23:11:08 +08:00
include_files_board_h.rst style: Fix "the the" typo across the codebase. 2026-03-23 11:07:49 +01:00
index.rst !Documentation: Describe the fork()/vfork() split. 2026-08-10 08:57:30 -03:00
integrate_newlib.rst style: fix typos 2025-04-30 13:45:46 +08:00
ipv6.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
kernel_threads_with_custom_stacks.rst sched/task: fix Redundant memory allocation. 2026-01-01 07:25:04 -03:00
logging_rambuffer.rst
lwl.rst docs/guides/lwl: move lwl's README.txt to lwl.rst 2025-12-23 15:20:06 +01:00
multiple_nsh_sessions.rst
nestedinterrupts.rst
nfs.rst
nix_flake.rst tools/nix: move nix flakes to tools/ 2025-08-28 10:04:01 +08:00
nsh_network_link_management.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
ofloader.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
optee.rst drivers/misc/optee: Expanded RPC support. 2025-08-06 02:29:33 +08:00
partially_linked_elf.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
platform_directories.rst style: fix typos 2025-04-30 13:45:46 +08:00
port.rst style: fix typos 2025-04-30 13:45:46 +08:00
port_bootsequence.rst docs/guides/bootsequence: Migrate UML diagram to PlantUML 2026-02-15 08:47:23 +01:00
port_drivers_to_stm32f7.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
port_relatedkernelconfigrations.rst
protected_build.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
pysimcoder.rst Documentation: fix spelling 2025-05-15 11:33:41 +08:00
qemu_tips.rst Documentation: add notes about TAP configuration for qemu 2025-12-18 11:39:54 -03:00
ram_rom_disks.rst
reading_can_msgs.rst nuttx/can: add message alignment 2025-11-24 14:11:41 +08:00
remove_device_drivers_nsh.rst
renode.rst !arch/stm32h7: use common STM32 Kconfig symbols 2026-06-14 11:35:31 -03:00
rndis.rst style: fix typos 2025-04-30 13:45:46 +08:00
rust.rst !sched/clock: remove CONFIG_SYSTEM_TIME64 and always use 64-bit time 2026-05-19 16:21:28 +08:00
semihosting.rst doc: Add semihost syslog guide instructions 2025-10-24 09:56:24 +08:00
signal_events_interrupt_handlers.rst
signaling_sem_priority_inheritance.rst
simulator.rst Documentation: add nxmodbus doc 2026-04-21 09:39:04 +08:00
smaller_vector_tables.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
specialstuff_in_nuttxheaderfiles.rst
stm32_ports.rst arch/arm/src/stm32: unify pulse count driver into common/stm32 2026-07-12 09:35:51 +08:00
stm32ccm.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
stm32nullpointer.rst style: Fix "the the" typo across the codebase. 2026-03-23 11:07:49 +01:00
testingtcpip.rst
thread_local_storage.rst
updating_release_system_elf.rst
usbtrace.rst !boards: Remove NSH_ARCHINIT and board_app_initialize 2026-05-02 18:36:46 +08:00
usingkernelthreads.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00
versioning_and_task_names.rst Documentation/Make: add implementation/make_build_system.rst 2025-11-20 09:39:16 -05:00
zerolatencyinterrupts.rst !arch/stm32: move stm32l1 and finalize the directory split 2026-06-24 14:54:44 -03:00