]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: linux/arm64 cgo support
authorShenghou Ma <minux@golang.org>
Fri, 3 Apr 2015 08:37:20 +0000 (04:37 -0400)
committerMinux Ma <minux@golang.org>
Wed, 8 Apr 2015 09:08:12 +0000 (09:08 +0000)
Change-Id: I309e3df7608b9eef9339196fdc50dedf5f9439f2
Reviewed-on: https://go-review.googlesource.com/8439
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Aram Hăvărneanu <aram@mgk.ro>
src/runtime/cgo/asm_arm64.s [new file with mode: 0644]
src/runtime/cgo/gcc_arm64.S [new file with mode: 0644]
src/runtime/cgo/gcc_linux_arm64.c [new file with mode: 0644]

diff --git a/src/runtime/cgo/asm_arm64.s b/src/runtime/cgo/asm_arm64.s
new file mode 100644 (file)
index 0000000..be03993
--- /dev/null
@@ -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 (file)
index 0000000..be4600f
--- /dev/null
@@ -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 (file)
index 0000000..ea11cf5
--- /dev/null
@@ -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 <pthread.h>
+#include <string.h>
+#include <signal.h>
+#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);
+       }
+}