Skip to content

aarch64 stage2: move fork save-area to Entry 2 (fix nested-fork hang)#9

Merged
alganet merged 1 commit into
mainfrom
aarch64-fork-savearea-fix
Jun 16, 2026
Merged

aarch64 stage2: move fork save-area to Entry 2 (fix nested-fork hang)#9
alganet merged 1 commit into
mainfrom
aarch64-fork-savearea-fix

Conversation

@alganet

@alganet alganet commented Jun 16, 2026

Copy link
Copy Markdown
Owner

The fork-emulation save area (a bump allocator that memcpy's the parent's whole process image plus its kernel and user stacks on every clone) was initialized at VA 0x78000000 -- inside paging Entry 1, growing up toward the kernel-stack top at 0x7B800000. That gave it only ~56MB AND backed it directly onto the live, descending kernel stack.

A process with a heap of tens of MB therefore overran the save area into the kernel stack on its first fork, corrupting return addresses -> silent hang (a CPU fault would have printed "!EC:..." and exited 139 instead). hs hit this running its probe sweep (hs forks+execs hs; its startup heap is ~55MB), where riscv64 -- whose save area is 576MB and separate from the kernel stack -- did not. The header comment already documented the intended Entry-2 layout ("saved process mem at 0xB0000000"); the code just shipped the wrong base.

Relocate the save area to VA 0x80000000 (Entry 2, identity-mapped): ~540MB up to file data at 0xA1900000, clear of the kernel stack. One constant.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to fix an AArch64 stage2 nested-fork hang by relocating the fork-emulation “saved process memory” bump allocator away from the live kernel stack region by changing its initialization base address (and updating the corresponding documentation/encoded outputs).

Changes:

  • Update the documented memory layout to describe the saved-process-memory region as being in paging Entry 2.
  • Change next_save_process_address initialization from 0x78000000 to 0x80000000 in the AArch64 stage2 source.
  • Propagate the same change into the .hex2 and .hex0 representations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
builder-hex0-aarch64-stage2.S Updates memory-layout comments and the save-area base initialization constant.
builder-hex0-aarch64-stage2.hex2 Mirrors the updated save-area base in the hex2-encoded stage2 output.
builder-hex0-aarch64-stage2.hex0 Mirrors the updated save-area base in the hex0-encoded stage2 output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread builder-hex0-aarch64-stage2.S Outdated
Comment thread builder-hex0-aarch64-stage2.S Outdated
Comment thread builder-hex0-aarch64-stage2.hex2 Outdated
Comment thread builder-hex0-aarch64-stage2.hex2 Outdated
Comment thread builder-hex0-aarch64-stage2.hex0 Outdated
Comment thread builder-hex0-aarch64-stage2.hex0 Outdated
@alganet

alganet commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

The raspi3b issues are expected, it's the next step on this.

The fork-emulation save area (a bump allocator that memcpy's the parent's
whole process image plus its kernel and user stacks on every clone) was
initialized at VA 0x78000000 -- inside paging Entry 1, growing up toward the
kernel-stack top at 0x7B800000. That gave it only ~56MB AND backed it directly
onto the live, descending kernel stack.

A process with a heap of tens of MB therefore overran the save area into the
kernel stack on its first fork, corrupting return addresses -> silent hang (a
CPU fault would have printed "!EC:..." and exited 139 instead). hs hit this
running its probe sweep (hs forks+execs hs; its startup heap is ~55MB), where
riscv64 -- whose save area is 576MB and separate from the kernel stack -- did
not.

Move the save area to VA 0x80000000 on virt (Entry 2 -> PA 0x80000000): ~540MB
up to file data at 0xA1900000, clear of the kernel stack. The base is chosen
per board, because the two boards map the upper VA window to different physical
RAM: raspi3b's Entry 2 aliases PA 0x00000000, so VA 0x80000000 there would
overwrite the kernel in low RAM. raspi3b therefore keeps the legacy base
VA 0x78000000 (Entry 1 -> PA 0x38000000, valid in its 1GB RAM) -- its original,
unchanged behavior. Board is selected via x27 (3 = raspi3b, 0 = virt), the same
id _trampoline/load_ram_base already use for storage/UART setup.
@alganet
alganet force-pushed the aarch64-fork-savearea-fix branch from b0fe120 to 7f49d51 Compare June 16, 2026 19:55
@alganet
alganet merged commit fdc7cf7 into main Jun 16, 2026
6 checks passed
@alganet
alganet deleted the aarch64-fork-savearea-fix branch June 16, 2026 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants