]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add support for openbsd/ppc64
authorJoel Sing <joel@sing.id.au>
Sat, 11 Mar 2023 15:09:06 +0000 (02:09 +1100)
committerJoel Sing <joel@sing.id.au>
Tue, 22 Aug 2023 02:48:11 +0000 (02:48 +0000)
Add runtime support for the openbsd/ppc64 port.

Updates #56001

Change-Id: I3cf010b34f96ce269858b02f16481fdad2cd5b77
Reviewed-on: https://go-review.googlesource.com/c/go/+/475618
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Paul Murphy <murp@ibm.com>
Run-TryBot: Joel Sing <joel@sing.id.au>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Eric Grosse <grosse@gmail.com>
src/runtime/asm_ppc64x.s
src/runtime/crash_unix_test.go
src/runtime/defs_openbsd_ppc64.go [new file with mode: 0644]
src/runtime/rt0_openbsd_ppc64.s [new file with mode: 0644]
src/runtime/signal_openbsd_ppc64.go [new file with mode: 0644]
src/runtime/signal_ppc64x.go
src/runtime/stubs_ppc64x.go
src/runtime/sys_openbsd_ppc64.s [new file with mode: 0644]
src/runtime/tls_ppc64x.s

index 5ff89cdeef9a0350363c00a470605ce3749c896b..8d8b576d3d717a8a7f3952ed4834ee3836758a39 100644 (file)
@@ -545,6 +545,43 @@ TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
 #define asmcgocallSaveOffset cgoCalleeStackSize
 #endif
 
+// func asmcgocall_no_g(fn, arg unsafe.Pointer)
+// Call fn(arg) aligned appropriately for the gcc ABI.
+// Called on a system stack, and there may be no g yet (during needm).
+TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
+       MOVD    fn+0(FP), R3
+       MOVD    arg+8(FP), R4
+
+       MOVD    R1, R15
+       SUB     $(asmcgocallSaveOffset+8), R1
+       RLDCR   $0, R1, $~15, R1        // 16-byte alignment for gcc ABI
+       MOVD    R15, asmcgocallSaveOffset(R1)
+
+       MOVD    R0, 0(R1)       // clear back chain pointer (TODO can we give it real back trace information?)
+
+       // This is a "global call", so put the global entry point in r12
+       MOVD    R3, R12
+
+#ifdef GO_PPC64X_HAS_FUNCDESC
+       // Load the real entry address from the first slot of the function descriptor.
+       MOVD    8(R12), R2
+       MOVD    (R12), R12
+#endif
+       MOVD    R12, CTR
+       MOVD    R4, R3          // arg in r3
+       BL      (CTR)
+
+       // C code can clobber R0, so set it back to 0. F27-F31 are
+       // callee save, so we don't need to recover those.
+       XOR     R0, R0
+
+       MOVD    asmcgocallSaveOffset(R1), R1    // Restore stack pointer.
+#ifndef GOOS_aix
+       MOVD    24(R1), R2
+#endif
+
+       RET
+
 // func asmcgocall(fn, arg unsafe.Pointer) int32
 // Call fn(arg) on the scheduler stack,
 // aligned appropriately for the gcc ABI.
@@ -677,9 +714,11 @@ TEXT ·cgocallback(SB),NOSPLIT,$24-24
 
 loadg:
        // Load m and g from thread-local storage.
+#ifndef GOOS_openbsd
        MOVBZ   runtime·iscgo(SB), R3
        CMP     R3, $0
        BEQ     nocgo
+#endif
        BL      runtime·load_g(SB)
 nocgo:
 
index 6bca2ac66e480a9e5df4f146090e25031e9905a1..8f6880b417648d1178c1250354662a0976759402 100644 (file)
@@ -65,7 +65,7 @@ func TestCrashDumpsAllThreads(t *testing.T) {
                t.Skipf("skipping; not supported on %v", runtime.GOOS)
        }
 
