From: Shenghou Ma Date: Fri, 3 Apr 2015 08:37:20 +0000 (-0400) Subject: runtime/cgo: linux/arm64 cgo support X-Git-Tag: go1.5beta1~1256 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0accc80fbbf483a8d120079bc4bc91cade8b87f2;p=gostls13.git runtime/cgo: linux/arm64 cgo support Change-Id: I309e3df7608b9eef9339196fdc50dedf5f9439f2 Reviewed-on: https://go-review.googlesource.com/8439 Reviewed-by: David Crawshaw Reviewed-by: Aram Hăvărneanu --- diff --git a/src/runtime/cgo/asm_arm64.s b/src/runtime/cgo/asm_arm64.s new file mode 100644 index 0000000000..be03993694 --- /dev/null +++ b/src/runtime/cgo/asm_arm64.s @@ -0,0 +1,57 @@ +// Copyright 2015 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. + +#include "textflag.h" + +/* + * void crosscall2(void (*fn)(void*, int32), void*, int32) + * Save registers and call fn with two arguments. + */ +TEXT crosscall2(SB),NOSPLIT,$-8 + /* + * We still need to save all callee save register as before, and then + * push 2 args for fn (R1 and R2). + * Also note that at procedure entry in 7g world, 8(RSP) will be the + * first arg. + * TODO(minux): use LDP/STP here if it matters. + */ + SUB $128, RSP + MOVD R1, (8*1)(RSP) + MOVD R2, (8*2)(RSP) + MOVD R19, (8*3)(RSP) + MOVD R20, (8*4)(RSP) + MOVD R21, (8*5)(RSP) + MOVD R22, (8*6)(RSP) + MOVD R23, (8*7)(RSP) + MOVD R24, (8*8)(RSP) + MOVD R25, (8*9)(RSP) + MOVD R26, (8*10)(RSP) + MOVD R27, (8*11)(RSP) + MOVD g, (8*12)(RSP) + MOVD R29, (8*13)(RSP) + MOVD R30, (8*14)(RSP) + + MOVD R0, R19 + + // Initialize Go ABI environment + BL runtime·reginit(SB) + BL runtime·load_g(SB) + BL (R19) + + MOVD (8*1)(RSP), R1 + MOVD (8*2)(RSP), R2 + MOVD (8*3)(RSP), R19 + MOVD (8*4)(RSP), R20 + MOVD (8*5)(RSP), R21 + MOVD (8*6)(RSP), R22 + MOVD (8*7)(RSP), R23 + MOVD (8*8)(RSP), R24 + MOVD (8*9)(RSP), R25 + MOVD (8*10)(RSP), R26 + MOVD (8*11)(RSP), R27 + MOVD (8*12)(RSP), g + MOVD (8*13)(RSP), R29 + MOVD (8*14)(RSP), R30 + ADD $128, RSP + RET diff --git a/src/runtime/cgo/gcc_arm64.S b/src/runtime/cgo/gcc_arm64.S new file mode 100644 index 0000000000..be4600f37d --- /dev/null +++ b/src/runtime/cgo/gcc_arm64.S @@ -0,0 +1,53 @@ +// Copyright 2015 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. + +/* + * Apple still insists on underscore prefixes for C function names. + */ +#if defined(__APPLE__) +#define EXT(s) _##s +#else +#define EXT(s) s +#endif + +/* + * void crosscall1(void (*fn)(void), void (*setg_gcc)(void *g), void *g) + * + * Calling into the 7g tool chain, where all registers are caller save. + * Called from standard ARM EABI, where x19-x29 are callee-save, so they + * must be saved explicitly, along with x30 (LR). + */ +.globl EXT(crosscall1) +EXT(crosscall1): + stp x19, x20, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp x29, x30, [sp, #-16]! + mov x29, sp + + mov x19, x0 + mov x20, x1 + mov x0, x2 + + blr x20 + blr x19 + + ldp x29, x30, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x19, x20, [sp], #16 + ret + +.globl EXT(__stack_chk_fail_local) +EXT(__stack_chk_fail_local): +1: + b 1b + +#ifdef __ELF__ +.section .note.GNU-stack,"",%progbits +#endif diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c new file mode 100644 index 0000000000..ea11cf5313 --- /dev/null +++ b/src/runtime/cgo/gcc_linux_arm64.c @@ -0,0 +1,73 @@ +// Copyright 2015 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. + +#include +#include +#include +#include "libcgo.h" + +static void *threadentry(void*); + +void (*x_cgo_inittls)(void **tlsg, void **tlsbase); +void (*setg_gcc)(void*); + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + pthread_sigmask(SIG_SETMASK, &ign, &oset); + + // Not sure why the memset is necessary here, + // but without it, we get a bogus stack size + // out of pthread_attr_getstacksize. C'est la Linux. + memset(&attr, 0, sizeof attr); + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); + + pthread_sigmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fatalf("pthread_create failed: %s", strerror(err)); + } +} + +extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + crosscall1(ts.fn, setg_gcc, (void*)ts.g); + return nil; +} + +void +x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +{ + pthread_attr_t attr; + size_t size; + + setg_gcc = setg; + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stacklo = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); + + if (x_cgo_inittls) { + x_cgo_inittls(tlsg, tlsbase); + } +}