Re: [RFC PATCH 08/18] aarch64: move boot stack out of .bss so zero_out_bss doesn't clobber it
Paulo Fernando Barbosa Duarte <[email protected]>
| Newsgroups | gmane.os.hurd.bugs |
|---|---|
| Message-ID | <[email protected]> |
On Mon, May 25, 2026 at 4:59 PM Sergey Bugaev <[email protected]> wrote: > How does that work? Even if you don't use x29 as a frame pointer > (which you normally do on AArch64, so I doubt that my GCC had that > off), surely you still save/restore at least x30? > > Maybe that could still happen if zero_out_bss got inlined into > c_boot_entry, and so did not have its x30 saved? The inlining is right, zero_out_bss does get inlined into c_boot_entry. But the LR overwrite is one frame deeper, in memset itself, which is a leaf function and normally doesn't save x30. I should have been more specific about the flag in my last reply. The actual trigger is -mno-omit-leaf-frame-pointer, not -fno-omit-frame-pointer alone, the general flag still lets GCC omit the prologue on leaves. My nix cross-gcc has both on by default, and the leaf one is what makes memset push x30. Same source, same compiler, only the flag differs: With -mno-omit-leaf-frame-pointer (nix default): memset: stp x29, x30, [sp, #-16]! ; saves x30 into the boot stack <body: zeroes [__bss_start, __bss_end)> ldp x29, x30, [sp], #16 ; reloads x30 = 0 (slot was wiped) ret ; branches to PC=0 Without it (stock cross-gcc): memset: <body: zeroes [__bss_start, __bss_end)> ret ; x30 stayed in the register c_boot_entry has SP on the boot stack, the boot stack lives in .bss, so the stp lands inside the about-to-be-wiped range. qemu cpu_reset confirms it: PC=0, all GPRs 0, undefined-instruction loop at vector_base + 0x200. I tried this on your branch wip-aarch64 a845e3dc + the same nix gcc, byte-identical fault. So the crash has been latent on wip-aarch64 since the boot stack moved into .bss, it just needed a toolchain that emits -mno-omit-leaf-frame-pointer to trip. nix's cross-gcc is the unusual one for wrapping every invocation with those flags, but the broader trend matters: distro build systems are moving toward frame-pointer defaults for the packages they ship. Fedora 38 added exactly the pair we're tripping to its RPM build flags: https://fedoraproject.org/wiki/Changes/fno-omit-frame-pointer Ubuntu 24.04 LTS did the same for 64-bit platforms: https://ubuntu.com/blog/ubuntu-performance-engineering-with-frame-pointers-by-default With PATCH 08 the boot stack sits above __bss_end, so the saved x30 lands outside the wipe range and ret returns cleanly. With the flag off, memset doesn't push x30 in the first place. Either way, no crash, regardless of which toolchain the next person uses. v2 will rewrite the commit body around this mechanism instead of the boot-route speculation. Paulo