-       if runtime.GOOS == "openbsd" && (runtime.GOARCH == "arm" || runtime.GOARCH == "mips64") {
+       if runtime.GOOS == "openbsd" && (runtime.GOARCH == "arm" || runtime.GOARCH == "mips64" || runtime.GOARCH == "ppc64") {
                // This may be ncpu < 2 related...
                t.Skipf("skipping; test fails on %s/%s - see issue #42464", runtime.GOOS, runtime.GOARCH)
        }
diff --git a/src/runtime/defs_openbsd_ppc64.go b/src/runtime/defs_openbsd_ppc64.go
new file mode 100644 (file)
index 0000000..dd23ce9
--- /dev/null
@@ -0,0 +1,183 @@
+// Copyright 2023 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.
+
+// Generated from:
+//
+//   GOARCH=ppc64 go tool cgo -godefs defs_openbsd.go
+//
+// Then converted to the form used by the runtime.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+       _EAGAIN = 0x23
+
+       _O_WRONLY   = 0x1
+       _O_NONBLOCK = 0x4
+       _O_CREAT    = 0x200
+       _O_TRUNC    = 0x400
+       _O_CLOEXEC  = 0x10000
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x1000
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+       _MAP_STACK   = 0x4000
+
+       _MADV_DONTNEED = 0x4
+       _MADV_FREE     = 0x6
+
+       _SA_SIGINFO = 0x40
+       _SA_RESTART = 0x2
+       _SA_ONSTACK = 0x1
+
+       _PTHREAD_CREATE_DETACHED = 0x1
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGEMT    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGBUS    = 0xa
+       _SIGSEGV   = 0xb
+       _SIGSYS    = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGTERM   = 0xf
+       _SIGURG    = 0x10
+       _SIGSTOP   = 0x11
+       _SIGTSTP   = 0x12
+       _SIGCONT   = 0x13
+       _SIGCHLD   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGIO     = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGINFO   = 0x1d
+       _SIGUSR1   = 0x1e
+       _SIGUSR2   = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_ERROR     = 0x4000
+       _EV_EOF       = 0x8000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type tforkt struct {
+       tf_tcb   unsafe.Pointer
+       tf_tid   *int32
+       tf_stack uintptr
+}
+
+type sigcontext struct {
+       sc_cookie uint64
+       sc_mask   int32
+       sc_reg    [32]uint64
+       sc_lr     uint64
+       sc_cr     uint64
+       sc_xer    uint64
+       sc_ctr    uint64
+       sc_pc     uint64
+       sc_ps     uint64
+       sc_vrsave uint64
+       pad_cgo_0 [8]byte
+       sc_vsx    [64][16]uint8
+       sc_fpscr  uint64
+       sc_vscr   uint64
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_code   int32
+       si_errno  int32
+       pad_cgo_0 [4]byte
+       _data     [120]byte
+}
+
+type stackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+//go:nosplit
+func (ts *timespec) setNsec(ns int64) {
+       ts.tv_sec = ns / 1e9
+       ts.tv_nsec = ns % 1e9
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint64
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
+
+type pthread uintptr
+type pthreadattr uintptr
+type pthreadcond uintptr
+type pthreadcondattr uintptr
+type pthreadmutex uintptr
+type pthreadmutexattr uintptr
diff --git a/src/runtime/rt0_openbsd_ppc64.s b/src/runtime/rt0_openbsd_ppc64.s
new file mode 100644 (file)
index 0000000..9fcad4f
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2023 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"
+
+TEXT _rt0_ppc64_openbsd(SB),NOSPLIT,$0
+       BR      main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+       // Make sure R0 is zero before _main
+       XOR     R0, R0
+
+       MOVD    $runtime·rt0_go(SB), R12
+       MOVD    R12, CTR
+       BR      (CTR)
diff --git a/src/runtime/signal_openbsd_ppc64.go b/src/runtime/signal_openbsd_ppc64.go
new file mode 100644 (file)
index 0000000..be7217e
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright 2023 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.
+
+package runtime
+
+import (
+       "internal/goarch"
+       "unsafe"
+)
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func (c *sigctxt) regs() *sigcontext {
+       return (*sigcontext)(c.ctxt)
+}
+
+func (c *sigctxt) r0() uint64  { return c.regs().sc_reg[0] }
+func (c *sigctxt) r1() uint64  { return c.regs().sc_reg[1] }
+func (c *sigctxt) r2() uint64  { return c.regs().sc_reg[2] }
+func (c *sigctxt) r3() uint64  { return c.regs().sc_reg[3] }
+func (c *sigctxt) r4() uint64  { return c.regs().sc_reg[4] }
+func (c *sigctxt) r5() uint64  { return c.regs().sc_reg[5] }
+func (c *sigctxt) r6() uint64  { return c.regs().sc_reg[6] }
+func (c *sigctxt) r7() uint64  { return c.regs().sc_reg[7] }
+func (c *sigctxt) r8() uint64  { return c.regs().sc_reg[8] }
+func (c *sigctxt) r9() uint64  { return c.regs().sc_reg[9] }
+func (c *sigctxt) r10() uint64 { return c.regs().sc_reg[10] }
+func (c *sigctxt) r11() uint64 { return c.regs().sc_reg[11] }
+func (c *sigctxt) r12() uint64 { return c.regs().sc_reg[12] }
+func (c *sigctxt) r13() uint64 { return c.regs().sc_reg[13] }
+func (c *sigctxt) r14() uint64 { return c.regs().sc_reg[14] }
+func (c *sigctxt) r15() uint64 { return c.regs().sc_reg[15] }
+func (c *sigctxt) r16() uint64 { return c.regs().sc_reg[16] }
+func (c *sigctxt) r17() uint64 { return c.regs().sc_reg[17] }
+func (c *sigctxt) r18() uint64 { return c.regs().sc_reg[18] }
+func (c *sigctxt) r19() uint64 { return c.regs().sc_reg[19] }
+func (c *sigctxt) r20() uint64 { return c.regs().sc_reg[20] }
+func (c *sigctxt) r21() uint64 { return c.regs().sc_reg[21] }
+func (c *sigctxt) r22() uint64 { return c.regs().sc_reg[22] }
+func (c *sigctxt) r23() uint64 { return c.regs().sc_reg[23] }
+func (c *sigctxt) r24() uint64 { return c.regs().sc_reg[24] }
+func (c *sigctxt) r25() uint64 { return c.regs().sc_reg[25] }
+func (c *sigctxt) r26() uint64 { return c.regs().sc_reg[26] }
+func (c *sigctxt) r27() uint64 { return c.regs().sc_reg[27] }
+func (c *sigctxt) r28() uint64 { return c.regs().sc_reg[28] }
+func (c *sigctxt) r29() uint64 { return c.regs().sc_reg[29] }
+func (c *sigctxt) r30() uint64 { return c.regs().sc_reg[30] }
+func (c *sigctxt) r31() uint64 { return c.regs().sc_reg[31] }
+func (c *sigctxt) sp() uint64  { return c.regs().sc_reg[1] }
+
+//go:nosplit
+//go:nowritebarrierrec
+func (c *sigctxt) pc() uint64 { return c.regs().sc_pc }
+
+func (c *sigctxt) trap() uint64 { return 0 /* XXX - c.regs().trap */ }
+func (c *sigctxt) ctr() uint64  { return c.regs().sc_ctr }
+func (c *sigctxt) link() uint64 { return c.regs().sc_lr }
+func (c *sigctxt) xer() uint64  { return c.regs().sc_xer }
+func (c *sigctxt) ccr() uint64  { return c.regs().sc_cr }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 {
+       return *(*uint64)(add(unsafe.Pointer(c.info), 16))
+}
+func (c *sigctxt) fault() uintptr { return uintptr(c.sigaddr()) }
+
+func (c *sigctxt) set_r0(x uint64)   { c.regs().sc_reg[0] = x }
+func (c *sigctxt) set_r12(x uint64)  { c.regs().sc_reg[12] = x }
+func (c *sigctxt) set_r30(x uint64)  { c.regs().sc_reg[30] = x }
+func (c *sigctxt) set_pc(x uint64)   { c.regs().sc_pc = x }
+func (c *sigctxt) set_sp(x uint64)   { c.regs().sc_reg[1] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().sc_lr = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*goarch.PtrSize)) = uintptr(x)
+}
index bdd354026cb0ad04c8eb61b78692cf4ed3d7a3c4..930c468010b4922ce79859139cf8c3ad6acd9cca 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build (aix || linux) && (ppc64 || ppc64le)
+//go:build (aix || linux || openbsd) && (ppc64 || ppc64le)
 
 package runtime
 
