From 55f8d56c31c7c940202c892e0e35d26930c6a8b0 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 25 Aug 2020 18:04:47 +1000 Subject: [PATCH] runtime: add support for openbsd/mips64 Update #40995 Change-Id: Ie028dfd87ef8731804567a0501f1f7758e8dd203 Reviewed-on: https://go-review.googlesource.com/c/go/+/250580 Trust: Joel Sing Reviewed-by: Ian Lance Taylor Run-TryBot: Joel Sing --- src/runtime/os_openbsd.go | 6 +- src/runtime/os_openbsd_mips64.go | 12 + src/runtime/rt0_openbsd_mips64.s | 36 +++ src/runtime/signal_mips64x.go | 2 +- src/runtime/signal_openbsd_mips64.go | 78 ++++++ src/runtime/sys_openbsd_mips64.s | 400 +++++++++++++++++++++++++++ 6 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 src/runtime/os_openbsd_mips64.go create mode 100644 src/runtime/rt0_openbsd_mips64.s create mode 100644 src/runtime/signal_openbsd_mips64.go create mode 100644 src/runtime/sys_openbsd_mips64.s diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go index cd3565df5b..d7960f4c91 100644 --- a/src/runtime/os_openbsd.go +++ b/src/runtime/os_openbsd.go @@ -236,7 +236,11 @@ func goenvs() { // Called to initialize a new m (including the bootstrap m). // Called on the parent thread (main thread in case of bootstrap), can allocate memory. func mpreinit(mp *m) { - mp.gsignal = malg(32 * 1024) + gsignalSize := int32(32 * 1024) + if GOARCH == "mips64" { + gsignalSize = int32(64 * 1024) + } + mp.gsignal = malg(gsignalSize) mp.gsignal.m = mp } diff --git a/src/runtime/os_openbsd_mips64.go b/src/runtime/os_openbsd_mips64.go new file mode 100644 index 0000000000..ae220cd683 --- /dev/null +++ b/src/runtime/os_openbsd_mips64.go @@ -0,0 +1,12 @@ +// Copyright 2020 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 + +//go:nosplit +func cputicks() int64 { + // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand(). + // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. + return nanotime() +} diff --git a/src/runtime/rt0_openbsd_mips64.s b/src/runtime/rt0_openbsd_mips64.s new file mode 100644 index 0000000000..82a8dfaba6 --- /dev/null +++ b/src/runtime/rt0_openbsd_mips64.s @@ -0,0 +1,36 @@ +// Copyright 2020 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_mips64_openbsd(SB),NOSPLIT,$0 + JMP _main<>(SB) + +TEXT _rt0_mips64le_openbsd(SB),NOSPLIT,$0 + JMP _main<>(SB) + +TEXT _main<>(SB),NOSPLIT|NOFRAME,$0 + // In a statically linked binary, the stack contains argc, + // argv as argc string pointers followed by a NULL, envv as a + // sequence of string pointers followed by a NULL, and auxv. + // There is no TLS base pointer. +#ifdef GOARCH_mips64 + MOVW 4(R29), R4 // argc, big-endian ABI places int32 at offset 4 +#else + MOVW 0(R29), R4 // argc +#endif + ADDV $8, R29, R5 // argv + JMP main(SB) + +TEXT main(SB),NOSPLIT|NOFRAME,$0 + // in external linking, glibc jumps to main with argc in R4 + // and argv in R5 + + // initialize REGSB = PC&0xffffffff00000000 + BGEZAL R0, 1(PC) + SRLV $32, R31, RSB + SLLV $32, RSB + + MOVV $runtime·rt0_go(SB), R1 + JMP (R1) diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 040c959f04..2a347ff4cb 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux +// +build linux openbsd // +build mips64 mips64le package runtime diff --git a/src/runtime/signal_openbsd_mips64.go b/src/runtime/signal_openbsd_mips64.go new file mode 100644 index 0000000000..54ed523c7b --- /dev/null +++ b/src/runtime/signal_openbsd_mips64.go @@ -0,0 +1,78 @@ +// Copyright 2020 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 ( + "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_regs[0] } +func (c *sigctxt) r1() uint64 { return c.regs().sc_regs[1] } +func (c *sigctxt) r2() uint64 { return c.regs().sc_regs[2] } +func (c *sigctxt) r3() uint64 { return c.regs().sc_regs[3] } +func (c *sigctxt) r4() uint64 { return c.regs().sc_regs[4] } +func (c *sigctxt) r5() uint64 { return c.regs().sc_regs[5] } +func (c *sigctxt) r6() uint64 { return c.regs().sc_regs[6] } +func (c *sigctxt) r7() uint64 { return c.regs().sc_regs[7] } +func (c *sigctxt) r8() uint64 { return c.regs().sc_regs[8] } +func (c *sigctxt) r9() uint64 { return c.regs().sc_regs[9] } +func (c *sigctxt) r10() uint64 { return c.regs().sc_regs[10] } +func (c *sigctxt) r11() uint64 { return c.regs().sc_regs[11] } +func (c *sigctxt) r12() uint64 { return c.regs().sc_regs[12] } +func (c *sigctxt) r13() uint64 { return c.regs().sc_regs[13] } +func (c *sigctxt) r14() uint64 { return c.regs().sc_regs[14] } +func (c *sigctxt) r15() uint64 { return c.regs().sc_regs[15] } +func (c *sigctxt) r16() uint64 { return c.regs().sc_regs[16] } +func (c *sigctxt) r17() uint64 { return c.regs().sc_regs[17] } +func (c *sigctxt) r18() uint64 { return c.regs().sc_regs[18] } +func (c *sigctxt) r19() uint64 { return c.regs().sc_regs[19] } +func (c *sigctxt) r20() uint64 { return c.regs().sc_regs[20] } +func (c *sigctxt) r21() uint64 { return c.regs().sc_regs[21] } +func (c *sigctxt) r22() uint64 { return c.regs().sc_regs[22] } +func (c *sigctxt) r23() uint64 { return c.regs().sc_regs[23] } +func (c *sigctxt) r24() uint64 { return c.regs().sc_regs[24] } +func (c *sigctxt) r25() uint64 { return c.regs().sc_regs[25] } +func (c *sigctxt) r26() uint64 { return c.regs().sc_regs[26] } +func (c *sigctxt) r27() uint64 { return c.regs().sc_regs[27] } +func (c *sigctxt) r28() uint64 { return c.regs().sc_regs[28] } +func (c *sigctxt) r29() uint64 { return c.regs().sc_regs[29] } +func (c *sigctxt) r30() uint64 { return c.regs().sc_regs[30] } +func (c *sigctxt) r31() uint64 { return c.regs().sc_regs[31] } +func (c *sigctxt) sp() uint64 { return c.regs().sc_regs[29] } + +//go:nosplit +//go:nowritebarrierrec +func (c *sigctxt) pc() uint64 { return c.regs().sc_pc } + +func (c *sigctxt) link() uint64 { return c.regs().sc_regs[31] } +func (c *sigctxt) lo() uint64 { return c.regs().mullo } +func (c *sigctxt) hi() uint64 { return c.regs().mulhi } + +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) set_r28(x uint64) { c.regs().sc_regs[28] = x } +func (c *sigctxt) set_r30(x uint64) { c.regs().sc_regs[30] = x } +func (c *sigctxt) set_pc(x uint64) { c.regs().sc_pc = x } +func (c *sigctxt) set_sp(x uint64) { c.regs().sc_regs[29] = x } +func (c *sigctxt) set_link(x uint64) { c.regs().sc_regs[31] = x } + +func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } +func (c *sigctxt) set_sigaddr(x uint64) { + *(*uint64)(add(unsafe.Pointer(c.info), 16)) = x +} diff --git a/src/runtime/sys_openbsd_mips64.s b/src/runtime/sys_openbsd_mips64.s new file mode 100644 index 0000000000..57a5dbd40e --- /dev/null +++ b/src/runtime/sys_openbsd_mips64.s @@ -0,0 +1,400 @@ +// Copyright 2020 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 mips64, OpenBSD +// /usr/src/sys/kern/syscalls.master for syscall numbers. +// + +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +#define CLOCK_REALTIME $0 +#define CLOCK_MONOTONIC $3 + +// Exit the entire program (like C exit) +TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 + MOVW code+0(FP), R4 // arg 1 - status + MOVV $1, R2 // sys_exit + SYSCALL + BEQ R7, 3(PC) + MOVV $0, R2 // crash on syscall failure + MOVV R2, (R2) + RET + +// func exitThread(wait *uint32) +TEXT runtime·exitThread(SB),NOSPLIT,$0 + MOVV wait+0(FP), R4 // arg 1 - notdead + MOVV $302, R2 // sys___threxit + SYSCALL + MOVV $0, R2 // crash on syscall failure + MOVV R2, (R2) + JMP 0(PC) + +TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0 + MOVV name+0(FP), R4 // arg 1 - path + MOVW mode+8(FP), R5 // arg 2 - mode + MOVW perm+12(FP), R6 // arg 3 - perm + MOVV $5, R2 // sys_open + SYSCALL + BEQ R7, 2(PC) + MOVW $-1, R2 + MOVW R2, ret+16(FP) + RET + +TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0 + MOVW fd+0(FP), R4 // arg 1 - fd + MOVV $6, R2 // sys_close + SYSCALL + BEQ R7, 2(PC) + MOVW $-1, R2 + MOVW R2, ret+8(FP) + RET + +TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0 + MOVW fd+0(FP), R4 // arg 1 - fd + MOVV p+8(FP), R5 // arg 2 - buf + MOVW n+16(FP), R6 // arg 3 - nbyte + MOVV $3, R2 // sys_read + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+24(FP) + RET + +// func pipe() (r, w int32, errno int32) +TEXT runtime·pipe(SB),NOSPLIT|NOFRAME,$0-12 + MOVV $r+0(FP), R4 + MOVW $0, R5 + MOVV $101, R2 // sys_pipe2 + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, errno+8(FP) + RET + +// func pipe2(flags int32) (r, w int32, errno int32) +TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 + MOVV $r+8(FP), R4 + MOVW flags+0(FP), R5 + MOVV $101, R2 // sys_pipe2 + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, errno+16(FP) + RET + +TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0 + MOVV fd+0(FP), R4 // arg 1 - fd + MOVV p+8(FP), R5 // arg 2 - buf + MOVW n+16(FP), R6 // arg 3 - nbyte + MOVV $4, R2 // sys_write + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+24(FP) + RET + +TEXT runtime·usleep(SB),NOSPLIT,$24-4 + MOVWU usec+0(FP), R3 + MOVV R3, R5 + MOVW $1000000, R4 + DIVVU R4, R3 + MOVV LO, R3 + MOVV R3, 8(R29) // tv_sec + MOVW $1000, R4 + MULVU R3, R4 + MOVV LO, R4 + SUBVU R4, R5 + MOVV R5, 16(R29) // tv_nsec + + ADDV $8, R29, R4 // arg 1 - rqtp + MOVV $0, R5 // arg 2 - rmtp + MOVV $91, R2 // sys_nanosleep + SYSCALL + RET + +TEXT runtime·getthrid(SB),NOSPLIT,$0-4 + MOVV $299, R2 // sys_getthrid + SYSCALL + MOVW R2, ret+0(FP) + RET + +TEXT runtime·thrkill(SB),NOSPLIT,$0-16 + MOVW tid+0(FP), R4 // arg 1 - tid + MOVV sig+8(FP), R5 // arg 2 - signum + MOVW $0, R6 // arg 3 - tcb + MOVV $119, R2 // sys_thrkill + SYSCALL + RET + +TEXT runtime·raiseproc(SB),NOSPLIT,$0 + MOVV $20, R4 // sys_getpid + SYSCALL + MOVV R2, R4 // arg 1 - pid + MOVW sig+0(FP), R5 // arg 2 - signum + MOVV $122, R2 // sys_kill + SYSCALL + RET + +TEXT runtime·mmap(SB),NOSPLIT,$0 + MOVV addr+0(FP), R4 // arg 1 - addr + MOVV n+8(FP), R5 // arg 2 - len + MOVW prot+16(FP), R6 // arg 3 - prot + MOVW flags+20(FP), R7 // arg 4 - flags + MOVW fd+24(FP), R8 // arg 5 - fd + MOVW $0, R9 // arg 6 - pad + MOVW off+28(FP), R10 // arg 7 - offset + MOVV $197, R2 // sys_mmap + SYSCALL + MOVV $0, R4 + BEQ R7, 3(PC) + MOVV R2, R4 // if error, move to R4 + MOVV $0, R2 + MOVV R2, p+32(FP) + MOVV R4, err+40(FP) + RET + +TEXT runtime·munmap(SB),NOSPLIT,$0 + MOVV addr+0(FP), R4 // arg 1 - addr + MOVV n+8(FP), R5 // arg 2 - len + MOVV $73, R2 // sys_munmap + SYSCALL + BEQ R7, 3(PC) + MOVV $0, R2 // crash on syscall failure + MOVV R2, (R2) + RET + +TEXT runtime·madvise(SB),NOSPLIT,$0 + MOVV addr+0(FP), R4 // arg 1 - addr + MOVV n+8(FP), R5 // arg 2 - len + MOVW flags+16(FP), R6 // arg 2 - flags + MOVV $75, R2 // sys_madvise + SYSCALL + BEQ R7, 2(PC) + MOVW $-1, R2 + MOVW R2, ret+24(FP) + RET + +TEXT runtime·setitimer(SB),NOSPLIT,$0 + MOVW mode+0(FP), R4 // arg 1 - mode + MOVV new+8(FP), R5 // arg 2 - new value + MOVV old+16(FP), R6 // arg 3 - old value + MOVV $69, R2 // sys_setitimer + SYSCALL + RET + +// func walltime1() (sec int64, nsec int32) +TEXT runtime·walltime1(SB), NOSPLIT, $32 + MOVW CLOCK_REALTIME, R4 // arg 1 - clock_id + MOVV $8(R29), R5 // arg 2 - tp + MOVV $87, R2 // sys_clock_gettime + SYSCALL + + MOVV 8(R29), R4 // sec + MOVV 16(R29), R5 // nsec + MOVV R4, sec+0(FP) + MOVW R5, nsec+8(FP) + + RET + +// int64 nanotime1(void) so really +// void nanotime1(int64 *nsec) +TEXT runtime·nanotime1(SB),NOSPLIT,$32 + MOVW CLOCK_MONOTONIC, R4 // arg 1 - clock_id + MOVV $8(R29), R5 // arg 2 - tp + MOVV $87, R2 // sys_clock_gettime + SYSCALL + + MOVV 8(R29), R3 // sec + MOVV 16(R29), R5 // nsec + + MOVV $1000000000, R4 + MULVU R4, R3 + MOVV LO, R3 + ADDVU R5, R3 + MOVV R3, ret+0(FP) + RET + +TEXT runtime·sigaction(SB),NOSPLIT,$0 + MOVW sig+0(FP), R4 // arg 1 - signum + MOVV new+8(FP), R5 // arg 2 - new sigaction + MOVV old+16(FP), R6 // arg 3 - old sigaction + MOVV $46, R2 // sys_sigaction + SYSCALL + BEQ R7, 3(PC) + MOVV $3, R2 // crash on syscall failure + MOVV R2, (R2) + RET + +TEXT runtime·obsdsigprocmask(SB),NOSPLIT,$0 + MOVW how+0(FP), R4 // arg 1 - mode + MOVW new+4(FP), R5 // arg 2 - new + MOVV $48, R2 // sys_sigprocmask + SYSCALL + BEQ R7, 3(PC) + MOVV $3, R2 // crash on syscall failure + MOVV R2, (R2) + MOVW R2, ret+8(FP) + RET + +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), R7 + CALL (R7) // Alignment for ELF ABI? + RET + +TEXT runtime·sigtramp(SB),NOSPLIT,$192 + // initialize REGSB = PC&0xffffffff00000000 + BGEZAL R0, 1(PC) + SRLV $32, R31, RSB + SLLV $32, RSB + + // this might be called in external code context, + // where g is not set. + MOVB runtime·iscgo(SB), R1 + BEQ R1, 2(PC) + JAL runtime·load_g(SB) + + MOVW R4, 8(R29) + MOVV R5, 16(R29) + MOVV R6, 24(R29) + MOVV $runtime·sigtrampgo(SB), R1 + JAL (R1) + RET + +// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void)); +TEXT runtime·tfork(SB),NOSPLIT,$0 + + // Copy mp, gp and fn off parent stack for use by child. + MOVV mm+16(FP), R16 + MOVV gg+24(FP), R17 + MOVV fn+32(FP), R18 + + MOVV param+0(FP), R4 // arg 1 - param + MOVV psize+8(FP), R5 // arg 2 - psize + MOVV $8, R2 // sys___tfork + SYSCALL + + // Return if syscall failed. + BEQ R7, 4(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+40(FP) + RET + + // In parent, return. + BEQ R2, 3(PC) + MOVW R2, ret+40(FP) + RET + + // Initialise m, g. + MOVV R17, g + MOVV R16, g_m(g) + + // Call fn. + CALL (R18) + + // fn should never return. + MOVV $2, R8 // crash if reached + MOVV R8, (R8) + RET + +TEXT runtime·sigaltstack(SB),NOSPLIT,$0 + MOVV new+0(FP), R4 // arg 1 - new sigaltstack + MOVV old+8(FP), R5 // arg 2 - old sigaltstack + MOVV $288, R2 // sys_sigaltstack + SYSCALL + BEQ R7, 3(PC) + MOVV $0, R8 // crash on syscall failure + MOVV R8, (R8) + RET + +TEXT runtime·osyield(SB),NOSPLIT,$0 + MOVV $298, R2 // sys_sched_yield + SYSCALL + RET + +TEXT runtime·thrsleep(SB),NOSPLIT,$0 + MOVV ident+0(FP), R4 // arg 1 - ident + MOVW clock_id+8(FP), R5 // arg 2 - clock_id + MOVV tsp+16(FP), R6 // arg 3 - tsp + MOVV lock+24(FP), R7 // arg 4 - lock + MOVV abort+32(FP), R8 // arg 5 - abort + MOVV $94, R2 // sys___thrsleep + SYSCALL + MOVW R2, ret+40(FP) + RET + +TEXT runtime·thrwakeup(SB),NOSPLIT,$0 + MOVV ident+0(FP), R4 // arg 1 - ident + MOVW n+8(FP), R5 // arg 2 - n + MOVV $301, R2 // sys___thrwakeup + SYSCALL + MOVW R2, ret+16(FP) + RET + +TEXT runtime·sysctl(SB),NOSPLIT,$0 + MOVV mib+0(FP), R4 // arg 1 - mib + MOVW miblen+8(FP), R5 // arg 2 - miblen + MOVV out+16(FP), R6 // arg 3 - out + MOVV size+24(FP), R7 // arg 4 - size + MOVV dst+32(FP), R8 // arg 5 - dest + MOVV ndst+40(FP), R9 // arg 6 - newlen + MOVV $202, R2 // sys___sysctl + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+48(FP) + RET + +// int32 runtime·kqueue(void); +TEXT runtime·kqueue(SB),NOSPLIT,$0 + MOVV $269, R2 // sys_kqueue + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+0(FP) + RET + +// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout); +TEXT runtime·kevent(SB),NOSPLIT,$0 + MOVW kq+0(FP), R4 // arg 1 - kq + MOVV ch+8(FP), R5 // arg 2 - changelist + MOVW nch+16(FP), R6 // arg 3 - nchanges + MOVV ev+24(FP), R7 // arg 4 - eventlist + MOVW nev+32(FP), R8 // arg 5 - nevents + MOVV ts+40(FP), R9 // arg 6 - timeout + MOVV $72, R2 // sys_kevent + SYSCALL + BEQ R7, 2(PC) + SUBVU R2, R0, R2 // caller expects negative errno + MOVW R2, ret+48(FP) + RET + +// func closeonexec(fd int32) +TEXT runtime·closeonexec(SB),NOSPLIT,$0 + MOVW fd+0(FP), R4 // arg 1 - fd + MOVV $2, R5 // arg 2 - cmd (F_SETFD) + MOVV $1, R6 // arg 3 - arg (FD_CLOEXEC) + MOVV $92, R2 // sys_fcntl + SYSCALL + RET + +// func runtime·setNonblock(int32 fd) +TEXT runtime·setNonblock(SB),NOSPLIT|NOFRAME,$0-4 + MOVW fd+0(FP), R4 // arg 1 - fd + MOVV $3, R5 // arg 2 - cmd (F_GETFL) + MOVV $0, R6 // arg 3 + MOVV $92, R2 // sys_fcntl + SYSCALL + MOVV $4, R6 // O_NONBLOCK + OR R2, R6 // arg 3 - flags + MOVW fd+0(FP), R4 // arg 1 - fd + MOVV $4, R5 // arg 2 - cmd (F_SETFL) + MOVV $92, R2 // sys_fcntl + SYSCALL + RET -- 2.48.1