[RFC PATCH 08/18] aarch64: move boot stack out of .bss so zero_out_bss doesn't clobber it

Paulo Duarte <[email protected]>
Newsgroups gmane.os.hurd.bugs
Message-ID <[email protected]>
The imported boot.S places the boot stack inside the .bss segment:

	.bss
.boot_stack:
	.space 4096
.boot_stack_end:

c_boot_entry() is the first C function called from _start, with sp
already pointing at .boot_stack_end.  Its first action is to call
zero_out_bss(), which memsets [__bss_start, __bss_end) — the whole
.bss range, including the very boot stack the kernel is *currently
running on*.  That wipes the saved x29/x30 and any locals the
compiler spilled on entry, so the next return / function call
branches to 0 and the kernel hangs in EL1.

Move the boot stack into its own `.boot_stack` nobits section and
place that section after `__bss_end` in the linker script so
zero_out_bss() leaves it alone:

	.section .boot_stack, "aw", %nobits
boot_stack:
	.space 4096
.boot_stack_end:

Brought up under qemu-system-aarch64 -M virt the bug fires
immediately; wip-aarch64 likely never exercised the
zero_out_bss-from-_start path because its testing was on a
different boot route.
---
 aarch64/aarch64/boot.S | 10 ++++++++--
 aarch64/ldscript       |  3 +++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/aarch64/aarch64/boot.S b/aarch64/aarch64/boot.S
index 85d3b944..ab736489 100644
--- a/aarch64/aarch64/boot.S
+++ b/aarch64/aarch64/boot.S
@@ -92,8 +92,14 @@ ENTRY(_start)
 	b	EXT(c_boot_entry)
 END(_start)
 
-	.bss
-.boot_stack:
+	/*
+	 * Put the boot stack in its own nobits section so it lives outside
+	 * [__bss_start, __bss_end). Otherwise c_boot_entry's call to
+	 * zero_out_bss() (which memsets the whole BSS region) would clobber
+	 * its own saved x29/x30, sending us to PC=0 on ret.
+	 */
+	.section .boot_stack, "aw", %nobits
+boot_stack:
 	.space	4096
 .boot_stack_end:
 
diff --git a/aarch64/ldscript b/aarch64/ldscript
index 236fc6f8..a5aec69d 100644
--- a/aarch64/ldscript
+++ b/aarch64/ldscript
@@ -27,6 +27,9 @@ SECTIONS
         __bss_start = .;
         *(.bss);
         __bss_end = .;
+        /* Boot stack lives in its own nobits region after __bss_end so
+           it survives zero_out_bss() running from within itself. */
+        *(.boot_stack);
     }
     _image_end = .;
 }
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.