commit 52d33b6ae41e86e81423d0dcb3e072de7be53789 (tree)
parent d1865477fb675a1bf60cbbe5c98bd12fb7cbbb8f
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Thu, 4 Jun 2026 00:36:25 +0200
std.os.linux.sparc64: work around kernel bug with uncommitted stack in clone()
https://sourceware.org/bugzilla/show_bug.cgi?id=31394
Diffstat:
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig
@@ -196,17 +196,28 @@ pub fn clone() callconv(.naked) u64 {
// g1 o0, o1, o2, o3, o4
asm volatile (
\\ save %%sp, -192, %%sp
+ \\
+ \\ // clone() on SPARC can fail with EFAULT if %%sp points to uncommitted memory, so flush
+ \\ // all register windows up to this point to ensure that the kernel has enough committed
+ \\ // memory for its stack frame.
+ \\ save %%sp, -192, %%sp
+ \\ flushw
+ \\ restore
+ \\
\\ # Save the func pointer and the arg pointer
\\ mov %%i0, %%g2
\\ mov %%i3, %%g3
+ \\
\\ # Shuffle the arguments
\\ mov 217, %%g1 // SYS_clone
\\ mov %%i2, %%o0
+ \\
\\ # Add some extra space for the initial frame
- \\ sub %%i1, 176 + 2047, %%o1
+ \\ sub %%i1, 192 + 2047, %%o1
+ \\
\\ mov %%i4, %%o2
\\ mov %%i5, %%o3
- \\ ldx [%%fp + 0x8af], %%o4
+ \\ ldx [%%fp + 176 + 2047], %%o4
\\ t 0x6d
\\ bcs,pn %%xcc, 1f
\\ nop
@@ -214,15 +225,18 @@ pub fn clone() callconv(.naked) u64 {
\\ # process is the child (=1) or the parent (=0).
\\ brnz %%o1, 2f
\\ nop
+ \\
\\ # Parent process, return the child pid
\\ mov %%o0, %%i0
\\ ret
\\ restore
+ \\
\\1:
\\ # The syscall failed
\\ sub %%g0, %%o0, %%i0
\\ ret
\\ restore
+ \\
\\2:
\\ # Child process
);