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 <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Quim Muntal <quimmuntal@gmail.com>
This commit is contained in:
qmuntal 2025-09-23 17:17:37 +02:00 committed by Gopher Robot
parent fdea7da3e6
commit 45d6bc76af
10 changed files with 111 additions and 337 deletions

View file

@ -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"

View file

@ -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.

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)