diff options
| author | Elias Naur <elias.naur@gmail.com> | 2013-08-14 15:38:54 +0000 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2013-08-14 15:38:54 +0000 |
| commit | 45233734e28776a6679dd8aa9f66a1d545ca8ec6 (patch) | |
| tree | 2d2df0108d9e04c1a23924201ff35acac4358cff /src/pkg | |
| parent | c92287686d3735050dc36a7eaa93ae1824732500 (diff) | |
| download | go-45233734e28776a6679dd8aa9f66a1d545ca8ec6.tar.xz | |
runtime.cmd/ld: Add ARM external linking and implement -shared in terms of external linking
This CL is an aggregate of 10271047, 10499043, 9733044. Descriptions of each follow:
10499043
runtime,cmd/ld: Merge TLS symbols and teach 5l about ARM TLS
This CL prepares for external linking support to ARM.
The pseudo-symbols runtime.g and runtime.m are merged into a single
runtime.tlsgm symbol. When external linking, the offset of a thread local
variable is stored at a memory location instead of being embedded into a offset
of a ldr instruction. With a single runtime.tlsgm symbol for both g and m, only
one such offset is needed.
The larger part of this CL moves TLS code from gcc compiled to internally
compiled. The TLS code now uses the modern MRC instruction, and 5l is taught
about TLS fallbacks in case the instruction is not available or appropriate.
10271047
This CL adds support for -linkmode external to 5l.
For 5l itself, use addrel to allow for D_CALL relocations to be handled by the
host linker. Of the cases listed in rsc's comment in issue 4069, only case 5 and
63 needed an update. One of the TODO: addrel cases was since replaced, and the
rest of the cases are either covered by indirection through addpool (cases with
LTO or LFROM flags) or stubs (case 74). The addpool cases are covered because
addpool emits AWORD instructions, which in turn are handled by case 11.
In the runtime, change the argv argument in the rt0* functions slightly to be a
pointer to the argv list, instead of relying on a particular location of argv.
9733044
The -shared flag to 6l outputs a shared library, implemented in Go
and callable from non-Go programs such as C.
The main part of this CL change the thread local storage model.
Go uses the fastest and least general mode, local exec. TLS data in shared
libraries normally requires at least the local dynamic mode, however, this CL
instead opts for using the initial exec mode. Initial exec mode is faster than
local dynamic mode and can be used in linux since the linker has reserved a
limited amount of TLS space for performance sensitive TLS code.
Initial exec mode requires an extra load from the GOT table to determine the
TLS offset. This penalty will not be paid if ld is not in -shared mode, since
TLS accesses will be reduced to local exec.
The elf sections .init_array and .rela.init_array are added to register the Go
runtime entry with cgo at library load time.
The "hidden" attribute is added to Cgo functions called from Go, since Go
does not generate call through the GOT table, and adding non-GOT relocations for
a global function is not supported by gcc. Cgo symbols don't need to be global
and avoiding the GOT table is also faster.
The changes to 8l are only removes code relevant to the old -shared mode where
internal linking was used.
This CL only address the low level linker work. It can be submitted by itself,
but to be useful, the runtime changes in CL 9738047 is also needed.
Design discussion at
https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/zmjXkGrEx6Q
Fixes #5590.
R=rsc
CC=golang-dev
https://golang.org/cl/12871044
Diffstat (limited to 'src/pkg')
| -rw-r--r-- | src/pkg/runtime/asm_arm.s | 55 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/asm_arm.s | 5 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/cgo_arm.c | 12 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/gcc_arm.S | 14 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/gcc_freebsd_arm.c | 64 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/gcc_linux_arm.c | 55 | ||||
| -rw-r--r-- | src/pkg/runtime/cgo/gcc_netbsd_arm.c | 59 | ||||
| -rw-r--r-- | src/pkg/runtime/cgocall.c | 5 | ||||
| -rw-r--r-- | src/pkg/runtime/os_linux_arm.c | 5 | ||||
| -rw-r--r-- | src/pkg/runtime/rt0_freebsd_arm.s | 3 | ||||
| -rw-r--r-- | src/pkg/runtime/rt0_linux_arm.s | 12 | ||||
| -rw-r--r-- | src/pkg/runtime/rt0_netbsd_arm.s | 3 | ||||
| -rw-r--r-- | src/pkg/runtime/sys_freebsd_arm.s | 4 | ||||
| -rw-r--r-- | src/pkg/runtime/sys_linux_arm.s | 11 | ||||
| -rw-r--r-- | src/pkg/runtime/sys_netbsd_arm.s | 6 |
15 files changed, 109 insertions, 204 deletions
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s index 6978ae4426..0d12b6a0d8 100644 --- a/src/pkg/runtime/asm_arm.s +++ b/src/pkg/runtime/asm_arm.s @@ -13,7 +13,7 @@ TEXT _rt0_go(SB),NOSPLIT,$-4 // copy arguments forward on an even stack // use R13 instead of SP to avoid linker rewriting the offsets MOVW 0(R13), R0 // argc - MOVW $4(R13), R1 // argv + MOVW 4(R13), R1 // argv SUB $64, R13 // plenty of scratch AND $~7, R13 MOVW R0, 60(R13) // save argc, argv away @@ -35,10 +35,15 @@ TEXT _rt0_go(SB),NOSPLIT,$-4 BL runtime·emptyfunc(SB) // fault if stack check is wrong // if there is an _cgo_init, call it. - MOVW _cgo_init(SB), R2 - CMP $0, R2 - MOVW.NE g, R0 // first argument of _cgo_init is g - BL.NE (R2) // will clobber R0-R3 + MOVW _cgo_init(SB), R4 + CMP $0, R4 + B.EQ nocgo + BL runtime·save_gm(SB); + MOVW g, R0 // first argument of _cgo_init is g + MOVW $setmg_gcc<>(SB), R1 // second argument is address of save_gm + BL (R4) // will clobber R0-R3 + +nocgo: // update stackguard after _cgo_init MOVW g_stackguard0(g), R0 MOVW R0, g_stackguard(g) @@ -119,9 +124,9 @@ TEXT runtime·gogo(SB), NOSPLIT, $-4-4 MOVW 0(FP), R1 // gobuf MOVW gobuf_g(R1), g MOVW 0(g), R2 // make sure g != nil - MOVW _cgo_save_gm(SB), R2 + MOVB runtime·iscgo(SB), R2 CMP $0, R2 // if in Cgo, we have to save g and m - BL.NE (R2) // this call will clobber R0 + BL.NE runtime·save_gm(SB) // this call will clobber R0 MOVW gobuf_sp(R1), SP // restore SP MOVW gobuf_lr(R1), LR MOVW gobuf_ret(R1), R0 @@ -437,9 +442,9 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$12-12 // See cgocall.c for more details. TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12 // Load m and g from thread-local storage. - MOVW _cgo_load_gm(SB), R0 + MOVB runtime·iscgo(SB), R0 CMP $0, R0 - BL.NE (R0) + BL.NE runtime·load_gm(SB) // If m is nil, Go did not create the current thread. // Call needm to obtain one for temporary use. @@ -519,9 +524,9 @@ TEXT runtime·setmg(SB), NOSPLIT, $0-8 MOVW gg+4(FP), g // Save m and g to thread-local storage. - MOVW _cgo_save_gm(SB), R0 + MOVB runtime·iscgo(SB), R0 CMP $0, R0 - BL.NE (R0) + BL.NE runtime·save_gm(SB) RET @@ -615,6 +620,34 @@ _next: MOVW $0, R0 RET +// We have to resort to TLS variable to save g(R10) and +// m(R9). One reason is that external code might trigger +// SIGSEGV, and our runtime.sigtramp don't even know we +// are in external code, and will continue to use R10/R9, +// this might as well result in another SIGSEGV. +// Note: all three functions will clobber R0, and the last +// two can be called from 5c ABI code. + +// g (R10) at 8(TP), m (R9) at 12(TP) +TEXT runtime·save_gm(SB),NOSPLIT,$0 + MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register + MOVW g, 8(R0) + MOVW m, 12(R0) + RET + +TEXT runtime·load_gm(SB),NOSPLIT,$0 + MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register + MOVW 8(R0), g + MOVW 12(R0), m + RET + +// void setmg_gcc(M*, G*); set m and g called from gcc. +TEXT setmg_gcc<>(SB),NOSPLIT,$0 + MOVW R0, m + MOVW R1, g + B runtime·save_gm(SB) + + // TODO: share code with memeq? TEXT bytes·Equal(SB),NOSPLIT,$0 MOVW a_len+4(FP), R1 diff --git a/src/pkg/runtime/cgo/asm_arm.s b/src/pkg/runtime/cgo/asm_arm.s index bf0132f6f6..850b1c6b61 100644 --- a/src/pkg/runtime/cgo/asm_arm.s +++ b/src/pkg/runtime/cgo/asm_arm.s @@ -14,12 +14,11 @@ TEXT crosscall2(SB),NOSPLIT,$-4 * push 2 args for fn (R1 and R2). * Also note that at procedure entry in 5c/5g world, 4(R13) will be the * first arg, so we must push another dummy reg (R0) for 0(R13). - * Additionally, cgo_tls_set_gm will clobber R0, so we need to save R0 + * Additionally, runtime·load_gm will clobber R0, so we need to save R0 * nevertheless. */ MOVM.WP [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, R14], (R13) - MOVW _cgo_load_gm(SB), R0 - BL (R0) + BL runtime·load_gm(SB) MOVW PC, R14 MOVW 0(R13), PC MOVM.IAW (R13), [R0, R1, R2, R4, R5, R6, R7, R8, m, g, R11, R12, PC] diff --git a/src/pkg/runtime/cgo/cgo_arm.c b/src/pkg/runtime/cgo/cgo_arm.c deleted file mode 100644 index d23f53e77a..0000000000 --- a/src/pkg/runtime/cgo/cgo_arm.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#pragma cgo_import_static x_cgo_load_gm -extern void x_cgo_load_gm(void); -void (*_cgo_load_gm)(void) = x_cgo_load_gm; - -#pragma cgo_import_static x_cgo_save_gm -extern void x_cgo_save_gm(void); -void (*_cgo_save_gm)(void) = x_cgo_save_gm; - diff --git a/src/pkg/runtime/cgo/gcc_arm.S b/src/pkg/runtime/cgo/gcc_arm.S index 3ec6e5d97b..e380a0f6db 100644 --- a/src/pkg/runtime/cgo/gcc_arm.S +++ b/src/pkg/runtime/cgo/gcc_arm.S @@ -12,7 +12,7 @@ #endif /* - * void crosscall_arm2(void (*fn)(void), void *g, void *m) + * void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void *m, void *g), void *m, void *g) * * Calling into the 5c tool chain, where all registers are caller save. * Called from standard ARM EABI, where r4-r11 are callee-save, so they @@ -21,12 +21,12 @@ .globl EXT(crosscall_arm2) EXT(crosscall_arm2): push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr} - mov r10, r1 // g - mov r9, r2 // m - mov r3, r0 // save r0, cgo_tls_set_gm will clobber it - bl EXT(x_cgo_save_gm) // save current g and m into TLS variable - mov lr, pc - mov pc, r3 + mov r4, r0 + mov r5, r1 + mov r0, r2 + mov r1, r3 + blx r5 // setmg(m, g) + blx r4 // fn() pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc} .globl EXT(__stack_chk_fail_local) diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c index 73c990c28f..211dca75cb 100644 --- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c @@ -8,72 +8,26 @@ #include <string.h> #include "libcgo.h" -static void *threadentry(void*); - -// We have to resort to TLS variable to save g(R10) and -// m(R9). One reason is that external code might trigger -// SIGSEGV, and our runtime.sigtramp don't even know we -// are in external code, and will continue to use R10/R9, -// this might as well result in another SIGSEGV. -// Note: all three functions will clobber R0, and the last -// two can be called from 5c ABI code. -void __aeabi_read_tp(void) __attribute__((naked)); -void x_cgo_save_gm(void) __attribute__((naked)); -void x_cgo_load_gm(void) __attribute__((naked)); - -void -__aeabi_read_tp(void) -{ - __asm__ __volatile__ ( #ifdef ARM_TP_ADDRESS - // ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000 - // GCC inline asm doesn't provide a way to provide a constant - // to "ldr r0, =??" pseudo instruction, so we hardcode the value - // and check it with cpp. +// ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000 +// and is known to runtime.read_tls_fallback. Verify it with +// cpp. #if ARM_TP_ADDRESS != 0xffff1000 #error Wrong ARM_TP_ADDRESS! #endif - "ldr r0, =0xffff1000\n\t" - "ldr r0, [r0]\n\t" -#else - "mrc p15, 0, r0, c13, c0, 3\n\t" #endif - "mov pc, lr\n\t" - ); -} -// g (R10) at 8(TP), m (R9) at 12(TP) -void -x_cgo_load_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "ldr r10, [r0, #8]\n\t" - "ldr r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} +static void *threadentry(void*); -void -x_cgo_save_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "str r10, [r0, #8]\n\t" - "str r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} +static void (*setmg_gcc)(void*, void*); void -x_cgo_init(G *g) +x_cgo_init(G *g, void (*setmg)(void*, void*)) { pthread_attr_t attr; size_t size; - x_cgo_save_gm(); // save g and m for the initial thread + setmg_gcc = setmg; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); g->stackguard = (uintptr)&attr - size + 4096; @@ -104,7 +58,7 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m); static void* threadentry(void *v) { @@ -121,6 +75,6 @@ threadentry(void *v) */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; - crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g); return nil; } diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c index 46a1126ad3..9a6e585948 100644 --- a/src/pkg/runtime/cgo/gcc_linux_arm.c +++ b/src/pkg/runtime/cgo/gcc_linux_arm.c @@ -8,60 +8,15 @@ static void *threadentry(void*); -// We have to resort to TLS variable to save g(R10) and -// m(R9). One reason is that external code might trigger -// SIGSEGV, and our runtime.sigtramp don't even know we -// are in external code, and will continue to use R10/R9, -// this might as well result in another SIGSEGV. -// Note: all three functions will clobber R0, and the last -// two can be called from 5c ABI code. -void __aeabi_read_tp(void) __attribute__((naked)); -void x_cgo_save_gm(void) __attribute__((naked)); -void x_cgo_load_gm(void) __attribute__((naked)); +static void (*setmg_gcc)(void*, void*); void -__aeabi_read_tp(void) -{ - // b __kuser_get_tls @ 0xffff0fe0 - __asm__ __volatile__ ( - "mvn r0, #0xf000\n\t" - "sub pc, r0, #31\n\t" - "nop\n\tnop\n\t" - ); -} - -// g (R10) at 8(TP), m (R9) at 12(TP) -void -x_cgo_load_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "ldr r10, [r0, #8]\n\t" - "ldr r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_save_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "str r10, [r0, #8]\n\t" - "str r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_init(G *g) +x_cgo_init(G *g, void (*setmg)(void*, void*)) { pthread_attr_t attr; size_t size; - x_cgo_save_gm(); // save g and m for the initial thread + setmg_gcc = setmg; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); g->stackguard = (uintptr)&attr - size + 4096; @@ -92,7 +47,7 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void*, void*); static void* threadentry(void *v) { @@ -109,6 +64,6 @@ threadentry(void *v) */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; - crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g); return nil; } diff --git a/src/pkg/runtime/cgo/gcc_netbsd_arm.c b/src/pkg/runtime/cgo/gcc_netbsd_arm.c index d93b531e7b..68c8b6e718 100644 --- a/src/pkg/runtime/cgo/gcc_netbsd_arm.c +++ b/src/pkg/runtime/cgo/gcc_netbsd_arm.c @@ -10,64 +10,15 @@ static void *threadentry(void*); -// We have to resort to TLS variable to save g(R10) and -// m(R9). One reason is that external code might trigger -// SIGSEGV, and our runtime.sigtramp don't even know we -// are in external code, and will continue to use R10/R9, -// this might as well result in another SIGSEGV. -// Note: all three functions will clobber R0, and the last -// two can be called from 5c ABI code. -void __aeabi_read_tp(void) __attribute__((naked)); -void x_cgo_save_gm(void) __attribute__((naked)); -void x_cgo_load_gm(void) __attribute__((naked)); +static void (*setmg_gcc)(void*, void*); void -__aeabi_read_tp(void) -{ - // this function is only allowed to clobber r0 - __asm__ __volatile__ ( - "mrc p15, 0, r0, c13, c0, 3\n\t" - "cmp r0, #0\n\t" - "movne pc, lr\n\t" - "push {r1,r2,r3,r12}\n\t" - "svc 0x00a0013c\n\t" // _lwp_getprivate - "pop {r1,r2,r3,r12}\n\t" - "mov pc, lr\n\t" - ); -} - -// g (R10) at 8(TP), m (R9) at 12(TP) -void -x_cgo_load_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "ldr r10, [r0, #8]\n\t" - "ldr r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_save_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "str r10, [r0, #8]\n\t" - "str r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_init(G *g) +x_cgo_init(G *g, void (*setmg)(void*, void*)) { pthread_attr_t attr; size_t size; - x_cgo_save_gm(); // save g and m for the initial thread + setmg_gcc = setmg; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); g->stackguard = (uintptr)&attr - size + 4096; @@ -100,7 +51,7 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void *g, void *m); static void* threadentry(void *v) { @@ -117,6 +68,6 @@ threadentry(void *v) */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; - crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g); return nil; } diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c index 7b0253191f..611ddf0e9e 100644 --- a/src/pkg/runtime/cgocall.c +++ b/src/pkg/runtime/cgocall.c @@ -87,11 +87,6 @@ void *_cgo_init; /* filled in by dynamic linker when Cgo is available */ static int64 cgosync; /* represents possible synchronization in C code */ -// These two are only used by the architecture where TLS based storage isn't -// the default for g and m (e.g., ARM) -void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */ -void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */ - static void unwindm(void); // Call from Go to C. diff --git a/src/pkg/runtime/os_linux_arm.c b/src/pkg/runtime/os_linux_arm.c index d22861ed3a..570b3f0bee 100644 --- a/src/pkg/runtime/os_linux_arm.c +++ b/src/pkg/runtime/os_linux_arm.c @@ -35,16 +35,13 @@ runtime·checkgoarm(void) #pragma textflag NOSPLIT void -runtime·setup_auxv(int32 argc, void *argv_list) +runtime·setup_auxv(int32 argc, byte **argv) { - byte **argv; byte **envp; byte *rnd; uint32 *auxv; uint32 t; - argv = &argv_list; - // skip envp to get to ELF auxiliary vector. for(envp = &argv[argc+1]; *envp != nil; envp++) ; diff --git a/src/pkg/runtime/rt0_freebsd_arm.s b/src/pkg/runtime/rt0_freebsd_arm.s index 16011a8065..d110876395 100644 --- a/src/pkg/runtime/rt0_freebsd_arm.s +++ b/src/pkg/runtime/rt0_freebsd_arm.s @@ -7,4 +7,7 @@ // FreeBSD and Linux use the same linkage to main TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4 + MOVW (R13), R0 // argc + MOVW $4(R13), R1 // argv + MOVM.DB.W [R0-R1], (R13) B _rt0_go(SB) diff --git a/src/pkg/runtime/rt0_linux_arm.s b/src/pkg/runtime/rt0_linux_arm.s index 13d5bd8a07..63133e9ade 100644 --- a/src/pkg/runtime/rt0_linux_arm.s +++ b/src/pkg/runtime/rt0_linux_arm.s @@ -5,6 +5,12 @@ #include "../../cmd/ld/textflag.h" TEXT _rt0_arm_linux(SB),NOSPLIT,$-4 + MOVW (R13), R0 // argc + MOVW $4(R13), R1 // argv + MOVW $_rt0_arm_linux1(SB), R4 + B (R4) + +TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4 // We first need to detect the kernel ABI, and warn the user // if the system only supports OABI // The strategy here is to call some EABI syscall to see if @@ -14,6 +20,8 @@ TEXT _rt0_arm_linux(SB),NOSPLIT,$-4 // we don't know the kernel ABI... Oh, not really, we can do // syscall in Thumb mode. + // Save argc and argv + MOVM.DB.W [R0-R1], (R13) // set up sa_handler MOVW $bad_abi<>(SB), R0 // sa_handler MOVW $0, R1 // sa_flags @@ -72,3 +80,7 @@ TEXT oabi_syscall<>(SB),NOSPLIT,$-4 // TODO(minux): only supports little-endian CPUs WORD $0x4770df01 // swi $1; bx lr +TEXT main(SB),NOSPLIT,$-4 + MOVW $_rt0_arm_linux1(SB), R4 + B (R4) + diff --git a/src/pkg/runtime/rt0_netbsd_arm.s b/src/pkg/runtime/rt0_netbsd_arm.s index 3ecefb0532..36effc3c51 100644 --- a/src/pkg/runtime/rt0_netbsd_arm.s +++ b/src/pkg/runtime/rt0_netbsd_arm.s @@ -7,4 +7,7 @@ // FreeBSD/NetBSD and Linux use the same linkage to main TEXT _rt0_arm_netbsd(SB),NOSPLIT,$-4 + MOVW (R13), R0 // argc + MOVW $4(R13), R1 // argv + MOVM.DB.W [R0-R1], (R13) B _rt0_go(SB) diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s index b698b73352..1146af64ef 100644 --- a/src/pkg/runtime/sys_freebsd_arm.s +++ b/src/pkg/runtime/sys_freebsd_arm.s @@ -282,3 +282,7 @@ TEXT runtime·casp(SB),NOSPLIT,$0 // return 0; TEXT runtime·cas(SB),NOSPLIT,$0 B runtime·armcas(SB) + +TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 + MOVW $0xffff1000, R0 + MOVW (R0), R0 diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/pkg/runtime/sys_linux_arm.s index 0e540f1c84..42aef56a76 100644 --- a/src/pkg/runtime/sys_linux_arm.s +++ b/src/pkg/runtime/sys_linux_arm.s @@ -286,11 +286,11 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$0 TEXT runtime·sigtramp(SB),NOSPLIT,$24 // this might be called in external code context, // where g and m are not set. - // first save R0, because _cgo_load_gm will clobber it + // first save R0, because runtime·load_gm will clobber it MOVW R0, 4(R13) - MOVW _cgo_load_gm(SB), R0 + MOVB runtime·iscgo(SB), R0 CMP $0, R0 - BL.NE (R0) + BL.NE runtime·load_gm(SB) CMP $0, m BNE 4(PC) @@ -441,3 +441,8 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0 MOVW $SYS_fcntl, R7 SWI $0 RET + +// b __kuser_get_tls @ 0xffff0fe0 +TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 + MOVW $0xffff0fe0, R0 + B (R0) diff --git a/src/pkg/runtime/sys_netbsd_arm.s b/src/pkg/runtime/sys_netbsd_arm.s index 7c2fe3444f..b660072102 100644 --- a/src/pkg/runtime/sys_netbsd_arm.s +++ b/src/pkg/runtime/sys_netbsd_arm.s @@ -301,3 +301,9 @@ TEXT runtime·casp(SB),NOSPLIT,$0 // return 0; TEXT runtime·cas(SB),NOSPLIT,$0 B runtime·armcas(SB) + +TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 + MOVM.WP [R1, R2, R3, R12], (R13) + SWI $0x00a0013c // _lwp_getprivate + MOVM.IAW (R13), [R1, R2, R3, R12] + RET |
