]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: rework asmcgocall on ppc64x
authorJoel Sing <joel@sing.id.au>
Sat, 18 Mar 2023 08:51:52 +0000 (19:51 +1100)
committerJoel Sing <joel@sing.id.au>
Tue, 22 Aug 2023 02:47:15 +0000 (02:47 +0000)
On some platforms asmcgocall can be called with a nil g. Additionally, it
can be called when already on a the system (g0) stack or on a signal stack.
In these cases we do not need to switch (and/or cannot switch) to the
system stack and as a result, do not need to save the g.

Rework asmcgocall on ppc64x to follow the pattern used on other architectures,
such as amd64 and arm64, where a separate nosave path is called in the above
cases. The nil g case will be needed to support openbsd/ppc64.

Updates #56001

Change-Id: I431d4200bcbc4aaddeb617aefe18590165ff2927
Reviewed-on: https://go-review.googlesource.com/c/go/+/478775
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Paul Murphy <murp@ibm.com>
Run-TryBot: Joel Sing <joel@sing.id.au>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/runtime/asm_ppc64x.s

index 66d0447c9dc152d025cee22ae0bef42df2cba9be..5ff89cdeef9a0350363c00a470605ce3749c896b 100644 (file)
@@ -554,6 +554,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
        MOVD    arg+8(FP), R4
 
        MOVD    R1, R7          // save original stack pointer
+       CMP     $0, g
+       BEQ     nosave
        MOVD    g, R5
 
        // Figure out if we need to switch to m->g0 stack.
@@ -563,29 +565,29 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
        MOVD    g_m(g), R8
        MOVD    m_gsignal(R8), R6
        CMP     R6, g
-       BEQ     g0
+       BEQ     nosave
        MOVD    m_g0(R8), R6
        CMP     R6, g
-       BEQ     g0
+       BEQ     nosave
+
        BL      gosave_systemstack_switch<>(SB)
        MOVD    R6, g
        BL      runtime·save_g(SB)
        MOVD    (g_sched+gobuf_sp)(g), R1
 
        // Now on a scheduling stack (a pthread-created stack).
-g0:
 #ifdef GOOS_aix
        // Create a fake LR to improve backtrace.
        MOVD    $runtime·asmcgocall(SB), R6
        MOVD    R6, 16(R1)
-       // AIX also save one argument on the stack.
-       SUB $8, R1
+       // AIX also saves one argument on the stack.
+       SUB     $8, R1
 #endif
        // Save room for two of our pointers, plus the callee
        // save area that lives on the caller stack.
        SUB     $(asmcgocallSaveOffset+16), R1
        RLDCR   $0, R1, $~15, R1        // 16-byte alignment for gcc ABI
-       MOVD    R5, (asmcgocallSaveOffset+8)(R1)// save old g on stack
+       MOVD    R5, (asmcgocallSaveOffset+8)(R1)        // save old g on stack
        MOVD    (g_stack+stack_hi)(R5), R5
        SUB     R7, R5
        MOVD    R5, asmcgocallSaveOffset(R1)    // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
@@ -605,9 +607,10 @@ g0:
        MOVD    R12, CTR
        MOVD    R4, R3          // arg in r3
        BL      (CTR)
-       // C code can clobber R0, so set it back to 0. F27-F31 are
-       // callee save, so we don't need to recover those.
+
+       // Reinitialise zero value register.
        XOR     R0, R0
+
        // Restore g, stack pointer, toc pointer.
        // R3 is errno, so don't touch it
        MOVD    (asmcgocallSaveOffset+8)(R1), g
@@ -623,6 +626,41 @@ g0:
        MOVW    R3, ret+16(FP)
        RET
 
+nosave:
+       // Running on a system stack, perhaps even without a g.
+       // Having no g can happen during thread creation or thread teardown.
+       // This code is like the above sequence but without saving/restoring g
+       // and without worrying about the stack moving out from under us
+       // (because we're on a system stack, not a goroutine stack).
+       // The above code could be used directly if already on a system stack,
+       // but then the only path through this code would be a rare case.
+       // Using this code for all "already on system stack" calls exercises it more,
+       // which should help keep it correct.
+
+       SUB     $(asmcgocallSaveOffset+8), R1
+       RLDCR   $0, R1, $~15, R1                // 16-byte alignment for gcc ABI
+       MOVD    R7, asmcgocallSaveOffset(R1)    // Save original stack pointer.
+
+       MOVD    R3, R12         // fn
+#ifdef GO_PPC64X_HAS_FUNCDESC
+       // Load the real entry address from the first slot of the function descriptor.
+       MOVD    8(R12), R2
+       MOVD    (R12), R12
+#endif
+       MOVD    R12, CTR
+       MOVD    R4, R3          // arg
+       BL      (CTR)
+
+       // Reinitialise zero value register.
+       XOR     R0, R0
+
+       MOVD    asmcgocallSaveOffset(R1), R1    // Restore stack pointer.
+#ifndef GOOS_aix
+       MOVD    24(R1), R2
+#endif
+       MOVW    R3, ret+16(FP)
+       RET
+
 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
 // See cgocall.go for more details.
 TEXT ·cgocallback(SB),NOSPLIT,$24-24