From abac4de4fd1aa04b8b8df03236da4ddd0e5dfa3c Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Wed, 27 Jan 2016 16:18:34 +0000 Subject: [PATCH] sync/atomic: new file for plan9_arm support Atomic load/store/add/swap routines, as for other ARM platforms, but with DMB inserted for load/store (assuming that "atomic" also implies acquire/release memory ordering). Change-Id: I70a283d8f0ae61a66432998ce59eac76fd940c67 --- diff --git a/src/sync/atomic/asm_plan9_arm.s b/src/sync/atomic/asm_plan9_arm.s new file mode 100644 index 0000000..5108fc6 --- /dev/null +++ b/src/sync/atomic/asm_plan9_arm.s @@ -0,0 +1,108 @@ +// Copyright 2012 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" + +#define DMB_ISH_7 \ + MOVB runtime·goarm(SB), R11; \ + CMP $7, R11; \ + BLT 2(PC); \ + WORD $0xf57ff05b // dmb ish + +// Plan9/ARM atomic operations. +// TODO(minux): this only supports ARMv6K or higher. + +TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0 + B ·CompareAndSwapUint32(SB) + +TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0 + B ·armCompareAndSwapUint32(SB) + +TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0 + B ·CompareAndSwapUint32(SB) + +TEXT ·AddInt32(SB),NOSPLIT,$0 + B ·AddUint32(SB) + +TEXT ·AddUint32(SB),NOSPLIT,$0 + B ·armAddUint32(SB) + +TEXT ·AddUintptr(SB),NOSPLIT,$0 + B ·AddUint32(SB) + +TEXT ·SwapInt32(SB),NOSPLIT,$0 + B ·SwapUint32(SB) + +TEXT ·SwapUint32(SB),NOSPLIT,$0 + B ·armSwapUint32(SB) + +TEXT ·SwapUintptr(SB),NOSPLIT,$0 + B ·SwapUint32(SB) + +TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0 + B ·CompareAndSwapUint64(SB) + +TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$-4 + B ·armCompareAndSwapUint64(SB) + +TEXT ·AddInt64(SB),NOSPLIT,$0 + B ·addUint64(SB) + +TEXT ·AddUint64(SB),NOSPLIT,$0 + B ·addUint64(SB) + +TEXT ·SwapInt64(SB),NOSPLIT,$0 + B ·swapUint64(SB) + +TEXT ·SwapUint64(SB),NOSPLIT,$0 + B ·swapUint64(SB) + +TEXT ·LoadInt32(SB),NOSPLIT,$0 + B ·LoadUint32(SB) + +TEXT ·LoadUint32(SB),NOSPLIT,$0-8 + MOVW addr+0(FP), R1 +load32loop: + LDREX (R1), R2 // loads R2 + STREX R2, (R1), R0 // stores R2 + CMP $0, R0 + BNE load32loop + MOVW R2, val+4(FP) + DMB_ISH_7 + RET + +TEXT ·LoadInt64(SB),NOSPLIT,$0 + B ·loadUint64(SB) + +TEXT ·LoadUint64(SB),NOSPLIT,$0 + B ·loadUint64(SB) + +TEXT ·LoadUintptr(SB),NOSPLIT,$0 + B ·LoadUint32(SB) + +TEXT ·LoadPointer(SB),NOSPLIT,$0 + B ·LoadUint32(SB) + +TEXT ·StoreInt32(SB),NOSPLIT,$0 + B ·StoreUint32(SB) + +TEXT ·StoreUint32(SB),NOSPLIT,$0-8 + MOVW addr+0(FP), R1 + MOVW val+4(FP), R2 + DMB_ISH_7 +storeloop: + LDREX (R1), R4 // loads R4 + STREX R2, (R1), R0 // stores R2 + CMP $0, R0 + BNE storeloop + RET + +TEXT ·StoreInt64(SB),NOSPLIT,$0 + B ·storeUint64(SB) + +TEXT ·StoreUint64(SB),NOSPLIT,$0 + B ·storeUint64(SB) + +TEXT ·StoreUintptr(SB),NOSPLIT,$0 + B ·StoreUint32(SB) From 29d742aa444207ce3f2fc952ef07b6f04e49f670 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Wed, 27 Jan 2016 16:31:24 +0000 Subject: [PATCH] runtime: new files for plan9_arm support Implementation more or less follows plan9_386 version. Change-Id: I2e921558b5816502e8aafe330530c5a48a6c7537 --- diff --git a/src/runtime/defs_plan9_arm.go b/src/runtime/defs_plan9_arm.go new file mode 100644 index 0000000..f92b0df --- /dev/null +++ b/src/runtime/defs_plan9_arm.go @@ -0,0 +1,59 @@ +package runtime + +const _PAGESIZE = 0x1000 + +type ureg struct { + r0 uint32 /* general registers */ + r1 uint32 /* ... */ + r2 uint32 /* ... */ + r3 uint32 /* ... */ + r4 uint32 /* ... */ + r5 uint32 /* ... */ + r6 uint32 /* ... */ + r7 uint32 /* ... */ + r8 uint32 /* ... */ + r9 uint32 /* ... */ + r10 uint32 /* ... */ + r11 uint32 /* ... */ + r12 uint32 /* ... */ + sp uint32 + link uint32 /* ... */ + trap uint32 /* trap type */ + psr uint32 + pc uint32 /* interrupted addr */ +} + +type sigctxt struct { + u *ureg +} + +func (c *sigctxt) pc() uintptr { return uintptr(c.u.pc) } +func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) } +func (c *sigctxt) lr() uintptr { return uintptr(c.u.link) } + +func (c *sigctxt) setpc(x uintptr) { c.u.pc = uint32(x) } +func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint32(x) } +func (c *sigctxt) setlr(x uintptr) { c.u.link = uint32(x) } +func (c *sigctxt) savelr(x uintptr) { c.u.r0 = uint32(x) } + +func dumpregs(u *ureg) { + print("r0 ", hex(u.r0), "\n") + print("r1 ", hex(u.r1), "\n") + print("r2 ", hex(u.r2), "\n") + print("r3 ", hex(u.r3), "\n") + print("r4 ", hex(u.r4), "\n") + print("r5 ", hex(u.r5), "\n") + print("r6 ", hex(u.r6), "\n") + print("r7 ", hex(u.r7), "\n") + print("r8 ", hex(u.r8), "\n") + print("r9 ", hex(u.r9), "\n") + print("r10 ", hex(u.r10), "\n") + print("r11 ", hex(u.r11), "\n") + print("r12 ", hex(u.r12), "\n") + print("sp ", hex(u.sp), "\n") + print("link ", hex(u.link), "\n") + print("pc ", hex(u.pc), "\n") + print("psr ", hex(u.psr), "\n") +} + +func sigpanictramp() diff --git a/src/runtime/internal/atomic/sys_plan9_arm.s b/src/runtime/internal/atomic/sys_plan9_arm.s new file mode 100644 index 0000000..01b7aef --- /dev/null +++ b/src/runtime/internal/atomic/sys_plan9_arm.s @@ -0,0 +1,11 @@ +// 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" + +TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0 + B runtime∕internal∕atomic·armcas(SB) + +TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0 + B runtime∕internal∕atomic·Cas(SB) diff --git a/src/runtime/os_plan9_arm.go b/src/runtime/os_plan9_arm.go new file mode 100644 index 0000000..d3336c0 --- /dev/null +++ b/src/runtime/os_plan9_arm.go @@ -0,0 +1,17 @@ +// Copyright 2014 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 + +func checkgoarm() { + return // TODO(minux) +} + +//go:nosplit +func cputicks() int64 { + // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1(). + // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. + // TODO: need more entropy to better seed fastrand1. + return nanotime() +} diff --git a/src/runtime/rt0_plan9_arm.s b/src/runtime/rt0_plan9_arm.s new file mode 100644 index 0000000..ba1338d --- /dev/null +++ b/src/runtime/rt0_plan9_arm.s @@ -0,0 +1,17 @@ +// Copyright 2009 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" + +//in plan 9 argc is at top of stack followed by ptrs to arguments + +TEXT _rt0_arm_plan9(SB),NOSPLIT,$-4 + MOVW R0, _tos(SB) + MOVW 0(R13), R0 + MOVW $4(R13), R1 + MOVW.W R1, -4(R13) + MOVW.W R0, -4(R13) + B runtime·rt0_go(SB) + +GLOBL _tos(SB), NOPTR, $4 diff --git a/src/runtime/sys_plan9_arm.s b/src/runtime/sys_plan9_arm.s new file mode 100644 index 0000000..78afb79 --- /dev/null +++ b/src/runtime/sys_plan9_arm.s @@ -0,0 +1,315 @@ +// Copyright 2010 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 "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +// from ../syscall/zsysnum_plan9.go + +#define SYS_SYSR1 0 +#define SYS_BIND 2 +#define SYS_CHDIR 3 +#define SYS_CLOSE 4 +#define SYS_DUP 5 +#define SYS_ALARM 6 +#define SYS_EXEC 7 +#define SYS_EXITS 8 +#define SYS_FAUTH 10 +#define SYS_SEGBRK 12 +#define SYS_OPEN 14 +#define SYS_OSEEK 16 +#define SYS_SLEEP 17 +#define SYS_RFORK 19 +#define SYS_PIPE 21 +#define SYS_CREATE 22 +#define SYS_FD2PATH 23 +#define SYS_BRK_ 24 +#define SYS_REMOVE 25 +#define SYS_NOTIFY 28 +#define SYS_NOTED 29 +#define SYS_SEGATTACH 30 +#define SYS_SEGDETACH 31 +#define SYS_SEGFREE 32 +#define SYS_SEGFLUSH 33 +#define SYS_RENDEZVOUS 34 +#define SYS_UNMOUNT 35 +#define SYS_SEMACQUIRE 37 +#define SYS_SEMRELEASE 38 +#define SYS_SEEK 39 +#define SYS_FVERSION 40 +#define SYS_ERRSTR 41 +#define SYS_STAT 42 +#define SYS_FSTAT 43 +#define SYS_WSTAT 44 +#define SYS_FWSTAT 45 +#define SYS_MOUNT 46 +#define SYS_AWAIT 47 +#define SYS_PREAD 50 +#define SYS_PWRITE 51 +#define SYS_TSEMACQUIRE 52 +#define SYS_NSEC 53 + +//func open(name *byte, mode, perm int32) int32 +TEXT runtime·open(SB),NOSPLIT,$0-16 + MOVW $SYS_OPEN, R0 + SWI 0 + MOVW R0, ret+12(FP) + RET + +//func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 +TEXT runtime·pread(SB),NOSPLIT,$0-24 + MOVW $SYS_PREAD, R0 + SWI 0 + MOVW R0, ret+20(FP) + RET + +//func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 +TEXT runtime·pwrite(SB),NOSPLIT,$0-24 + MOVW $SYS_PWRITE, R0 + SWI 0 + MOVW R0, ret+20(FP) + RET + +//func seek(fd int32, offset int64, whence int32) int64 +TEXT runtime·seek(SB),NOSPLIT,$4-24 + MOVW $ret_lo+16(FP), R0 + MOVW R0, newoff-4(SP) + MOVW $SYS_SEEK, R0 + SWI 0 + CMP $-1, R0 + MOVW.EQ R0, ret_lo+16(FP) + MOVW.EQ R0, ret_hi+20(FP) + RET + +//func closefd(fd int32) int32 +TEXT runtime·closefd(SB),NOSPLIT,$0-8 + MOVW $SYS_CLOSE, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func exits(msg *byte) +TEXT runtime·exits(SB),NOSPLIT,$0-4 + MOVW $SYS_EXITS, R0 + SWI 0 + RET + +//func brk_(addr unsafe.Pointer) int32 +TEXT runtime·brk_(SB),NOSPLIT,$0-8 + MOVW $SYS_BRK_, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func sleep(ms int32) int32 +TEXT runtime·sleep(SB),NOSPLIT,$0-8 + MOVW $SYS_SLEEP, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func plan9_semacquire(addr *uint32, block int32) int32 +TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0-12 + MOVW $SYS_SEMACQUIRE, R0 + SWI 0 + MOVW R0, ret+8(FP) + RET + +//func plan9_tsemacquire(addr *uint32, ms int32) int32 +TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-12 + MOVW $SYS_TSEMACQUIRE, R0 + SWI 0 + MOVW R0, ret+8(FP) + RET + +//func nsec(*int64) int64 +TEXT runtime·nsec(SB),NOSPLIT,$-4-12 + MOVW $SYS_NSEC, R0 + SWI 0 + MOVW unnamed+0(FP), R1 + MOVW 0(R1), R0 + MOVW R0, ret_lo+4(FP) + MOVW 4(R1), R0 + MOVW R0, ret_hi+8(FP) + RET + +// time.now() (sec int64, nsec int32) +TEXT time·now(SB),NOSPLIT,$12-12 + // use nsec system call to get current time in nanoseconds + MOVW $sysnsec_lo-8(SP), R0 // destination addr + MOVW R0,res-12(SP) + MOVW $SYS_NSEC, R0 + SWI 0 + MOVW sysnsec_lo-8(SP), R1 // R1:R2 = nsec + MOVW sysnsec_hi-4(SP), R2 + + // multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61) + // to get seconds (96 bit scaled result) + MOVW $0x89705f41, R3 // 2**61 * 10**-9 + MULLU R1,R3,(R6,R5) // R5:R6:R7 = R1:R2 * R3 + MOVW $0,R7 + MULALU R2,R3,(R7,R6) + + // unscale by discarding low 32 bits, shifting the rest by 29 + MOVW R6>>29,R6 // R6:R7 = (R5:R6:R7 >> 61) + ORR R7<<3,R6 + MOVW R7>>29,R7 + + // subtract (10**9 * sec) from nsec to get nanosecond remainder + MOVW $1000000000, R5 // 10**9 + MULLU R6,R5,(R9,R8) // R8:R9 = R6:R7 * R5 + MULA R7,R5,R9,R9 + SUB.S R8,R1 // R1:R2 -= R8:R9 + SBC R9,R2 + + // because reciprocal was a truncated repeating fraction, quotient + // may be slightly too small -- adjust to make remainder < 10**9 + CMP R5,R1 // if remainder > 10**9 + SUB.HS R5,R1 // remainder -= 10**9 + ADD.HS $1,R6 // sec += 1 + + MOVW R6,sec_lo+0(FP) + MOVW R7,sec_hi+4(FP) + MOVW R1,nsec+8(FP) + RET + +//func notify(fn unsafe.Pointer) int32 +TEXT runtime·notify(SB),NOSPLIT,$0-8 + MOVW $SYS_NOTIFY, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func noted(mode int32) int32 +TEXT runtime·noted(SB),NOSPLIT,$0-8 + MOVW $SYS_NOTED, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func plan9_semrelease(addr *uint32, count int32) int32 +TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0-12 + MOVW $SYS_SEMRELEASE, R0 + SWI 0 + MOVW R0, ret+8(FP) + RET + +//func rfork(flags int32) int32 +TEXT runtime·rfork(SB),NOSPLIT,$0-8 + MOVW $SYS_RFORK, R0 + SWI 0 + MOVW R0, ret+4(FP) + RET + +//func tstart_plan9(newm *m) +TEXT runtime·tstart_plan9(SB),NOSPLIT,$0-4 + MOVW newm+0(FP), R1 + MOVW m_g0(R1), g + + // Layout new m scheduler stack on os stack. + MOVW R13, R0 + MOVW R0, g_stack+stack_hi(g) + SUB $(64*1024), R0 + MOVW R0, (g_stack+stack_lo)(g) + MOVW R0, g_stackguard0(g) + MOVW R0, g_stackguard1(g) + + // Initialize procid from TOS struct. + MOVW _tos(SB), R0 + MOVW 48(R0), R0 + MOVW R0, m_procid(R1) // save pid as m->procid + + BL runtime·mstart(SB) + + MOVW $0x1234, R0 + MOVW R0, 0(R0) // not reached + RET + +//func sigtramp(ureg, msg unsafe.Pointer) +TEXT runtime·sigtramp(SB),NOSPLIT,$0-8 + // check that g and m exist + CMP $0, g + BEQ 4(PC) + MOVW g_m(g), R0 + CMP $0, R0 + BNE 2(PC) + BL runtime·badsignal2(SB) // will exit + + // save args + MOVW ureg+0(FP), R1 + MOVW msg+4(FP), R2 + + // change stack + MOVW m_gsignal(R0), R3 + MOVW (g_stack+stack_hi)(R3), R13 + + // make room for args, retval and g + SUB $24, R13 + + // save g + MOVW g, R3 + MOVW R3, 20(R13) + + // g = m->gsignal + MOVW m_gsignal(R0), g + + // load args and call sighandler + ADD $4,R13,R5 + MOVM.IA [R1-R3], (R5) + BL runtime·sighandler(SB) + MOVW 16(R13), R0 // retval + + // restore g + MOVW 20(R13), g + + // call noted(R0) + MOVW R0, 4(R13) + BL runtime·noted(SB) + RET + +//func sigpanictramp() +TEXT runtime·sigpanictramp(SB),NOSPLIT,$0-0 + MOVW.W R0, -4(R13) + B runtime·sigpanic(SB) + +//func setfpmasks() +// Only used by the 64-bit runtime. +TEXT runtime·setfpmasks(SB),NOSPLIT,$0 + RET + +#define ERRMAX 128 /* from os_plan9.h */ + +// func errstr() string +// Only used by package syscall. +// Grab error string due to a syscall made +// in entersyscall mode, without going +// through the allocator (issue 4994). +// See ../syscall/asm_plan9_arm.s:/·Syscall/ +TEXT runtime·errstr(SB),NOSPLIT,$0-8 + MOVW g_m(g), R0 + MOVW (m_mOS+mOS_errstr)(R0), R1 + MOVW R1, ret_base+0(FP) + MOVW $ERRMAX, R2 + MOVW R2, ret_len+4(FP) + MOVW $SYS_ERRSTR, R0 + SWI 0 + MOVW R1, R2 + MOVBU 0(R2), R0 + CMP $0, R0 + BEQ 3(PC) + ADD $1, R2 + B -4(PC) + SUB R1, R2 + MOVW R2, ret_len+4(FP) + RET + +TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0 + B runtime·armPublicationBarrier(SB) + +// never called (cgo not supported) +TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 + MOVW $0, R0 + MOVW R0, (R0) + RET From 1d10198e815f3df5443e765572edcd4e293eb848 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Wed, 27 Jan 2016 16:36:31 +0000 Subject: [PATCH] syscall: new files for plan_arm support Implementation closely follows plan9_386 version. Change-Id: Ifb76e001fb5664e6a23541cf4768d7f11b2be68b --- diff --git a/src/syscall/asm_plan9_arm.s b/src/syscall/asm_plan9_arm.s new file mode 100644 index 0000000..dd05844 --- /dev/null +++ b/src/syscall/asm_plan9_arm.s @@ -0,0 +1,97 @@ +// Copyright 2009 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" + +#define SYS_SEEK 39 /* from zsysnum_plan9.go */ + +// System call support for plan9 on arm + +TEXT sysresult<>(SB),NOSPLIT,$12 + MOVW $runtime·emptystring+0(SB), R2 + CMP $-1, R0 + B.NE ok + MOVW R1, save-4(SP) + BL runtime·errstr(SB) + MOVW save-4(SP), R1 + MOVW $err-12(SP), R2 +ok: + MOVM.IA (R2), [R3-R4] + MOVM.IA [R3-R4], (R1) + RET + +//func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString) +TEXT ·Syscall(SB),NOSPLIT,$0 + BL runtime·entersyscall(SB) + MOVW trap+0(FP), R0 // syscall num + MOVM.IA.W (R13),[R1-R2] // pop LR and caller's LR + SWI 0 + MOVM.DB.W [R1-R2],(R13) // push LR and caller's LR + MOVW $0, R2 + MOVW $r1+16(FP), R1 + MOVM.IA.W [R0,R2], (R1) + BL sysresult<>(SB) + BL runtime·exitsyscall(SB) + RET + +//func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString) +// Actually Syscall5 but the rest of the code expects it to be named Syscall6. +TEXT ·Syscall6(SB),NOSPLIT,$0 + BL runtime·entersyscall(SB) + MOVW trap+0(FP), R0 // syscall num + MOVM.IA.W (R13),[R1-R2] // pop LR and caller's LR + SWI 0 + MOVM.DB.W [R1-R2],(R13) // push LR and caller's LR + MOVW $0, R1 + MOVW $r1+28(FP), R1 + MOVM.IA.W [R0,R2], (R1) + BL sysresult<>(SB) + BL runtime·exitsyscall(SB) + RET + +//func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) +TEXT ·RawSyscall(SB),NOSPLIT,$0 + MOVW trap+0(FP), R0 // syscall num + MOVM.IA.W (R13),[R1] // pop caller's LR + SWI 0 + MOVM.DB.W [R1],(R13) // push caller's LR + MOVW R0, r1+16(FP) + MOVW R0, r2+20(FP) + MOVW R0, err+24(FP) + RET + +//func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) +// Actually RawSyscall5 but the rest of the code expects it to be named RawSyscall6. +TEXT ·RawSyscall6(SB),NOSPLIT,$0 + MOVW trap+0(FP), R0 // syscall num + MOVM.IA.W (R13),[R1] // pop caller's LR + SWI 0 + MOVM.DB.W [R1],(R13) // push caller's LR + MOVW R0, r1+28(FP) + MOVW R0, r2+32(FP) + MOVW R0, err+36(FP) + RET + +//func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string) +TEXT ·seek(SB),NOSPLIT,$0 + MOVW $newoffset_lo+20(FP), R5 + MOVW R5, placeholder+0(FP) //placeholder = dest for return value + MOVW $SYS_SEEK, R0 // syscall num + MOVM.IA.W (R13),[R1] // pop LR + SWI 0 + MOVM.DB.W [R1],(R13) // push LR + CMP $-1, R0 + MOVW.EQ R0, 0(R5) + MOVW.EQ R0, 4(R5) + MOVW $err+28(FP), R1 + BL sysresult<>(SB) + RET + +//func exit(code int) +// Import runtime·exit for cleanly exiting. +TEXT ·exit(SB),NOSPLIT,$4 + MOVW code+0(FP), R0 + MOVW R0, e-4(SP) + BL runtime·exit(SB) + RET diff --git a/src/syscall/zsyscall_plan9_arm.go b/src/syscall/zsyscall_plan9_arm.go new file mode 100644 index 0000000..d54aeff --- /dev/null +++ b/src/syscall/zsyscall_plan9_arm.go @@ -0,0 +1,294 @@ +// mksyscall.pl -l32 -plan9 syscall_plan9.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +// +build arm,plan9 + +package syscall + +import "unsafe" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fd2path(fd int, buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func await(s []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(s) > 0 { + _p0 = unsafe.Pointer(&s[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func open(path string, mode int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + use(unsafe.Pointer(_p0)) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func create(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + use(unsafe.Pointer(_p0)) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func remove(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) + use(unsafe.Pointer(_p0)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func stat(path string, edir []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + use(unsafe.Pointer(_p0)) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(name string, old string, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(old) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount(fd int, afd int, old string, flag int, aname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(old) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(aname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) + use(unsafe.Pointer(_p0)) + use(unsafe.Pointer(_p1)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wstat(path string, edir []byte) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + use(unsafe.Pointer(_p0)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + use(unsafe.Pointer(_p0)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(oldfd int, newfd int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, edir []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fwstat(fd int, edir []byte) (err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} From ed427f613b9abdcf41358c1b58e75a98cae70b42 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Wed, 27 Jan 2016 18:43:36 +0000 Subject: [PATCH] runtime: signal handling support for plan9_arm Plan 9 trap/signal handling differs on ARM from other architectures because ARM has a link register. Also trap message syntax varies between different architectures (historical accident?). Change-Id: Ib6485f82857a2f9a0d6b2c375cf0aaa230b83656 --- diff --git a/src/runtime/defs_plan9_386.go b/src/runtime/defs_plan9_386.go index 3574cb6..54ace48 100644 --- a/src/runtime/defs_plan9_386.go +++ b/src/runtime/defs_plan9_386.go @@ -30,9 +30,13 @@ func (c *sigctxt) pc() uintptr { return uintptr(c.u.pc) } func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) } +func (c *sigctxt) lr() uintptr { return uintptr(0) } func (c *sigctxt) setpc(x uintptr) { c.u.pc = uint32(x) } func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint32(x) } +func (c *sigctxt) setlr(x uintptr) {} + +func (c *sigctxt) savelr(x uintptr) {} func dumpregs(u *ureg) { print("ax ", hex(u.ax), "\n") @@ -49,3 +53,5 @@ print("fs ", hex(u.fs), "\n") print("gs ", hex(u.gs), "\n") } + +func sigpanictramp() {} diff --git a/src/runtime/defs_plan9_amd64.go b/src/runtime/defs_plan9_amd64.go index 54b4d39..1633ec1 100644 --- a/src/runtime/defs_plan9_amd64.go +++ b/src/runtime/defs_plan9_amd64.go @@ -39,9 +39,13 @@ func (c *sigctxt) pc() uintptr { return uintptr(c.u.ip) } func (c *sigctxt) sp() uintptr { return uintptr(c.u.sp) } +func (c *sigctxt) lr() uintptr { return uintptr(0) } func (c *sigctxt) setpc(x uintptr) { c.u.ip = uint64(x) } func (c *sigctxt) setsp(x uintptr) { c.u.sp = uint64(x) } +func (c *sigctxt) setlr(x uintptr) {} + +func (c *sigctxt) savelr(x uintptr) {} func dumpregs(u *ureg) { print("ax ", hex(u.ax), "\n") @@ -66,3 +70,5 @@ print("fs ", hex(u.fs), "\n") print("gs ", hex(u.gs), "\n") } + +func sigpanictramp() {} diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go index edd66c5..2f358fc 100644 --- a/src/runtime/os3_plan9.go +++ b/src/runtime/os3_plan9.go @@ -66,22 +66,37 @@ pc = 0 } - // Only push sigpanic if PC != 0. - // + // IF LR exists, it must be saved to the stack before + // entry to sigpanic so that panics in leaf + // functions are correctly handled. This smashes + // the stack frame but we're not going back there + // anyway. + if usesLR { + c.savelr(c.lr()) + } + // If PC == 0, probably panicked because of a call to a nil func. - // Not pushing that onto SP will make the trace look like a call + // Not faking that as the return address will make the trace look like a call // to sigpanic instead. (Otherwise the trace will end at // sigpanic and we won't get to see who faulted). if pc != 0 { - if sys.RegSize > sys.PtrSize { + if usesLR { + c.setlr(pc) + } else { + if sys.RegSize > sys.PtrSize { + sp -= sys.PtrSize + *(*uintptr)(unsafe.Pointer(sp)) = 0 + } sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = 0 + *(*uintptr)(unsafe.Pointer(sp)) = pc + c.setsp(sp) } - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = pc - c.setsp(sp) } - c.setpc(funcPC(sigpanic)) + if usesLR { + c.setpc(funcPC(sigpanictramp)) + } else { + c.setpc(funcPC(sigpanic)) + } return _NCONT } if flags&_SigNotify != 0 { @@ -105,7 +120,7 @@ level, _, docrash = gotraceback() if level > 0 { goroutineheader(gp) - tracebacktrap(c.pc(), c.sp(), 0, gp) + tracebacktrap(c.pc(), c.sp(), c.lr(), gp) tracebackothers(gp) print("\n") dumpregs(_ureg) diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 6e6a55e..7ce814b 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -78,7 +78,15 @@ note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig))) switch g.sig { case _SIGRFAULT, _SIGWFAULT: - addr := note[index(note, "addr=")+5:] + i := index(note, "addr=") + if i >= 0 { + i += 5 + } else if i = index(note, "va="); i >= 0 { + i += 3 + } else { + panicmem() + } + addr := note[i:] g.sigcode1 = uintptr(atolwhex(addr)) if g.sigcode1 < 0x1000 || g.paniconfault { panicmem() diff --git a/src/runtime/signal_plan9.go b/src/runtime/signal_plan9.go index 19247f2..d3894c8 100644 --- a/src/runtime/signal_plan9.go +++ b/src/runtime/signal_plan9.go @@ -22,8 +22,8 @@ {_SigThrow, "sys: trap: invalid opcode"}, // We can recover from some memory errors in runtime·sigpanic. - {_SigPanic, "sys: trap: fault read addr"}, // SIGRFAULT - {_SigPanic, "sys: trap: fault write addr"}, // SIGWFAULT + {_SigPanic, "sys: trap: fault read"}, // SIGRFAULT + {_SigPanic, "sys: trap: fault write"}, // SIGWFAULT // We can also recover from math errors. {_SigPanic, "sys: trap: divide error"}, // SIGINTDIV