From: Joel Sing Date: Sat, 18 Mar 2023 08:51:52 +0000 (+1100) Subject: runtime: rework asmcgocall on ppc64x X-Git-Tag: go1.22rc1~1162 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b291538d33c2b79f592d4fef5e50eb12e95b1251;p=gostls13.git runtime: rework asmcgocall on ppc64x 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 Reviewed-by: Paul Murphy Run-TryBot: Joel Sing Reviewed-by: Dmitri Shuralyov Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 66d0447c9d..5ff89cdeef 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -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