From b6687c8933e2e123cd336d6ee96aa43df40bfc24 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 27 Apr 2016 22:18:24 -0400 Subject: [PATCH] runtime: add linux/mips64x cgo support Change-Id: Id40dd05b7b264f3b779fdf9ccc2421ba4bc70589 Reviewed-on: https://go-review.googlesource.com/19806 Reviewed-by: Minux Ma --- src/runtime/asm_mips64x.s | 100 +++++++++++++++++++++++++------- src/runtime/cgo_mips64x.go | 12 ++++ src/runtime/cgocall.go | 6 +- src/runtime/sys_linux_mips64x.s | 4 +- src/runtime/tls_mips64x.s | 7 +++ 5 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 src/runtime/cgo_mips64x.go diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index 85b71d2d90..7dd35aa0f5 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -31,7 +31,15 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0 MOVV R1, (g_stack+stack_lo)(g) MOVV R29, (g_stack+stack_hi)(g) - // no cgo yet + // if there is a _cgo_init, call it using the gcc ABI. + MOVV _cgo_init(SB), R25 + BEQ R25, nocgo + + MOVV R0, R7 // arg 3: not used + MOVV R0, R6 // arg 2: not used + MOVV $setg_gcc<>(SB), R5 // arg 1: setg + MOVV g, R4 // arg 0: G + JAL (R25) nocgo: // update stackguard after _cgo_init @@ -81,7 +89,7 @@ TEXT runtime·asminit(SB),NOSPLIT,$-8-0 RET TEXT _cgo_reginit(SB),NOSPLIT,$-8-0 - // crosscall_ppc64 and crosscall2 need to reginit, but can't + // crosscall1 needs to reginit, but can't // get at the 'runtime.reginit' symbol. JMP runtime·reginit(SB) @@ -453,26 +461,64 @@ TEXT gosave<>(SB),NOSPLIT,$-8 // aligned appropriately for the gcc ABI. // See cgocall.go for more details. TEXT ·asmcgocall(SB),NOSPLIT,$0-20 - UNDEF // no cgo yet + MOVV fn+0(FP), R25 + MOVV arg+8(FP), R4 + + MOVV R29, R3 // save original stack pointer + MOVV g, R2 + + // Figure out if we need to switch to m->g0 stack. + // We get called to create new OS threads too, and those + // come in on the m->g0 stack already. + MOVV g_m(g), R5 + MOVV m_g0(R5), R6 + BEQ R6, g, g0 + + JAL gosave<>(SB) + MOVV R6, g + JAL runtime·save_g(SB) + MOVV (g_sched+gobuf_sp)(g), R29 + + // Now on a scheduling stack (a pthread-created stack). +g0: + // Save room for two of our pointers. + ADDV $-16, R29 + MOVV R2, 0(R29) // save old g on stack + MOVV (g_stack+stack_hi)(R2), R2 + SUBVU R3, R2 + MOVV R2, 8(R29) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) + JAL (R25) + + // Restore g, stack pointer. R2 is return value. + MOVV 0(R29), g + JAL runtime·save_g(SB) + MOVV (g_stack+stack_hi)(g), R5 + MOVV 8(R29), R6 + SUBVU R6, R5 + MOVV R5, R29 + + MOVW R2, ret+16(FP) RET -// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) +// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) // Turn the fn into a Go func (by taking its address) and call // cgocallback_gofunc. -TEXT runtime·cgocallback(SB),NOSPLIT,$24-24 +TEXT runtime·cgocallback(SB),NOSPLIT,$32-32 MOVV $fn+0(FP), R1 MOVV R1, 8(R29) MOVV frame+8(FP), R1 MOVV R1, 16(R29) MOVV framesize+16(FP), R1 MOVV R1, 24(R29) + MOVV ctxt+24(FP), R1 + MOVV R1, 32(R29) MOVV $runtime·cgocallback_gofunc(SB), R1 JAL (R1) RET -// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize) +// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) // See cgocall.go for more details. -TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24 +TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32 NO_LOCAL_POINTERS // Load m and g from thread-local storage. @@ -508,8 +554,8 @@ needm: // and then systemstack will try to use it. If we don't set it here, // that restored SP will be uninitialized (typically 0) and // will not be usable. - MOVV g_m(g), R1 - MOVV m_g0(R1), R1 + MOVV g_m(g), R3 + MOVV m_g0(R3), R1 MOVV R29, (g_sched+gobuf_sp)(R1) havem: @@ -537,18 +583,21 @@ havem: // so that the traceback will seamlessly trace back into // the earlier calls. // - // In the new goroutine, -16(SP) and -8(SP) are unused. + // In the new goroutine, -8(SP) is unused (where SP refers to + // m->curg's SP while we're setting it up, before we've adjusted it). MOVV m_curg(R3), g JAL runtime·save_g(SB) MOVV (g_sched+gobuf_sp)(g), R2 // prepare stack as R2 - MOVV (g_sched+gobuf_pc)(g), R3 - MOVV R3, -24(R2) + MOVV (g_sched+gobuf_pc)(g), R4 + MOVV R4, -24(R2) + MOVV ctxt+24(FP), R1 + MOVV R1, -16(R2) MOVV $-24(R2), R29 JAL runtime·cgocallbackg(SB) // Restore g->sched (== m->curg->sched) from saved values. - MOVV 0(R29), R3 - MOVV R3, (g_sched+gobuf_pc)(g) + MOVV 0(R29), R4 + MOVV R4, (g_sched+gobuf_pc)(g) MOVV $24(R29), R2 MOVV R2, (g_sched+gobuf_sp)(g) @@ -580,10 +629,10 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8 JAL runtime·save_g(SB) RET -// void setg_gcc(G*); set g in C TLS. -// Must obey the gcc calling convention. -TEXT setg_gcc<>(SB),NOSPLIT,$-8-0 - UNDEF // no cgo yet +// void setg_gcc(G*); set g called from gcc with g in R1 +TEXT setg_gcc<>(SB),NOSPLIT,$0-0 + MOVV R1, g + JAL runtime·save_g(SB) RET TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 @@ -805,8 +854,19 @@ TEXT runtime·return0(SB), NOSPLIT, $0 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. // Must obey the gcc calling convention. -TEXT _cgo_topofstack(SB),NOSPLIT,$-8 - UNDEF // no cgo yet +TEXT _cgo_topofstack(SB),NOSPLIT,$16 + // g (R30) and REGTMP (R23) might be clobbered by load_g. They + // are callee-save in the gcc calling convention, so save them. + MOVV R23, savedR23-16(SP) + MOVV g, savedG-8(SP) + + JAL runtime·load_g(SB) + MOVV g_m(g), R1 + MOVV m_curg(R1), R1 + MOVV (g_stack+stack_hi)(R1), R2 // return value in R2 + + MOVV savedG-8(SP), g + MOVV savedR23-16(SP), R23 RET // The top-most function running on a goroutine diff --git a/src/runtime/cgo_mips64x.go b/src/runtime/cgo_mips64x.go new file mode 100644 index 0000000000..f718e92912 --- /dev/null +++ b/src/runtime/cgo_mips64x.go @@ -0,0 +1,12 @@ +// Copyright 2016 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. + +// +build mips64 mips64le + +package runtime + +// crosscall1 calls into the runtime to set up the registers the +// Go runtime expects and so the symbol it calls needs to be exported +// for external linking to work. +//go:cgo_export_static _cgo_reginit diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 6dceff09ef..8457fb2de7 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -286,6 +286,10 @@ func cgocallbackg1(ctxt uintptr) { // | | fixed frame area | // +--------------------+------------------------------+ <- sp cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize)) + case "mips64", "mips64le": + // On mips64x, stack frame is two words and there's a saved LR between + // SP and the stack frame and between the stack frame and the arguments. + cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize)) } // Invoke callback. @@ -323,7 +327,7 @@ func unwindm(restore *bool) { switch GOARCH { default: throw("unwindm not implemented") - case "386", "amd64", "arm", "ppc64", "ppc64le", "s390x": + case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x": sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize)) case "arm64": sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16)) diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index e84b2c5bd5..d4a81ca364 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -228,8 +228,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 MOVW sig+8(FP), R4 MOVV info+16(FP), R5 MOVV ctx+24(FP), R6 - MOVV fn+0(FP), R1 - JAL (R1) + MOVV fn+0(FP), R25 + JAL (R25) RET TEXT runtime·sigtramp(SB),NOSPLIT,$64 diff --git a/src/runtime/tls_mips64x.s b/src/runtime/tls_mips64x.s index 870eecb8dd..53bd6f2615 100644 --- a/src/runtime/tls_mips64x.s +++ b/src/runtime/tls_mips64x.s @@ -16,8 +16,15 @@ TEXT runtime·save_g(SB),NOSPLIT,$-8-0 MOVB runtime·iscgo(SB), R23 BEQ R23, nocgo + MOVV R3, R23 // save R3 + MOVV g, runtime·tls_g(SB) // TLS relocation clobbers R3 + MOVV R23, R3 // restore R3 + nocgo: RET TEXT runtime·load_g(SB),NOSPLIT,$-8-0 + MOVV runtime·tls_g(SB), g // TLS relocation clobbers R3 RET + +GLOBL runtime·tls_g(SB), TLSBSS, $8 -- 2.48.1