index 0b7771ef03006e00249aa89ae8c9bb3c2be2d660..36b01a72b15197975c13f939d2eecea7d13c46f6 100644 (file)
@@ -6,11 +6,16 @@
 
 package runtime
 
+import "unsafe"
+
 // Called from assembly only; declared for go vet.
 func load_g()
 func save_g()
 func reginit()
 
+//go:noescape
+func asmcgocall_no_g(fn, arg unsafe.Pointer)
+
 // Spills/loads arguments in registers to/from an internal/abi.RegArgs
 // respectively. Does not follow the Go ABI.
 func spillArgs()
diff --git a/src/runtime/sys_openbsd_ppc64.s b/src/runtime/sys_openbsd_ppc64.s
new file mode 100644 (file)
index 0000000..a1c67c8
--- /dev/null
@@ -0,0 +1,655 @@
+// Copyright 2023 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.
+//
+// System calls and other sys.stuff for ppc64, OpenBSD
+// System calls are implemented in libc/libpthread, this file
+// contains trampolines that convert from Go to C calling convention.
+// Some direct system call implementations currently remain.
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define CLOCK_REALTIME $0
+#define        CLOCK_MONOTONIC $3
+
+// mstart_stub is the first function executed on a new thread started by pthread_create.
+// It just does some low-level setup and then calls mstart.
+// Note: called with the C calling convention.
+TEXT runtime·mstart_stub(SB),NOSPLIT,$32
+       // R3 points to the m.
+       // We are already on m's g0 stack.
+
+       // Go relies on R0 being $0.
+       XOR     R0, R0
+
+       // TODO(jsing): Save callee-save registers (R14-R31, F14-F31, V20-V31).
+
+       MOVD    m_g0(R3), g
+       BL      runtime·save_g(SB)
+
+       BL      runtime·mstart(SB)
+
+       // TODO(jsing): Restore callee-save registers (R14-R31, F14-F31, V20-V31).
+
+       // Go is all done with this OS thread.
+       // Tell pthread everything is ok (we never join with this thread, so
+       // the value here doesn't really matter).
+       MOVD    $0, R3
+
+       RET
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+       MOVW    sig+8(FP), R3
+       MOVD    info+16(FP), R4
+       MOVD    ctx+24(FP), R5
+       MOVD    fn+0(FP), R12
+       MOVD    R12, CTR
+       CALL    (CTR)                   // Alignment for ELF ABI?
+       RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$16
+       // Go relies on R0 being $0 and we may have been executing non-Go code.
+       XOR     R0, R0
+
+       // TODO(jsing): Save callee-save registers (R2, R14-R31, F14-F31).
+       // in the case of signal forwarding.
+       // Please refer to https://golang.org/issue/31827 .
+
+       // If called from an external code context, g will not be set.
+       BL      runtime·load_g(SB)
+
+       BL      runtime·sigtrampgo<ABIInternal>(SB)
+
+       // TODO(jsing): Restore callee-save registers.
+
+       RET
+
+// These trampolines help convert from Go calling convention to C calling convention.
+// They should be called with asmcgocall.
+// A pointer to the arguments is passed in R3.
+// A single int32 result is returned in R3.
+// (For more results, make an args/results structure.)
+TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$32
+       MOVD    0(R3), R3               // arg 1 - attr
+       CALL    libc_pthread_attr_init(SB)
+       RET
+
+TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$32
+       MOVD    0(R3), R3               // arg 1 - attr
+       CALL    libc_pthread_attr_destroy(SB)
+       RET
+
+TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - size
+       MOVD    0(R3), R3               // arg 1 - attr
+       CALL    libc_pthread_attr_getstacksize(SB)
+       RET
+
+TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - state
+       MOVD    0(R3), R3               // arg 1 - attr
+       CALL    libc_pthread_attr_setdetachstate(SB)
+       RET
+
+TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$32
+       MOVD    0(R3), R4               // arg 2 - attr
+       MOVD    8(R3), R5               // arg 3 - start
+       MOVD    16(R3), R6              // arg 4 - arg
+
+       MOVD    R1, R15
+       SUB     $64, R1
+       RLDCR   $0, R1, $~15, R1
+       MOVD    R1, R3                  // arg 1 - &threadid (discard)
+       CALL    libc_pthread_create(SB)
+       MOVD    R15, R1
+
+       RET
+
+TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - signal (int64)
+       MOVD    $0, R5                  // arg 3 - tcb
+       MOVW    0(R3), R3               // arg 1 - tid
+       CALL    libc_thrkill(SB)
+       RET
+
+TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$32
+       MOVW    8(R3), R4               // arg 2 - clock_id
+       MOVD    16(R3), R5              // arg 3 - abstime
+       MOVD    24(R3), R6              // arg 4 - lock
+       MOVD    32(R3), R7              // arg 5 - abort
+       MOVD    0(R3), R3               // arg 1 - id
+       CALL    libc_thrsleep(SB)
+       RET
+
+TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$32
+       MOVW    8(R3), R4               // arg 2 - count
+       MOVD    0(R3), R3               // arg 1 - id
+       CALL    libc_thrwakeup(SB)
+       RET
+
+TEXT runtime·exit_trampoline(SB),NOSPLIT,$32
+       MOVW    0(R3), R3               // arg 1 - status
+       CALL    libc_exit(SB)
+       MOVD    $0, R3                  // crash on failure
+       MOVD    R3, (R3)
+       RET
+
+TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+       CALL    libc_getthrid(SB)
+       MOVW    R3, 0(R14)              // return value
+       RET
+
+TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+       CALL    libc_getpid(SB)         // arg 1 - pid
+       MOVW    0(R14), R4              // arg 2 - signal
+       CALL    libc_kill(SB)
+       RET
+
+TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$32
+       CALL    libc_sched_yield(SB)
+       RET
+
+TEXT runtime·mmap_trampoline(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+       MOVD    0(R14), R3              // arg 1 - addr
+       MOVD    8(R14), R4              // arg 2 - len
+       MOVW    16(R14), R5             // arg 3 - prot
+       MOVW    20(R14), R6             // arg 4 - flags
+       MOVW    24(R14), R7             // arg 5 - fid
+       MOVW    28(R14), R8             // arg 6 - offset
+       CALL    libc_mmap(SB)
+       MOVD    $0, R4
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R4                // errno
+       MOVD    $0, R3
+noerr:
+       MOVD    R3, 32(R14)
+       MOVD    R4, 40(R14)
+       RET
+
+TEXT runtime·munmap_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - len
+       MOVD    0(R3), R3               // arg 1 - addr
+       CALL    libc_munmap(SB)
+       CMP     R3, $-1
+       BNE     3(PC)
+       MOVD    $0, R3                  // crash on failure
+       MOVD    R3, (R3)
+       RET
+
+TEXT runtime·madvise_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - len
+       MOVW    16(R3), R5              // arg 3 - advice
+       MOVD    0(R3), R3               // arg 1 - addr
+       CALL    libc_madvise(SB)
+       // ignore failure - maybe pages are locked
+       RET
+
+TEXT runtime·open_trampoline(SB),NOSPLIT,$32
+       MOVW    8(R3), R4               // arg 2 - flags
+       MOVW    12(R3), R5              // arg 3 - mode
+       MOVD    0(R3), R3               // arg 1 - path
+       MOVD    $0, R6                  // varargs
+       CALL    libc_open(SB)
+       RET
+
+TEXT runtime·close_trampoline(SB),NOSPLIT,$32
+       MOVW    0(R3), R3               // arg 1 - fd
+       CALL    libc_close(SB)
+       RET
+
+TEXT runtime·read_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - buf
+       MOVW    16(R3), R5              // arg 3 - count
+       MOVW    0(R3), R3               // arg 1 - fd (int32)
+       CALL    libc_read(SB)
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3                // errno
+       NEG     R3, R3                  // caller expects negative errno value
+noerr:
+       RET
+
+TEXT runtime·write_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - buf
+       MOVW    16(R3), R5              // arg 3 - count
+       MOVD    0(R3), R3               // arg 1 - fd (uintptr)
+       CALL    libc_write(SB)
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3                // errno
+       NEG     R3, R3                  // caller expects negative errno value
+noerr:
+       RET
+
+TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$32
+       MOVW    8(R3), R4               // arg 2 - flags
+       MOVD    0(R3), R3               // arg 1 - filedes
+       CALL    libc_pipe2(SB)
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3                // errno
+       NEG     R3, R3                  // caller expects negative errno value
+noerr:
+       RET
+
+TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - new
+       MOVD    16(R3), R5              // arg 3 - old
+       MOVW    0(R3), R3               // arg 1 - which
+       CALL    libc_setitimer(SB)
+       RET
+
+TEXT runtime·usleep_trampoline(SB),NOSPLIT,$32
+       MOVW    0(R3), R3               // arg 1 - usec
+       CALL    libc_usleep(SB)
+       RET
+
+TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$32
+       MOVW    8(R3), R4               // arg 2 - miblen
+       MOVD    16(R3), R5              // arg 3 - out
+       MOVD    24(R3), R6              // arg 4 - size
+       MOVD    32(R3), R7              // arg 5 - dst
+       MOVD    40(R3), R8              // arg 6 - ndst
+       MOVD    0(R3), R3               // arg 1 - mib
+       CALL    libc_sysctl(SB)
+       RET
+
+TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$32
+       CALL    libc_kqueue(SB)
+       RET
+
+TEXT runtime·kevent_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - keventt
+       MOVW    16(R3), R5              // arg 3 - nch
+       MOVD    24(R3), R6              // arg 4 - ev
+       MOVW    32(R3), R7              // arg 5 - nev
+       MOVD    40(R3), R8              // arg 6 - ts
+       MOVW    0(R3), R3               // arg 1 - kq
+       CALL    libc_kevent(SB)
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3                // errno
+       NEG     R3, R3                  // caller expects negative errno value
+noerr:
+       RET
+
+TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - tp
+       MOVW    0(R3), R3               // arg 1 - clock_id
+       CALL    libc_clock_gettime(SB)
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3                // errno
+       NEG     R3, R3                  // caller expects negative errno value
+noerr:
+       RET
+
+TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+       MOVW    0(R14), R3              // arg 1 - fd
+       MOVW    4(R14), R4              // arg 2 - cmd
+       MOVW    8(R14), R5              // arg 3 - arg
+       MOVD    $0, R6                  // vararg
+       CALL    libc_fcntl(SB)
+       MOVD    $0, R4
+       CMP     R3, $-1
+       BNE     noerr
+       CALL    libc_errno(SB)
+       MOVW    (R3), R4                // errno
+       MOVW    $-1, R3
+noerr:
+       MOVW    R3, 12(R14)
+       MOVW    R4, 16(R14)
+       RET
+
+TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - new
+       MOVD    16(R3), R5              // arg 3 - old
+       MOVW    0(R3), R3               // arg 1 - sig
+       CALL    libc_sigaction(SB)
+       CMP     R3, $-1
+       BNE     3(PC)
+       MOVD    $0, R3                  // crash on syscall failure
+       MOVD    R3, (R3)
+       RET
+
+TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - new
+       MOVD    16(R3), R5              // arg 3 - old
+       MOVW    0(R3), R3               // arg 1 - how
+       CALL    libc_pthread_sigmask(SB)
+       CMP     R3, $-1
+       BNE     3(PC)
+       MOVD    $0, R3                  // crash on syscall failure
+       MOVD    R3, (R3)
+       RET
+
+TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$32
+       MOVD    8(R3), R4               // arg 2 - old
+       MOVD    0(R3), R3               // arg 1 - new
+       CALL    libc_sigaltstack(SB)
+       CMP     R3, $-1
+       BNE     3(PC)
+       MOVD    $0, R3                  // crash on syscall failure
+       MOVD    R3, (R3)
+       RET
+
+TEXT runtime·issetugid_trampoline(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+       CALL    libc_getthrid(SB)
+       MOVW    R3, 0(R14)              // return value
+       RET
+
+// syscall calls a function in libc on behalf of the syscall package.
+// syscall takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscall must be called on the g0 stack with the
+// C calling convention (use libcCall).
+//
+// syscall expects a 32-bit result and tests for 32-bit -1
+// to decide there was an error.
+TEXT runtime·syscall(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    $0, R6                  // vararg
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (4*8)(R14)          // r1
+       MOVD    R4, (5*8)(R14)          // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMPW    R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (6*8)(R14)          // err
+
+ok:
+       RET
+
+// syscallX calls a function in libc on behalf of the syscall package.
+// syscallX takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscallX must be called on the g0 stack with the
+// C calling convention (use libcCall).
+//
+// syscallX is like syscall but expects a 64-bit result
+// and tests for 64-bit -1 to decide there was an error.
+TEXT runtime·syscallX(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    $0, R6                  // vararg
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (4*8)(R14)          // r1
+       MOVD    R4, (5*8)(R14)          // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMP     R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (6*8)(R14)          // err
+
+ok:
+       RET
+
+// syscall6 calls a function in libc on behalf of the syscall package.
+// syscall6 takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     a4    uintptr
+//     a5    uintptr
+//     a6    uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscall6 must be called on the g0 stack with the
+// C calling convention (use libcCall).
+//
+// syscall6 expects a 32-bit result and tests for 32-bit -1
+// to decide there was an error.
+TEXT runtime·syscall6(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    (4*8)(R14), R6          // a4
+       MOVD    (5*8)(R14), R7          // a5
+       MOVD    (6*8)(R14), R8          // a6
+       MOVD    $0, R9                  // vararg
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (7*8)(R14)          // r1
+       MOVD    R4, (8*8)(R14)          // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMPW    R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (9*8)(R14)          // err
+
+ok:
+       RET
+
+// syscall6X calls a function in libc on behalf of the syscall package.
+// syscall6X takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     a4    uintptr
+//     a5    uintptr
+//     a6    uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscall6X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+//
+// syscall6X is like syscall6 but expects a 64-bit result
+// and tests for 64-bit -1 to decide there was an error.
+TEXT runtime·syscall6X(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    (4*8)(R14), R6          // a4
+       MOVD    (5*8)(R14), R7          // a5
+       MOVD    (6*8)(R14), R8          // a6
+       MOVD    $0, R9                  // vararg
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (7*8)(R14)          // r1
+       MOVD    R4, (8*8)(R14)          // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMP     R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (9*8)(R14)          // err
+
+ok:
+       RET
+
+// syscall10 calls a function in libc on behalf of the syscall package.
+// syscall10 takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     a4    uintptr
+//     a5    uintptr
+//     a6    uintptr
+//     a7    uintptr
+//     a8    uintptr
+//     a9    uintptr
+//     a10   uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscall10 must be called on the g0 stack with the
+// C calling convention (use libcCall). Note that this is
+// really syscall8 as a maximum of eight parameters can be
+// passed via registers (and current usage does not exceed
+// this).
+TEXT runtime·syscall10(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    (4*8)(R14), R6          // a4
+       MOVD    (5*8)(R14), R7          // a5
+       MOVD    (6*8)(R14), R8          // a6
+       MOVD    (7*8)(R14), R9          // a7
+       MOVD    (8*8)(R14), R10         // a8
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (11*8)(R14)         // r1
+       MOVD    R4, (12*8)(R14)         // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMPW    R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (13*8)(R14)         // err
+
+ok:
+       RET
+
+// syscall10X calls a function in libc on behalf of the syscall package.
+// syscall10X takes a pointer to a struct like:
+// struct {
+//     fn    uintptr
+//     a1    uintptr
+//     a2    uintptr
+//     a3    uintptr
+//     a4    uintptr
+//     a5    uintptr
+//     a6    uintptr
+//     a7    uintptr
+//     a8    uintptr
+//     a9    uintptr
+//     a10   uintptr
+//     r1    uintptr
+//     r2    uintptr
+//     err   uintptr
+// }
+// syscall10X must be called on the g0 stack with the
+// C calling convention (use libcCall). Note that this is
+// really syscall8X as a maximum of eight parameters can be
+// passed via registers (and current usage does not exceed
+// this).
+//
+// syscall10X is like syscall10 but expects a 64-bit result
+// and tests for 64-bit -1 to decide there was an error.
+TEXT runtime·syscall10X(SB),NOSPLIT,$32
+       MOVD    R3, R14                 // pointer to args
+
+       MOVD    (0*8)(R14), R12         // fn
+       MOVD    (1*8)(R14), R3          // a1
+       MOVD    (2*8)(R14), R4          // a2
+       MOVD    (3*8)(R14), R5          // a3
+       MOVD    (4*8)(R14), R6          // a4
+       MOVD    (5*8)(R14), R7          // a5
+       MOVD    (6*8)(R14), R8          // a6
+       MOVD    (7*8)(R14), R9          // a7
+       MOVD    (8*8)(R14), R10         // a8
+
+       MOVD    R12, CTR
+       CALL    (CTR)
+
+       MOVD    R3, (11*8)(R14)         // r1
+       MOVD    R4, (12*8)(R14)         // r2
+
+       // Standard libc functions return -1 on error
+       // and set errno.
+       CMP     R3, $-1
+       BNE     ok
+
+       // Get error code from libc.
+       CALL    libc_errno(SB)
+       MOVW    (R3), R3
+       MOVD    R3, (13*8)(R14)         // err
+
+ok:
+       RET
index 17aec9fc1e3cb5ccd512ad46326659fb24565a8e..137214b8582c8fb18bfbfab76362c9f56fd860af 100644 (file)
 // NOTE: setg_gcc<> assume this clobbers only R31.
 TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
 #ifndef GOOS_aix
+#ifndef GOOS_openbsd
        MOVBZ   runtime·iscgo(SB), R31
        CMP     R31, $0
        BEQ     nocgo
+#endif
 #endif
        MOVD    runtime·tls_g(SB), R31
        MOVD    g, 0(R31)