mirror of
https://github.com/apache/nuttx.git
synced 2026-08-14 00:43:13 +00:00
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>
|
||
|---|---|---|
| .. | ||
| image | ||
| porting-case-studies | ||
| armv7m_runtimestackcheck.rst | ||
| automounter.rst | ||
| building_nuttx_with_app_out_of_src_tree.rst | ||
| building_uclibcpp.rst | ||
| changing_systemclockconfig.rst | ||
| cpp_cmake.rst | ||
| custom_app_directories.rst | ||
| customapps.rst | ||
| customboards.rst | ||
| devicetree.rst | ||
| drivers.rst | ||
| etcromfs.rst | ||
| fork_vfork_migration.rst | ||
| fortify.rst | ||
| fully_linked_elf.rst | ||
| include_files_board_h.rst | ||
| index.rst | ||
| integrate_newlib.rst | ||
| ipv6.rst | ||
| kernel_threads_with_custom_stacks.rst | ||
| logging_rambuffer.rst | ||
| lwl.rst | ||
| multiple_nsh_sessions.rst | ||
| nestedinterrupts.rst | ||
| nfs.rst | ||
| nix_flake.rst | ||
| nsh_network_link_management.rst | ||
| ofloader.rst | ||
| optee.rst | ||
| partially_linked_elf.rst | ||
| platform_directories.rst | ||
| port.rst | ||
| port_bootsequence.rst | ||
| port_drivers_to_stm32f7.rst | ||
| port_relatedkernelconfigrations.rst | ||
| protected_build.rst | ||
| pysimcoder.rst | ||
| qemu_tips.rst | ||
| ram_rom_disks.rst | ||
| reading_can_msgs.rst | ||
| remove_device_drivers_nsh.rst | ||
| renode.rst | ||
| rndis.rst | ||
| rust.rst | ||
| semihosting.rst | ||
| signal_events_interrupt_handlers.rst | ||
| signaling_sem_priority_inheritance.rst | ||
| simulator.rst | ||
| smaller_vector_tables.rst | ||
| specialstuff_in_nuttxheaderfiles.rst | ||
| stm32_ports.rst | ||
| stm32ccm.rst | ||
| stm32nullpointer.rst | ||
| testingtcpip.rst | ||
| thread_local_storage.rst | ||
| updating_release_system_elf.rst | ||
| usbtrace.rst | ||
| usingkernelthreads.rst | ||
| versioning_and_task_names.rst | ||
| zerolatencyinterrupts.rst | ||