From: qmuntal Date: Tue, 23 Sep 2025 15:17:37 +0000 (+0200) Subject: runtime: unify arm64 entry point code X-Git-Tag: go1.26rc1~777 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=45d6bc76af;p=gostls13.git runtime: unify arm64 entry point code There is a lot of duplication in how arm64 OSes handle entry points. Do as amd64, have all the logic in a common function. Cq-Include-Trybots: luci.golang.try:gotip-darwin-arm64-longtest,gotip-windows-arm64 Change-Id: I370c25c3c4b107b525aba14e9dcac34a02d9872e Reviewed-on: https://go-review.googlesource.com/c/go/+/706175 Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui Auto-Submit: Quim Muntal --- diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index a0072a3931..a0e82ec830 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -7,6 +7,78 @@ #include "tls_arm64.h" #include "funcdata.h" #include "textflag.h" +#include "cgo/abi_arm64.h" + +// _rt0_arm64 is common startup code for most arm64 systems when using +// internal linking. This is the entry point for the program from the +// kernel for an ordinary -buildmode=exe program. The stack holds the +// number of arguments and the C-style argv. +TEXT _rt0_arm64(SB),NOSPLIT,$0 + MOVD 0(RSP), R0 // argc + ADD $8, RSP, R1 // argv + JMP runtime·rt0_go(SB) + +// main is common startup code for most amd64 systems when using +// external linking. The C startup code will call the symbol "main" +// passing argc and argv in the usual C ABI registers R0 and R1. +TEXT main(SB),NOSPLIT,$0 + JMP runtime·rt0_go(SB) + +// _rt0_arm64_lib is common startup code for most arm64 systems when +// using -buildmode=c-archive or -buildmode=c-shared. The linker will +// arrange to invoke this function as a global constructor (for +// c-archive) or when the shared library is loaded (for c-shared). +// We expect argc and argv to be passed in the usual C ABI registers +// R0 and R1. +TEXT _rt0_arm64_lib(SB),NOSPLIT,$184 + // Preserve callee-save registers. + SAVE_R19_TO_R28(24) + SAVE_F8_TO_F15(104) + + // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go + MOVD ZR, g + + MOVD R0, _rt0_arm64_lib_argc<>(SB) + MOVD R1, _rt0_arm64_lib_argv<>(SB) + + // Synchronous initialization. + MOVD $runtime·libpreinit(SB), R4 + BL (R4) + + // Create a new thread to do the runtime initialization and return. + MOVD _cgo_sys_thread_create(SB), R4 + CBZ R4, nocgo + MOVD $_rt0_arm64_lib_go(SB), R0 + MOVD $0, R1 + SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. + BL (R4) + ADD $16, RSP + B restore + +nocgo: + MOVD $0x800000, R0 // stacksize = 8192KB + MOVD $_rt0_arm64_lib_go(SB), R1 + MOVD R0, 8(RSP) + MOVD R1, 16(RSP) + MOVD $runtime·newosproc0(SB),R4 + BL (R4) + +restore: + // Restore callee-save registers. + RESTORE_R19_TO_R28(24) + RESTORE_F8_TO_F15(104) + RET + +TEXT _rt0_arm64_lib_go(SB),NOSPLIT,$0 + MOVD _rt0_arm64_lib_argc<>(SB), R0 + MOVD _rt0_arm64_lib_argv<>(SB), R1 + MOVD $runtime·rt0_go(SB),R4 + B (R4) + +DATA _rt0_arm64_lib_argc<>(SB)/8, $0 +GLOBL _rt0_arm64_lib_argc<>(SB),NOPTR, $8 +DATA _rt0_arm64_lib_argv<>(SB)/8, $0 +GLOBL _rt0_arm64_lib_argv<>(SB),NOPTR, $8 #ifdef GOARM64_LSE DATA no_lse_msg<>+0x00(SB)/64, $"This program can only run on ARM64 processors with LSE support.\n" diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index f47419cf7d..7610802e0f 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -777,13 +777,14 @@ func newosproc(mp *m) { // //go:nowritebarrierrec //go:nosplit -func newosproc0(mp *m, stk unsafe.Pointer) { - // TODO: this is completely broken. The args passed to newosproc0 (in asm_amd64.s) - // are stacksize and function, not *m and stack. - // Check os_linux.go for an implementation that might actually work. +func newosproc0(stacksize uintptr, fn uintptr) { throw("bad newosproc0") } +//go:nosplit +//go:nowritebarrierrec +func libpreinit() {} + func exitThread(wait *atomic.Uint32) { // We should never reach exitThread on Windows because we let // the OS clean up threads. diff --git a/src/runtime/rt0_android_arm64.s b/src/runtime/rt0_android_arm64.s index 4135bf07d5..ff4b691222 100644 --- a/src/runtime/rt0_android_arm64.s +++ b/src/runtime/rt0_android_arm64.s @@ -4,17 +4,15 @@ #include "textflag.h" -TEXT _rt0_arm64_android(SB),NOSPLIT|NOFRAME,$0 - MOVD $_rt0_arm64_linux(SB), R4 - B (R4) +TEXT _rt0_arm64_android(SB),NOSPLIT,$0 + JMP _rt0_arm64(SB) // When building with -buildmode=c-shared, this symbol is called when the shared // library is loaded. -TEXT _rt0_arm64_android_lib(SB),NOSPLIT|NOFRAME,$0 +TEXT _rt0_arm64_android_lib(SB),NOSPLIT,$0 MOVW $1, R0 // argc MOVD $_rt0_arm64_android_argv(SB), R1 // **argv - MOVD $_rt0_arm64_linux_lib(SB), R4 - B (R4) + JMP _rt0_arm64_lib(SB) DATA _rt0_arm64_android_argv+0x00(SB)/8,$_rt0_arm64_android_argv0(SB) DATA _rt0_arm64_android_argv+0x08(SB)/8,$0 // end argv diff --git a/src/runtime/rt0_darwin_arm64.s b/src/runtime/rt0_darwin_arm64.s index 697104ac64..e9cd5fc7f5 100644 --- a/src/runtime/rt0_darwin_arm64.s +++ b/src/runtime/rt0_darwin_arm64.s @@ -3,61 +3,13 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "cgo/abi_arm64.h" -TEXT _rt0_arm64_darwin(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - BL (R2) -exit: - MOVD $0, R0 - MOVD $1, R16 // sys_exit - SVC $0x80 - B exit +TEXT _rt0_arm64_darwin(SB),NOSPLIT,$0 + // Darwin puts argc and argv in R0 and R1, + // so there is no need to go through _rt0_arm64. + JMP runtime·rt0_go(SB) // When linking with -buildmode=c-archive or -buildmode=c-shared, // this symbol is called from a global initialization function. -// -// Note that all currently shipping darwin/arm64 platforms require -// cgo and do not support c-shared. -TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$152 - // Preserve callee-save registers. - SAVE_R19_TO_R28(8) - SAVE_F8_TO_F15(88) - - MOVD R0, _rt0_arm64_darwin_lib_argc<>(SB) - MOVD R1, _rt0_arm64_darwin_lib_argv<>(SB) - - MOVD $0, g // initialize g to nil - - // Synchronous initialization. - MOVD $runtime·libpreinit(SB), R4 - BL (R4) - - // Create a new thread to do the runtime initialization and return. - MOVD _cgo_sys_thread_create(SB), R4 - MOVD $_rt0_arm64_darwin_lib_go(SB), R0 - MOVD $0, R1 - SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. - BL (R4) - ADD $16, RSP - - // Restore callee-save registers. - RESTORE_R19_TO_R28(8) - RESTORE_F8_TO_F15(88) - - RET - -TEXT _rt0_arm64_darwin_lib_go(SB),NOSPLIT,$0 - MOVD _rt0_arm64_darwin_lib_argc<>(SB), R0 - MOVD _rt0_arm64_darwin_lib_argv<>(SB), R1 - MOVD $runtime·rt0_go(SB), R4 - B (R4) - -DATA _rt0_arm64_darwin_lib_argc<>(SB)/8, $0 -GLOBL _rt0_arm64_darwin_lib_argc<>(SB),NOPTR, $8 -DATA _rt0_arm64_darwin_lib_argv<>(SB)/8, $0 -GLOBL _rt0_arm64_darwin_lib_argv<>(SB),NOPTR, $8 - -// external linking entry point. -TEXT main(SB),NOSPLIT|NOFRAME,$0 - JMP _rt0_arm64_darwin(SB) +TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0 + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_freebsd_arm64.s b/src/runtime/rt0_freebsd_arm64.s index e517ae059d..a7a952664e 100644 --- a/src/runtime/rt0_freebsd_arm64.s +++ b/src/runtime/rt0_freebsd_arm64.s @@ -3,72 +3,12 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "cgo/abi_arm64.h" // On FreeBSD argc/argv are passed in R0, not RSP -TEXT _rt0_arm64_freebsd(SB),NOSPLIT|NOFRAME,$0 - ADD $8, R0, R1 // argv - MOVD 0(R0), R0 // argc - BL main(SB) +TEXT _rt0_arm64_freebsd(SB),NOSPLIT,$0 + JMP _rt0_arm64(SB) // When building with -buildmode=c-shared, this symbol is called when the shared // library is loaded. -TEXT _rt0_arm64_freebsd_lib(SB),NOSPLIT,$184 - // Preserve callee-save registers. - SAVE_R19_TO_R28(24) - SAVE_F8_TO_F15(104) - - // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go - MOVD ZR, g - - MOVD R0, _rt0_arm64_freebsd_lib_argc<>(SB) - MOVD R1, _rt0_arm64_freebsd_lib_argv<>(SB) - - // Synchronous initialization. - MOVD $runtime·libpreinit(SB), R4 - BL (R4) - - // Create a new thread to do the runtime initialization and return. - MOVD _cgo_sys_thread_create(SB), R4 - CBZ R4, nocgo - MOVD $_rt0_arm64_freebsd_lib_go(SB), R0 - MOVD $0, R1 - SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. - BL (R4) - ADD $16, RSP - B restore - -nocgo: - MOVD $0x800000, R0 // stacksize = 8192KB - MOVD $_rt0_arm64_freebsd_lib_go(SB), R1 - MOVD R0, 8(RSP) - MOVD R1, 16(RSP) - MOVD $runtime·newosproc0(SB),R4 - BL (R4) - -restore: - // Restore callee-save registers. - RESTORE_R19_TO_R28(24) - RESTORE_F8_TO_F15(104) - RET - -TEXT _rt0_arm64_freebsd_lib_go(SB),NOSPLIT,$0 - MOVD _rt0_arm64_freebsd_lib_argc<>(SB), R0 - MOVD _rt0_arm64_freebsd_lib_argv<>(SB), R1 - MOVD $runtime·rt0_go(SB),R4 - B (R4) - -DATA _rt0_arm64_freebsd_lib_argc<>(SB)/8, $0 -GLOBL _rt0_arm64_freebsd_lib_argc<>(SB),NOPTR, $8 -DATA _rt0_arm64_freebsd_lib_argv<>(SB)/8, $0 -GLOBL _rt0_arm64_freebsd_lib_argv<>(SB),NOPTR, $8 - - -TEXT main(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - BL (R2) -exit: - MOVD $0, R0 - MOVD $1, R8 // SYS_exit - SVC - B exit +TEXT _rt0_arm64_freebsd_lib(SB),NOSPLIT,$0 + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_ios_arm64.s b/src/runtime/rt0_ios_arm64.s index dcc83656e2..1ab945b31c 100644 --- a/src/runtime/rt0_ios_arm64.s +++ b/src/runtime/rt0_ios_arm64.s @@ -11,4 +11,4 @@ TEXT _rt0_arm64_ios(SB),NOSPLIT|NOFRAME,$0 // library entry point. TEXT _rt0_arm64_ios_lib(SB),NOSPLIT|NOFRAME,$0 - JMP _rt0_arm64_darwin_lib(SB) + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_linux_arm64.s b/src/runtime/rt0_linux_arm64.s index 0eb8fc2f48..eed9c5f920 100644 --- a/src/runtime/rt0_linux_arm64.s +++ b/src/runtime/rt0_linux_arm64.s @@ -3,71 +3,11 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "cgo/abi_arm64.h" -TEXT _rt0_arm64_linux(SB),NOSPLIT|NOFRAME,$0 - MOVD 0(RSP), R0 // argc - ADD $8, RSP, R1 // argv - BL main(SB) +TEXT _rt0_arm64_linux(SB),NOSPLIT,$0 + JMP _rt0_arm64(SB) // When building with -buildmode=c-shared, this symbol is called when the shared // library is loaded. -TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$184 - // Preserve callee-save registers. - SAVE_R19_TO_R28(24) - SAVE_F8_TO_F15(104) - - // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go - MOVD ZR, g - - MOVD R0, _rt0_arm64_linux_lib_argc<>(SB) - MOVD R1, _rt0_arm64_linux_lib_argv<>(SB) - - // Synchronous initialization. - MOVD $runtime·libpreinit(SB), R4 - BL (R4) - - // Create a new thread to do the runtime initialization and return. - MOVD _cgo_sys_thread_create(SB), R4 - CBZ R4, nocgo - MOVD $_rt0_arm64_linux_lib_go(SB), R0 - MOVD $0, R1 - SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. - BL (R4) - ADD $16, RSP - B restore - -nocgo: - MOVD $0x800000, R0 // stacksize = 8192KB - MOVD $_rt0_arm64_linux_lib_go(SB), R1 - MOVD R0, 8(RSP) - MOVD R1, 16(RSP) - MOVD $runtime·newosproc0(SB),R4 - BL (R4) - -restore: - // Restore callee-save registers. - RESTORE_R19_TO_R28(24) - RESTORE_F8_TO_F15(104) - RET - -TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0 - MOVD _rt0_arm64_linux_lib_argc<>(SB), R0 - MOVD _rt0_arm64_linux_lib_argv<>(SB), R1 - MOVD $runtime·rt0_go(SB),R4 - B (R4) - -DATA _rt0_arm64_linux_lib_argc<>(SB)/8, $0 -GLOBL _rt0_arm64_linux_lib_argc<>(SB),NOPTR, $8 -DATA _rt0_arm64_linux_lib_argv<>(SB)/8, $0 -GLOBL _rt0_arm64_linux_lib_argv<>(SB),NOPTR, $8 - - -TEXT main(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - BL (R2) -exit: - MOVD $0, R0 - MOVD $94, R8 // sys_exit - SVC - B exit +TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$0 + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_netbsd_arm64.s b/src/runtime/rt0_netbsd_arm64.s index 691a8e4be7..07fb0a1240 100644 --- a/src/runtime/rt0_netbsd_arm64.s +++ b/src/runtime/rt0_netbsd_arm64.s @@ -3,69 +3,13 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "cgo/abi_arm64.h" -TEXT _rt0_arm64_netbsd(SB),NOSPLIT|NOFRAME,$0 +TEXT _rt0_arm64_netbsd(SB),NOSPLIT,$0 MOVD 0(RSP), R0 // argc ADD $8, RSP, R1 // argv BL main(SB) // When building with -buildmode=c-shared, this symbol is called when the shared // library is loaded. -TEXT _rt0_arm64_netbsd_lib(SB),NOSPLIT,$184 - // Preserve callee-save registers. - SAVE_R19_TO_R28(24) - SAVE_F8_TO_F15(104) - - // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go - MOVD ZR, g - - MOVD R0, _rt0_arm64_netbsd_lib_argc<>(SB) - MOVD R1, _rt0_arm64_netbsd_lib_argv<>(SB) - - // Synchronous initialization. - MOVD $runtime·libpreinit(SB), R4 - BL (R4) - - // Create a new thread to do the runtime initialization and return. - MOVD _cgo_sys_thread_create(SB), R4 - CBZ R4, nocgo - MOVD $_rt0_arm64_netbsd_lib_go(SB), R0 - MOVD $0, R1 - SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. - BL (R4) - ADD $16, RSP - B restore - -nocgo: - MOVD $0x800000, R0 // stacksize = 8192KB - MOVD $_rt0_arm64_netbsd_lib_go(SB), R1 - MOVD R0, 8(RSP) - MOVD R1, 16(RSP) - MOVD $runtime·newosproc0(SB),R4 - BL (R4) - -restore: - // Restore callee-save registers. - RESTORE_R19_TO_R28(24) - RESTORE_F8_TO_F15(104) - RET - -TEXT _rt0_arm64_netbsd_lib_go(SB),NOSPLIT,$0 - MOVD _rt0_arm64_netbsd_lib_argc<>(SB), R0 - MOVD _rt0_arm64_netbsd_lib_argv<>(SB), R1 - MOVD $runtime·rt0_go(SB),R4 - B (R4) - -DATA _rt0_arm64_netbsd_lib_argc<>(SB)/8, $0 -GLOBL _rt0_arm64_netbsd_lib_argc<>(SB),NOPTR, $8 -DATA _rt0_arm64_netbsd_lib_argv<>(SB)/8, $0 -GLOBL _rt0_arm64_netbsd_lib_argv<>(SB),NOPTR, $8 - - -TEXT main(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - BL (R2) -exit: - MOVD $0, R0 - SVC $1 // sys_exit +TEXT _rt0_arm64_netbsd_lib(SB),NOSPLIT,$0 + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_openbsd_arm64.s b/src/runtime/rt0_openbsd_arm64.s index 49d49b34ac..2050f6a200 100644 --- a/src/runtime/rt0_openbsd_arm64.s +++ b/src/runtime/rt0_openbsd_arm64.s @@ -3,77 +3,11 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "cgo/abi_arm64.h" -// See comment in runtime/sys_openbsd_arm64.s re this construction. -#define INVOKE_SYSCALL \ - SVC; \ - NOOP; \ - NOOP - -TEXT _rt0_arm64_openbsd(SB),NOSPLIT|NOFRAME,$0 - MOVD 0(RSP), R0 // argc - ADD $8, RSP, R1 // argv - BL main(SB) +TEXT _rt0_arm64_openbsd(SB),NOSPLIT,$0 + JMP _rt0_arm64(SB) // When building with -buildmode=c-shared, this symbol is called when the shared // library is loaded. TEXT _rt0_arm64_openbsd_lib(SB),NOSPLIT,$184 - // Preserve callee-save registers. - SAVE_R19_TO_R28(24) - SAVE_F8_TO_F15(104) - - // Initialize g as null in case of using g later e.g. sigaction in cgo_sigaction.go - MOVD ZR, g - - MOVD R0, _rt0_arm64_openbsd_lib_argc<>(SB) - MOVD R1, _rt0_arm64_openbsd_lib_argv<>(SB) - - // Synchronous initialization. - MOVD $runtime·libpreinit(SB), R4 - BL (R4) - - // Create a new thread to do the runtime initialization and return. - MOVD _cgo_sys_thread_create(SB), R4 - CBZ R4, nocgo - MOVD $_rt0_arm64_openbsd_lib_go(SB), R0 - MOVD $0, R1 - SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. - BL (R4) - ADD $16, RSP - B restore - -nocgo: - MOVD $0x800000, R0 // stacksize = 8192KB - MOVD $_rt0_arm64_openbsd_lib_go(SB), R1 - MOVD R0, 8(RSP) - MOVD R1, 16(RSP) - MOVD $runtime·newosproc0(SB),R4 - BL (R4) - -restore: - // Restore callee-save registers. - RESTORE_R19_TO_R28(24) - RESTORE_F8_TO_F15(104) - RET - -TEXT _rt0_arm64_openbsd_lib_go(SB),NOSPLIT,$0 - MOVD _rt0_arm64_openbsd_lib_argc<>(SB), R0 - MOVD _rt0_arm64_openbsd_lib_argv<>(SB), R1 - MOVD $runtime·rt0_go(SB),R4 - B (R4) - -DATA _rt0_arm64_openbsd_lib_argc<>(SB)/8, $0 -GLOBL _rt0_arm64_openbsd_lib_argc<>(SB),NOPTR, $8 -DATA _rt0_arm64_openbsd_lib_argv<>(SB)/8, $0 -GLOBL _rt0_arm64_openbsd_lib_argv<>(SB),NOPTR, $8 - - -TEXT main(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - BL (R2) -exit: - MOVD $0, R0 - MOVD $1, R8 // sys_exit - INVOKE_SYSCALL - B exit + JMP _rt0_arm64_lib(SB) diff --git a/src/runtime/rt0_windows_arm64.s b/src/runtime/rt0_windows_arm64.s index 8802c2b82e..dc68cff5f2 100644 --- a/src/runtime/rt0_windows_arm64.s +++ b/src/runtime/rt0_windows_arm64.s @@ -8,22 +8,15 @@ // This is the entry point for the program from the // kernel for an ordinary -buildmode=exe program. -TEXT _rt0_arm64_windows(SB),NOSPLIT|NOFRAME,$0 - B ·rt0_go(SB) +TEXT _rt0_arm64_windows(SB),NOSPLIT,$0 + // Windows doesn't use argc and argv, + // so there is no need to go through _rt0_arm64. + JMP runtime·rt0_go(SB) -TEXT _rt0_arm64_windows_lib(SB),NOSPLIT|NOFRAME,$0 - MOVD $_rt0_arm64_windows_lib_go(SB), R0 - MOVD $0, R1 - MOVD _cgo_sys_thread_create(SB), R2 - B (R2) - -TEXT _rt0_arm64_windows_lib_go(SB),NOSPLIT|NOFRAME,$0 +// When building with -buildmode=c-shared, this symbol is called when the shared +// library is loaded. +TEXT _rt0_arm64_windows_lib(SB),NOSPLIT,$0 + // We get the argc and argv parameters from Win32. MOVD $0, R0 MOVD $0, R1 - MOVD $runtime·rt0_go(SB), R2 - B (R2) - -TEXT main(SB),NOSPLIT|NOFRAME,$0 - MOVD $runtime·rt0_go(SB), R2 - B (R2) - + JMP _rt0_arm64_lib(SB)