mirror of https://github.com/golang/go.git
runtime: add support for linux/arm64
Change-Id: Ibda6a5bedaff57fd161d63fc04ad260931d34413 Reviewed-on: https://go-review.googlesource.com/7142 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
5a0c322bce
commit
846ee0465b
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2011 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
|
||||
|
||||
const (
|
||||
thechar = '7'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 32
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = 4096
|
||||
_PCQuantum = 4
|
||||
_Int64Align = 8
|
||||
hugePageSize = 0
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// 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
|
||||
|
||||
type uintreg uint64
|
||||
type intptr int64 // TODO(rsc): remove
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,61 @@
|
|||
// 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.
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//go:noescape
|
||||
func xadd(ptr *uint32, delta int32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xadd64(ptr *uint64, delta int64) uint64
|
||||
|
||||
//go:noescape
|
||||
func xchg(ptr *uint32, new uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xchg64(ptr *uint64, new uint64) uint64
|
||||
|
||||
// NO go:noescape annotation; see atomic_pointer.go.
|
||||
func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func xchguintptr(ptr *uintptr, new uintptr) uintptr
|
||||
|
||||
//go:noescape
|
||||
func atomicload(ptr *uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func atomicload64(ptr *uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:nosplit
|
||||
func atomicor8(addr *uint8, v uint8) {
|
||||
// TODO(dfc) implement this in asm.
|
||||
// Align down to 4 bytes and use 32-bit CAS.
|
||||
uaddr := uintptr(unsafe.Pointer(addr))
|
||||
addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
|
||||
word := uint32(v) << ((uaddr & 3) * 8) // little endian
|
||||
for {
|
||||
old := *addr32
|
||||
if cas(addr32, old, old|word) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func cas64(ptr *uint64, old, new uint64) bool
|
||||
|
||||
//go:noescape
|
||||
func atomicstore(ptr *uint32, val uint32)
|
||||
|
||||
//go:noescape
|
||||
func atomicstore64(ptr *uint64, val uint64)
|
||||
|
||||
// NO go:noescape annotation; see atomic_pointer.go.
|
||||
func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
// 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// uint32 runtime·atomicload(uint32 volatile* addr)
|
||||
TEXT ·atomicload(SB),NOSPLIT,$-8-12
|
||||
MOVD ptr+0(FP), R0
|
||||
LDARW (R0), R0
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
// uint64 runtime·atomicload64(uint64 volatile* addr)
|
||||
TEXT ·atomicload64(SB),NOSPLIT,$-8-16
|
||||
MOVD ptr+0(FP), R0
|
||||
LDAR (R0), R0
|
||||
MOVD R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
// void *runtime·atomicloadp(void *volatile *addr)
|
||||
TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
|
||||
MOVD ptr+0(FP), R0
|
||||
LDAR (R0), R0
|
||||
MOVD R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
|
||||
B runtime·atomicstore64(SB)
|
||||
|
||||
TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVW val+8(FP), R1
|
||||
STLRW R1, (R0)
|
||||
RET
|
||||
|
||||
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVD val+8(FP), R1
|
||||
STLR R1, (R0)
|
||||
RET
|
||||
|
||||
TEXT runtime·xchg(SB), NOSPLIT, $0-20
|
||||
again:
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVW new+8(FP), R1
|
||||
LDAXRW (R0), R2
|
||||
STLXRW R1, (R0), R3
|
||||
CBNZ R3, again
|
||||
MOVW R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·xchg64(SB), NOSPLIT, $0-24
|
||||
again:
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVD new+8(FP), R1
|
||||
LDAXR (R0), R2
|
||||
STLXR R1, (R0), R3
|
||||
CBNZ R3, again
|
||||
MOVD R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
|
||||
// Atomically:
|
||||
// if(*val == *old){
|
||||
// *val = new;
|
||||
// return 1;
|
||||
// } else {
|
||||
// return 0;
|
||||
// }
|
||||
TEXT runtime·cas64(SB), NOSPLIT, $0-25
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVD old+8(FP), R1
|
||||
MOVD new+16(FP), R2
|
||||
again:
|
||||
LDAXR (R0), R3
|
||||
CMP R1, R3
|
||||
BNE ok
|
||||
STLXR R2, (R0), R3
|
||||
CBNZ R3, again
|
||||
ok:
|
||||
CSET EQ, R0
|
||||
MOVB R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
// uint32 xadd(uint32 volatile *ptr, int32 delta)
|
||||
// Atomically:
|
||||
// *val += delta;
|
||||
// return *val;
|
||||
TEXT runtime·xadd(SB), NOSPLIT, $0-20
|
||||
again:
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVW delta+8(FP), R1
|
||||
LDAXRW (R0), R2
|
||||
ADDW R2, R1, R2
|
||||
STLXRW R2, (R0), R3
|
||||
CBNZ R3, again
|
||||
MOVW R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·xadd64(SB), NOSPLIT, $0-24
|
||||
again:
|
||||
MOVD ptr+0(FP), R0
|
||||
MOVD delta+8(FP), R1
|
||||
LDAXR (R0), R2
|
||||
ADD R2, R1, R2
|
||||
STLXR R2, (R0), R3
|
||||
CBNZ R3, again
|
||||
MOVD R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
|
||||
B runtime·xchg64(SB)
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !arm
|
||||
// +build !arm64
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
#ifdef GOARCH_arm
|
||||
#define JMP B
|
||||
#endif
|
||||
#ifdef GOARCH_arm64
|
||||
#define JMP B
|
||||
#endif
|
||||
#ifdef GOARCH_ppc64
|
||||
#define JMP BR
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
// Created by cgo -cdefs and converted (by hand) to Go
|
||||
// ../cmd/cgo/cgo -cdefs defs_linux.go defs1_linux.go defs2_linux.go
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
_EINTR = 0x4
|
||||
_EAGAIN = 0xb
|
||||
_ENOMEM = 0xc
|
||||
|
||||
_PROT_NONE = 0x0
|
||||
_PROT_READ = 0x1
|
||||
_PROT_WRITE = 0x2
|
||||
_PROT_EXEC = 0x4
|
||||
|
||||
_MAP_ANON = 0x20
|
||||
_MAP_PRIVATE = 0x2
|
||||
_MAP_FIXED = 0x10
|
||||
|
||||
_MADV_DONTNEED = 0x4
|
||||
_MADV_HUGEPAGE = 0xe
|
||||
_MADV_NOHUGEPAGE = 0xf
|
||||
|
||||
_SA_RESTART = 0x10000000
|
||||
_SA_ONSTACK = 0x8000000
|
||||
_SA_RESTORER = 0x0 // Only used on intel
|
||||
_SA_SIGINFO = 0x4
|
||||
|
||||
_SIGHUP = 0x1
|
||||
_SIGINT = 0x2
|
||||
_SIGQUIT = 0x3
|
||||
_SIGILL = 0x4
|
||||
_SIGTRAP = 0x5
|
||||
_SIGABRT = 0x6
|
||||
_SIGBUS = 0x7
|
||||
_SIGFPE = 0x8
|
||||
_SIGKILL = 0x9
|
||||
_SIGUSR1 = 0xa
|
||||
_SIGSEGV = 0xb
|
||||
_SIGUSR2 = 0xc
|
||||
_SIGPIPE = 0xd
|
||||
_SIGALRM = 0xe
|
||||
_SIGSTKFLT = 0x10
|
||||
_SIGCHLD = 0x11
|
||||
_SIGCONT = 0x12
|
||||
_SIGSTOP = 0x13
|
||||
_SIGTSTP = 0x14
|
||||
_SIGTTIN = 0x15
|
||||
_SIGTTOU = 0x16
|
||||
_SIGURG = 0x17
|
||||
_SIGXCPU = 0x18
|
||||
_SIGXFSZ = 0x19
|
||||
_SIGVTALRM = 0x1a
|
||||
_SIGPROF = 0x1b
|
||||
_SIGWINCH = 0x1c
|
||||
_SIGIO = 0x1d
|
||||
_SIGPWR = 0x1e
|
||||
_SIGSYS = 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
|
||||
|
||||
_EPOLLIN = 0x1
|
||||
_EPOLLOUT = 0x4
|
||||
_EPOLLERR = 0x8
|
||||
_EPOLLHUP = 0x10
|
||||
_EPOLLRDHUP = 0x2000
|
||||
_EPOLLET = 0x80000000
|
||||
_EPOLL_CLOEXEC = 0x80000
|
||||
_EPOLL_CTL_ADD = 0x1
|
||||
_EPOLL_CTL_DEL = 0x2
|
||||
_EPOLL_CTL_MOD = 0x3
|
||||
)
|
||||
|
||||
type timespec struct {
|
||||
tv_sec int64
|
||||
tv_nsec int64
|
||||
}
|
||||
|
||||
func (ts *timespec) set_sec(x int64) {
|
||||
ts.tv_sec = x
|
||||
}
|
||||
|
||||
func (ts *timespec) set_nsec(x int32) {
|
||||
ts.tv_nsec = int64(x)
|
||||
}
|
||||
|
||||
type timeval struct {
|
||||
tv_sec int64
|
||||
tv_usec int64
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = int64(x)
|
||||
}
|
||||
|
||||
type sigactiont struct {
|
||||
sa_handler uintptr
|
||||
sa_flags uint64
|
||||
sa_restorer uintptr
|
||||
sa_mask uint64
|
||||
}
|
||||
|
||||
type siginfo struct {
|
||||
si_signo int32
|
||||
si_errno int32
|
||||
si_code int32
|
||||
// below here is a union; si_addr is the only field we use
|
||||
si_addr uint64
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
}
|
||||
|
||||
type epollevent struct {
|
||||
events uint32
|
||||
_pad uint32
|
||||
data [8]byte // to match amd64
|
||||
}
|
||||
|
||||
// Created by cgo -cdefs and then converted to Go by hand
|
||||
// ../cmd/cgo/cgo -cdefs defs_linux.go defs1_linux.go defs2_linux.go
|
||||
|
||||
const (
|
||||
_O_RDONLY = 0x0
|
||||
_O_CLOEXEC = 0x80000
|
||||
)
|
||||
|
||||
type usigset struct {
|
||||
__val [16]uint64
|
||||
}
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_flags int32
|
||||
pad_cgo_0 [4]byte
|
||||
ss_size uintptr
|
||||
}
|
||||
|
||||
type sigcontext struct {
|
||||
fault_address uint64
|
||||
/* AArch64 registers */
|
||||
regs [31]uint64
|
||||
sp uint64
|
||||
pc uint64
|
||||
pstate uint64
|
||||
_pad [8]byte // __attribute__((__aligned__(16)))
|
||||
__reserved [4096]byte
|
||||
}
|
||||
|
||||
type ucontext struct {
|
||||
uc_flags uint64
|
||||
uc_link *ucontext
|
||||
uc_stack sigaltstackt
|
||||
uc_sigmask uint64
|
||||
_pad [(1024 - 64) / 8]byte
|
||||
_pad2 [8]byte // sigcontext must be aligned to 16-byte
|
||||
uc_mcontext sigcontext
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ func infoBigStruct() []byte {
|
|||
typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
|
||||
typePointer, typeDead, // i string
|
||||
}
|
||||
case "amd64", "ppc64", "ppc64le":
|
||||
case "arm64", "amd64", "ppc64", "ppc64le":
|
||||
return []byte{
|
||||
typePointer, // q *int
|
||||
typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
// xxhash: https://code.google.com/p/xxhash/
|
||||
// cityhash: https://code.google.com/p/cityhash/
|
||||
|
||||
// +build amd64 amd64p32 ppc64 ppc64le
|
||||
// +build amd64 amd64p32 arm64 ppc64 ppc64le
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// 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
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// In addition to the 16 bits taken from the top, we can take 3 from the
|
||||
// bottom, because node must be pointer-aligned, giving a total of 19 bits
|
||||
// of count.
|
||||
const (
|
||||
addrBits = 48
|
||||
cntBits = 64 - addrBits + 3
|
||||
)
|
||||
|
||||
func lfstackPack(node *lfnode, cnt uintptr) uint64 {
|
||||
return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
|
||||
}
|
||||
|
||||
func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
|
||||
node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
|
||||
cnt = uintptr(val & (1<<cntBits - 1))
|
||||
return
|
||||
}
|
||||
|
|
@ -253,12 +253,20 @@ func mallocinit() {
|
|||
// but it hardly matters: e0 00 is not valid UTF-8 either.
|
||||
//
|
||||
// If this fails we fall back to the 32 bit memory mechanism
|
||||
//
|
||||
// However, on arm64, we ignore all this advice above and slam the
|
||||
// allocation at 0x40 << 32 because when using 4k pages with 3-level
|
||||
// translation buffers, the user address space is limited to 39 bits
|
||||
arenaSize := round(_MaxMem, _PageSize)
|
||||
bitmapSize = arenaSize / (ptrSize * 8 / 4)
|
||||
spansSize = arenaSize / _PageSize * ptrSize
|
||||
spansSize = round(spansSize, _PageSize)
|
||||
for i := 0; i <= 0x7f; i++ {
|
||||
p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32)
|
||||
if GOARCH == "arm64" {
|
||||
p = uintptr(i)<<40 | uintptrMask&(0x0040<<32)
|
||||
} else {
|
||||
p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32)
|
||||
}
|
||||
pSize = bitmapSize + spansSize + arenaSize + _PageSize
|
||||
p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved))
|
||||
if p != 0 {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// void runtime·memclr(void*, uintptr)
|
||||
TEXT runtime·memclr(SB),NOSPLIT,$0-16
|
||||
MOVD ptr+0(FP), R3
|
||||
MOVD n+8(FP), R4
|
||||
CMP $0, R4
|
||||
BEQ done
|
||||
ADD R3, R4, R4
|
||||
MOVBU.P $0, 1(R3)
|
||||
CMP R3, R4
|
||||
BNE -2(PC)
|
||||
done:
|
||||
RET
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// void runtime·memmove(void*, void*, uintptr)
|
||||
TEXT runtime·memmove(SB), NOSPLIT, $-8-24
|
||||
MOVD to+0(FP), R3
|
||||
MOVD from+8(FP), R4
|
||||
MOVD n+16(FP), R5
|
||||
CMP $0, R5
|
||||
BNE check
|
||||
RET
|
||||
|
||||
check:
|
||||
CMP R3, R4
|
||||
BLT backward
|
||||
|
||||
ADD R3, R5
|
||||
loop:
|
||||
MOVBU.P 1(R4), R6
|
||||
MOVBU.P R6, 1(R3)
|
||||
CMP R3, R5
|
||||
BNE loop
|
||||
RET
|
||||
|
||||
backward:
|
||||
ADD R5, R4
|
||||
ADD R3, R5
|
||||
loop1:
|
||||
MOVBU.W -1(R4), R6
|
||||
MOVBU.W R6, -1(R5)
|
||||
CMP R3, R5
|
||||
BNE loop1
|
||||
RET
|
||||
|
|
@ -289,10 +289,13 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWorkProducer
|
|||
// Scan local variables if stack frame has been allocated.
|
||||
size := frame.varp - frame.sp
|
||||
var minsize uintptr
|
||||
if thechar != '6' && thechar != '8' {
|
||||
minsize = ptrSize
|
||||
} else {
|
||||
switch thechar {
|
||||
case '6', '8':
|
||||
minsize = 0
|
||||
case '7':
|
||||
minsize = spAlign
|
||||
default:
|
||||
minsize = ptrSize
|
||||
}
|
||||
if size > minsize {
|
||||
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// Routines that are implemented in assembly in asm_{amd64,386}.s
|
||||
|
||||
// +build arm ppc64 ppc64le
|
||||
// +build arm arm64 ppc64 ppc64le
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
_AT_NULL = 0
|
||||
_AT_RANDOM = 25 // introduced in 2.6.29
|
||||
)
|
||||
|
||||
var randomNumber uint32
|
||||
|
||||
func cputicks() int64 {
|
||||
// Currently cputicks() is used in blocking profiler and to seed fastrand1().
|
||||
// nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
|
||||
// randomNumber provides better seeding of fastrand1.
|
||||
return nanotime() + int64(randomNumber)
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ package runtime
|
|||
//uint32 runtime·panicking;
|
||||
var paniclk mutex
|
||||
|
||||
const hasLinkRegister = GOARCH == "arm" || GOARCH == "ppc64" || GOARCH == "ppc64le"
|
||||
const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
|
||||
|
||||
// Unwind the stack after a deferred function calls recover
|
||||
// after a panic. Then arrange to continue running as though
|
||||
|
|
|
|||
|
|
@ -2042,15 +2042,19 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr
|
|||
throw("newproc1: new g is not Gdead")
|
||||
}
|
||||
|
||||
sp := newg.stack.hi
|
||||
sp -= 4 * regSize // extra space in case of reads slightly beyond frame
|
||||
sp -= uintptr(siz)
|
||||
memmove(unsafe.Pointer(sp), unsafe.Pointer(argp), uintptr(narg))
|
||||
totalSize := 4*regSize + uintptr(siz) // extra space in case of reads slightly beyond frame
|
||||
if hasLinkRegister {
|
||||
totalSize += ptrSize
|
||||
}
|
||||
totalSize += -totalSize & (spAlign - 1) // align to spAlign
|
||||
sp := newg.stack.hi - totalSize
|
||||
spArg := sp
|
||||
if hasLinkRegister {
|
||||
// caller's LR
|
||||
sp -= ptrSize
|
||||
*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
|
||||
spArg += ptrSize
|
||||
}
|
||||
memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
|
||||
|
||||
memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
|
||||
newg.sched.sp = sp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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 _rt0_arm64_linux(SB),NOSPLIT,$-8
|
||||
MOVD 0(RSP), R0 // argc
|
||||
ADD $8, RSP, R1 // argv
|
||||
BL main(SB)
|
||||
|
||||
TEXT main(SB),NOSPLIT,$-8
|
||||
MOVD $runtime·rt0_go(SB), R2
|
||||
BL (R2)
|
||||
exit:
|
||||
MOVD $0, R0
|
||||
MOVD $94, R8 // sys_exit
|
||||
SVC
|
||||
B exit
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
// 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.
|
||||
|
||||
// +build linux
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func dumpregs(c *sigctxt) {
|
||||
print("r0 ", hex(c.r0()), "\n")
|
||||
print("r1 ", hex(c.r1()), "\n")
|
||||
print("r2 ", hex(c.r2()), "\n")
|
||||
print("r3 ", hex(c.r3()), "\n")
|
||||
print("r4 ", hex(c.r4()), "\n")
|
||||
print("r5 ", hex(c.r5()), "\n")
|
||||
print("r6 ", hex(c.r6()), "\n")
|
||||
print("r7 ", hex(c.r7()), "\n")
|
||||
print("r8 ", hex(c.r8()), "\n")
|
||||
print("r9 ", hex(c.r9()), "\n")
|
||||
print("r10 ", hex(c.r10()), "\n")
|
||||
print("r11 ", hex(c.r11()), "\n")
|
||||
print("r12 ", hex(c.r12()), "\n")
|
||||
print("r13 ", hex(c.r13()), "\n")
|
||||
print("r14 ", hex(c.r14()), "\n")
|
||||
print("r15 ", hex(c.r15()), "\n")
|
||||
print("r16 ", hex(c.r16()), "\n")
|
||||
print("r17 ", hex(c.r17()), "\n")
|
||||
print("r18 ", hex(c.r18()), "\n")
|
||||
print("r19 ", hex(c.r19()), "\n")
|
||||
print("r20 ", hex(c.r20()), "\n")
|
||||
print("r21 ", hex(c.r21()), "\n")
|
||||
print("r22 ", hex(c.r22()), "\n")
|
||||
print("r23 ", hex(c.r23()), "\n")
|
||||
print("r24 ", hex(c.r24()), "\n")
|
||||
print("r25 ", hex(c.r25()), "\n")
|
||||
print("r26 ", hex(c.r26()), "\n")
|
||||
print("r27 ", hex(c.r27()), "\n")
|
||||
print("r28 ", hex(c.r28()), "\n")
|
||||
print("r29 ", hex(c.r29()), "\n")
|
||||
print("lr ", hex(c.lr()), "\n")
|
||||
print("sp ", hex(c.sp()), "\n")
|
||||
print("pc ", hex(c.pc()), "\n")
|
||||
print("fault ", hex(c.fault()), "\n")
|
||||
}
|
||||
|
||||
func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
_g_ := getg()
|
||||
c := &sigctxt{info, ctxt}
|
||||
|
||||
if sig == _SIGPROF {
|
||||
sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp, _g_.m)
|
||||
return
|
||||
}
|
||||
|
||||
flags := int32(_SigThrow)
|
||||
if sig < uint32(len(sigtable)) {
|
||||
flags = sigtable[sig].flags
|
||||
}
|
||||
if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
|
||||
// Make it look like a call to the signal func.
|
||||
// Have to pass arguments out of band since
|
||||
// augmenting the stack frame would break
|
||||
// the unwinding code.
|
||||
gp.sig = sig
|
||||
gp.sigcode0 = uintptr(c.sigcode())
|
||||
gp.sigcode1 = uintptr(c.fault())
|
||||
gp.sigpc = uintptr(c.pc())
|
||||
|
||||
// We arrange lr, and pc to pretend the panicking
|
||||
// function calls sigpanic directly.
|
||||
// Always save LR to stack so that panics in leaf
|
||||
// functions are correctly handled. This smashes
|
||||
// the stack frame but we're not going back there
|
||||
// anyway.
|
||||
sp := c.sp() - spAlign // needs only sizeof uint64, but must align the stack
|
||||
c.set_sp(sp)
|
||||
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
|
||||
|
||||
// Don't bother saving PC if it's zero, which is
|
||||
// probably a call to a nil func: the old link register
|
||||
// is more useful in the stack trace.
|
||||
if gp.sigpc != 0 {
|
||||
c.set_lr(uint64(gp.sigpc))
|
||||
}
|
||||
|
||||
// In case we are panicking from external C code
|
||||
c.set_r28(uint64(uintptr(unsafe.Pointer(gp))))
|
||||
c.set_pc(uint64(funcPC(sigpanic)))
|
||||
return
|
||||
}
|
||||
|
||||
if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
|
||||
if sigsend(sig) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
exit(2)
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_g_.m.throwing = 1
|
||||
_g_.m.caughtsig = gp
|
||||
startpanic()
|
||||
|
||||
if sig < uint32(len(sigtable)) {
|
||||
print(sigtable[sig].name, "\n")
|
||||
} else {
|
||||
print("Signal ", sig, "\n")
|
||||
}
|
||||
|
||||
print("PC=", hex(c.pc()), "\n")
|
||||
if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
|
||||
print("signal arrived during cgo execution\n")
|
||||
gp = _g_.m.lockedg
|
||||
}
|
||||
print("\n")
|
||||
|
||||
var docrash bool
|
||||
if gotraceback(&docrash) > 0 {
|
||||
goroutineheader(gp)
|
||||
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
|
||||
tracebackothers(gp)
|
||||
print("\n")
|
||||
dumpregs(c)
|
||||
}
|
||||
|
||||
if docrash {
|
||||
crash()
|
||||
}
|
||||
|
||||
exit(2)
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// 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.
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type sigctxt struct {
|
||||
info *siginfo
|
||||
ctxt unsafe.Pointer
|
||||
}
|
||||
|
||||
func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
|
||||
func (c *sigctxt) r0() uint64 { return c.regs().regs[0] }
|
||||
func (c *sigctxt) r1() uint64 { return c.regs().regs[1] }
|
||||
func (c *sigctxt) r2() uint64 { return c.regs().regs[2] }
|
||||
func (c *sigctxt) r3() uint64 { return c.regs().regs[3] }
|
||||
func (c *sigctxt) r4() uint64 { return c.regs().regs[4] }
|
||||
func (c *sigctxt) r5() uint64 { return c.regs().regs[5] }
|
||||
func (c *sigctxt) r6() uint64 { return c.regs().regs[6] }
|
||||
func (c *sigctxt) r7() uint64 { return c.regs().regs[7] }
|
||||
func (c *sigctxt) r8() uint64 { return c.regs().regs[8] }
|
||||
func (c *sigctxt) r9() uint64 { return c.regs().regs[9] }
|
||||
func (c *sigctxt) r10() uint64 { return c.regs().regs[10] }
|
||||
func (c *sigctxt) r11() uint64 { return c.regs().regs[11] }
|
||||
func (c *sigctxt) r12() uint64 { return c.regs().regs[12] }
|
||||
func (c *sigctxt) r13() uint64 { return c.regs().regs[13] }
|
||||
func (c *sigctxt) r14() uint64 { return c.regs().regs[14] }
|
||||
func (c *sigctxt) r15() uint64 { return c.regs().regs[15] }
|
||||
func (c *sigctxt) r16() uint64 { return c.regs().regs[16] }
|
||||
func (c *sigctxt) r17() uint64 { return c.regs().regs[17] }
|
||||
func (c *sigctxt) r18() uint64 { return c.regs().regs[18] }
|
||||
func (c *sigctxt) r19() uint64 { return c.regs().regs[19] }
|
||||
func (c *sigctxt) r20() uint64 { return c.regs().regs[20] }
|
||||
func (c *sigctxt) r21() uint64 { return c.regs().regs[21] }
|
||||
func (c *sigctxt) r22() uint64 { return c.regs().regs[22] }
|
||||
func (c *sigctxt) r23() uint64 { return c.regs().regs[23] }
|
||||
func (c *sigctxt) r24() uint64 { return c.regs().regs[24] }
|
||||
func (c *sigctxt) r25() uint64 { return c.regs().regs[25] }
|
||||
func (c *sigctxt) r26() uint64 { return c.regs().regs[26] }
|
||||
func (c *sigctxt) r27() uint64 { return c.regs().regs[27] }
|
||||
func (c *sigctxt) r28() uint64 { return c.regs().regs[28] }
|
||||
func (c *sigctxt) r29() uint64 { return c.regs().regs[29] }
|
||||
func (c *sigctxt) lr() uint64 { return c.regs().regs[30] }
|
||||
func (c *sigctxt) sp() uint64 { return c.regs().sp }
|
||||
func (c *sigctxt) pc() uint64 { return c.regs().pc }
|
||||
func (c *sigctxt) pstate() uint64 { return c.regs().pstate }
|
||||
func (c *sigctxt) fault() uint64 { return c.regs().fault_address }
|
||||
|
||||
func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
|
||||
func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
|
||||
|
||||
func (c *sigctxt) set_pc(x uint64) { c.regs().pc = x }
|
||||
func (c *sigctxt) set_sp(x uint64) { c.regs().sp = x }
|
||||
func (c *sigctxt) set_lr(x uint64) { c.regs().regs[30] = x }
|
||||
func (c *sigctxt) set_r28(x uint64) { c.regs().regs[28] = x }
|
||||
|
||||
func (c *sigctxt) set_sigaddr(x uint64) {
|
||||
*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
|
||||
}
|
||||
|
|
@ -439,10 +439,13 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
|
|||
// Adjust local variables if stack frame has been allocated.
|
||||
size := frame.varp - frame.sp
|
||||
var minsize uintptr
|
||||
if thechar != '6' && thechar != '8' {
|
||||
minsize = ptrSize
|
||||
} else {
|
||||
switch thechar {
|
||||
case '6', '8':
|
||||
minsize = 0
|
||||
case '7':
|
||||
minsize = spAlign
|
||||
default:
|
||||
minsize = ptrSize
|
||||
}
|
||||
if size > minsize {
|
||||
var bv bitvector
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ import "unsafe"
|
|||
|
||||
// Declarations for runtime services implemented in C or assembly.
|
||||
|
||||
const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
|
||||
const regSize = 4 << (^uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const
|
||||
const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
|
||||
const regSize = 4 << (^uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const
|
||||
const spAlign = 1*(1-goarch_arm64) + 16*goarch_arm64 // SP alignment: 1 normally, 16 for ARM64
|
||||
|
||||
// Should be a built-in for unsafe.Pointer?
|
||||
//go:nosplit
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2013 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"
|
||||
|
||||
// adjust Gobuf as if it executed a call to fn with context ctxt
|
||||
// and then did an immediate Gosave.
|
||||
func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
|
||||
if buf.lr != 0 {
|
||||
throw("invalid use of gostartcall")
|
||||
}
|
||||
buf.lr = buf.pc
|
||||
buf.pc = uintptr(fn)
|
||||
buf.ctxt = ctxt
|
||||
}
|
||||
|
||||
// Called to rewind context saved during morestack back to beginning of function.
|
||||
// To help us, the linker emits a jmp back to the beginning right after the
|
||||
// call to morestack. We just have to decode and apply that jump.
|
||||
func rewindmorestack(buf *gobuf) {
|
||||
var inst uint32
|
||||
if buf.pc&3 == 0 && buf.pc != 0 {
|
||||
inst = *(*uint32)(unsafe.Pointer(buf.pc))
|
||||
// section C3.2.6 Unconditional branch (immediate)
|
||||
if inst>>26 == 0x05 {
|
||||
buf.pc += uintptr(int32(inst<<6) >> 4)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
|
||||
throw("runtime: misuse of rewindmorestack")
|
||||
}
|
||||
|
|
@ -0,0 +1,431 @@
|
|||
// 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.
|
||||
|
||||
//
|
||||
// System calls and other sys.stuff for arm64, Linux
|
||||
//
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "textflag.h"
|
||||
|
||||
#define AT_FDCWD -100
|
||||
|
||||
#define SYS_exit 93
|
||||
#define SYS_read 63
|
||||
#define SYS_write 64
|
||||
#define SYS_openat 56
|
||||
#define SYS_close 57
|
||||
#define SYS_fcntl 25
|
||||
#define SYS_gettimeofday 169
|
||||
#define SYS_pselect6 72
|
||||
#define SYS_mmap 222
|
||||
#define SYS_munmap 215
|
||||
#define SYS_setitimer 103
|
||||
#define SYS_clone 220
|
||||
#define SYS_sched_yield 124
|
||||
#define SYS_rt_sigreturn 139
|
||||
#define SYS_rt_sigaction 134
|
||||
#define SYS_rt_sigprocmask 135
|
||||
#define SYS_sigaltstack 132
|
||||
#define SYS_getrlimit 163
|
||||
#define SYS_madvise 233
|
||||
#define SYS_mincore 232
|
||||
#define SYS_gettid 178
|
||||
#define SYS_tkill 130
|
||||
#define SYS_futex 98
|
||||
#define SYS_sched_getaffinity 123
|
||||
#define SYS_exit_group 94
|
||||
#define SYS_epoll_create1 20
|
||||
#define SYS_epoll_ctl 21
|
||||
#define SYS_epoll_pwait 22
|
||||
#define SYS_clock_gettime 113
|
||||
|
||||
TEXT runtime·exit(SB),NOSPLIT,$-8-4
|
||||
MOVW code+0(FP), R0
|
||||
MOVD $SYS_exit_group, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·exit1(SB),NOSPLIT,$-8-4
|
||||
MOVW code+0(FP), R0
|
||||
MOVD $SYS_exit, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·open(SB),NOSPLIT,$-8-20
|
||||
MOVD $AT_FDCWD, R0
|
||||
MOVD name+0(FP), R1
|
||||
MOVW mode+8(FP), R2
|
||||
MOVW perm+12(FP), R3
|
||||
MOVD $SYS_openat, R8
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC done
|
||||
MOVW $-1, R0
|
||||
done:
|
||||
MOVW R0, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·close(SB),NOSPLIT,$-8-12
|
||||
MOVW fd+0(FP), R0
|
||||
MOVD $SYS_close, R8
|
||||
SVC
|
||||
BCC done
|
||||
MOVW $-1, R0
|
||||
done:
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·write(SB),NOSPLIT,$-8-28
|
||||
MOVD fd+0(FP), R0
|
||||
MOVD p+8(FP), R1
|
||||
MOVW n+16(FP), R2
|
||||
MOVD $SYS_write, R8
|
||||
SVC
|
||||
BCC done
|
||||
MOVW $-1, R0
|
||||
done:
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·read(SB),NOSPLIT,$-8-28
|
||||
MOVW fd+0(FP), R0
|
||||
MOVD p+8(FP), R1
|
||||
MOVW n+16(FP), R2
|
||||
MOVD $SYS_read, R8
|
||||
SVC
|
||||
BCC done
|
||||
MOVW $-1, R0
|
||||
done:
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
|
||||
MOVW kind+0(FP), R0
|
||||
MOVD limit+8(FP), R1
|
||||
MOVD $SYS_getrlimit, R8
|
||||
SVC
|
||||
MOVW R0, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·usleep(SB),NOSPLIT,$16-4
|
||||
MOVWU usec+0(FP), R3
|
||||
MOVD R3, R5
|
||||
MOVW $1000000, R4
|
||||
UDIV R4, R3
|
||||
MOVD R3, 8(RSP)
|
||||
MUL R3, R4
|
||||
SUB R4, R5
|
||||
MOVW $1000, R4
|
||||
MUL R4, R5
|
||||
MOVD R5, 16(RSP)
|
||||
|
||||
// pselect6(0, 0, 0, 0, &ts, 0)
|
||||
MOVD $0, R0
|
||||
MOVD R0, R1
|
||||
MOVD R0, R2
|
||||
MOVD R0, R3
|
||||
ADD $8, RSP, R4
|
||||
MOVD R0, R5
|
||||
MOVD $SYS_pselect6, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·raise(SB),NOSPLIT,$-8
|
||||
MOVD $SYS_gettid, R8
|
||||
SVC
|
||||
MOVW R0, R0 // arg 1 tid
|
||||
MOVW sig+0(FP), R1 // arg 2
|
||||
MOVD $SYS_tkill, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
|
||||
MOVW mode+0(FP), R0
|
||||
MOVD new+8(FP), R1
|
||||
MOVD old+16(FP), R2
|
||||
MOVD $SYS_setitimer, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·mincore(SB),NOSPLIT,$-8-28
|
||||
MOVD addr+0(FP), R0
|
||||
MOVD n+8(FP), R1
|
||||
MOVD dst+16(FP), R2
|
||||
MOVD $SYS_mincore, R8
|
||||
SVC
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
// func now() (sec int64, nsec int32)
|
||||
TEXT time·now(SB),NOSPLIT,$16-12
|
||||
MOVD RSP, R0
|
||||
MOVD $0, R1
|
||||
MOVD $SYS_gettimeofday, R8
|
||||
SVC
|
||||
MOVD 0(RSP), R3 // sec
|
||||
MOVD 8(RSP), R5 // usec
|
||||
MOVD $1000, R4
|
||||
MUL R4, R5
|
||||
MOVD R3, sec+0(FP)
|
||||
MOVW R5, nsec+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·nanotime(SB),NOSPLIT,$16-8
|
||||
MOVW $1, R0 // CLOCK_MONOTONIC
|
||||
MOVD RSP, R1
|
||||
MOVD $SYS_clock_gettime, R8
|
||||
SVC
|
||||
MOVD 0(RSP), R3 // sec
|
||||
MOVD 8(RSP), R5 // nsec
|
||||
// sec is in R3, nsec in R5
|
||||
// return nsec in R3
|
||||
MOVD $1000000000, R4
|
||||
MUL R4, R3
|
||||
ADD R5, R3
|
||||
MOVD R3, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
|
||||
MOVW sig+0(FP), R0
|
||||
MOVD new+8(FP), R1
|
||||
MOVD old+16(FP), R2
|
||||
MOVW size+24(FP), R3
|
||||
MOVD $SYS_rt_sigprocmask, R8
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC done
|
||||
MOVD $0, R0
|
||||
MOVD R0, (R0) // crash
|
||||
done:
|
||||
RET
|
||||
|
||||
TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
|
||||
MOVD sig+0(FP), R0
|
||||
MOVD new+8(FP), R1
|
||||
MOVD old+16(FP), R2
|
||||
MOVD size+24(FP), R3
|
||||
MOVD $SYS_rt_sigaction, R8
|
||||
SVC
|
||||
MOVW R0, ret+32(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·sigtramp(SB),NOSPLIT,$64
|
||||
// this might be called in external code context,
|
||||
// where g is not set.
|
||||
// first save R0, because runtime·load_g will clobber it
|
||||
MOVW R0, 8(RSP)
|
||||
// TODO(minux): iscgo & load_g
|
||||
|
||||
// check that g exists
|
||||
CMP g, ZR
|
||||
BNE ok
|
||||
MOVD $runtime·badsignal(SB), R0
|
||||
BL (R0)
|
||||
RET
|
||||
|
||||
ok:
|
||||
// save g
|
||||
MOVD g, 40(RSP)
|
||||
MOVD g, R6
|
||||
|
||||
// g = m->gsignal
|
||||
MOVD g_m(g), R7
|
||||
MOVD m_gsignal(R7), g
|
||||
|
||||
// R0 is already saved above
|
||||
MOVD R1, 16(RSP)
|
||||
MOVD R2, 24(RSP)
|
||||
MOVD R6, 32(RSP)
|
||||
|
||||
BL runtime·sighandler(SB)
|
||||
|
||||
// restore g
|
||||
MOVD 40(RSP), g
|
||||
RET
|
||||
|
||||
TEXT runtime·mmap(SB),NOSPLIT,$-8
|
||||
MOVD addr+0(FP), R0
|
||||
MOVD n+8(FP), R1
|
||||
MOVW prot+16(FP), R2
|
||||
MOVW flags+20(FP), R3
|
||||
MOVW fd+24(FP), R4
|
||||
MOVW off+28(FP), R5
|
||||
|
||||
MOVD $SYS_mmap, R8
|
||||
SVC
|
||||
MOVD R0, ret+32(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·munmap(SB),NOSPLIT,$-8
|
||||
MOVD addr+0(FP), R0
|
||||
MOVD n+8(FP), R1
|
||||
MOVD $SYS_munmap, R8
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC cool
|
||||
MOVD R0, 0xf0(R0)
|
||||
cool:
|
||||
RET
|
||||
|
||||
TEXT runtime·madvise(SB),NOSPLIT,$-8
|
||||
MOVD addr+0(FP), R0
|
||||
MOVD n+8(FP), R1
|
||||
MOVW flags+16(FP), R2
|
||||
MOVD $SYS_madvise, R8
|
||||
SVC
|
||||
// ignore failure - maybe pages are locked
|
||||
RET
|
||||
|
||||
// int64 futex(int32 *uaddr, int32 op, int32 val,
|
||||
// struct timespec *timeout, int32 *uaddr2, int32 val2);
|
||||
TEXT runtime·futex(SB),NOSPLIT,$-8
|
||||
MOVD addr+0(FP), R0
|
||||
MOVW op+8(FP), R1
|
||||
MOVW val+12(FP), R2
|
||||
MOVD ts+16(FP), R3
|
||||
MOVD addr2+24(FP), R4
|
||||
MOVW val3+32(FP), R5
|
||||
MOVD $SYS_futex, R8
|
||||
SVC
|
||||
MOVW R0, ret+40(FP)
|
||||
RET
|
||||
|
||||
// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
|
||||
TEXT runtime·clone(SB),NOSPLIT,$-8
|
||||
MOVW flags+0(FP), R0
|
||||
MOVD stk+8(FP), R1
|
||||
|
||||
// Copy mp, gp, fn off parent stack for use by child.
|
||||
MOVD mm+16(FP), R10
|
||||
MOVD gg+24(FP), R11
|
||||
MOVD fn+32(FP), R12
|
||||
|
||||
MOVD R10, -8(R1)
|
||||
MOVD R11, -16(R1)
|
||||
MOVD R12, -24(R1)
|
||||
MOVD $1234, R10
|
||||
MOVD R10, -32(R1)
|
||||
|
||||
MOVD $SYS_clone, R8
|
||||
SVC
|
||||
|
||||
// In parent, return.
|
||||
CMP ZR, R0
|
||||
BEQ child
|
||||
MOVW R0, ret+40(FP)
|
||||
RET
|
||||
child:
|
||||
|
||||
// In child, on new stack.
|
||||
MOVD -32(RSP), R10
|
||||
MOVD $1234, R0
|
||||
CMP R0, R10
|
||||
BEQ good
|
||||
MOVD $0, R0
|
||||
MOVD R0, (R0) // crash
|
||||
|
||||
// Initialize m->procid to Linux tid
|
||||
good:
|
||||
MOVD $SYS_gettid, R8
|
||||
SVC
|
||||
|
||||
MOVD -24(RSP), R12
|
||||
MOVD -16(RSP), R11
|
||||
MOVD -8(RSP), R10
|
||||
|
||||
MOVD R0, m_procid(R10)
|
||||
|
||||
// TODO: setup TLS.
|
||||
|
||||
// In child, set up new stack
|
||||
MOVD R10, g_m(R11)
|
||||
MOVD R11, g
|
||||
//CALL runtime·stackcheck(SB)
|
||||
|
||||
// Call fn
|
||||
MOVD R12, R0
|
||||
BL (R0)
|
||||
|
||||
// It shouldn't return. If it does, exit
|
||||
MOVW $111, R0
|
||||
again:
|
||||
MOVD $SYS_exit_group, R8
|
||||
SVC
|
||||
B again // keep exiting
|
||||
|
||||
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
|
||||
MOVD new+0(FP), R0
|
||||
MOVD old+8(FP), R1
|
||||
MOVD $SYS_sigaltstack, R8
|
||||
SVC
|
||||
CMN $4095, R0
|
||||
BCC ok
|
||||
MOVD $0, R0
|
||||
MOVD R0, (R0) // crash
|
||||
ok:
|
||||
RET
|
||||
|
||||
TEXT runtime·osyield(SB),NOSPLIT,$-8
|
||||
MOVD $SYS_sched_yield, R8
|
||||
SVC
|
||||
RET
|
||||
|
||||
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
|
||||
MOVD pid+0(FP), R0
|
||||
MOVD len+8(FP), R1
|
||||
MOVD buf+16(FP), R2
|
||||
MOVD $SYS_sched_getaffinity, R8
|
||||
SVC
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollcreate(int32 size);
|
||||
TEXT runtime·epollcreate(SB),NOSPLIT,$-8
|
||||
MOVW $0, R0
|
||||
MOVD $SYS_epoll_create1, R8
|
||||
SVC
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollcreate1(int32 flags);
|
||||
TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
|
||||
MOVW flags+0(FP), R0
|
||||
MOVD $SYS_epoll_create1, R8
|
||||
SVC
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
// func epollctl(epfd, op, fd int32, ev *epollEvent) int
|
||||
TEXT runtime·epollctl(SB),NOSPLIT,$-8
|
||||
MOVW epfd+0(FP), R0
|
||||
MOVW op+4(FP), R1
|
||||
MOVW fd+8(FP), R2
|
||||
MOVD ev+16(FP), R3
|
||||
MOVD $SYS_epoll_ctl, R8
|
||||
SVC
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
|
||||
TEXT runtime·epollwait(SB),NOSPLIT,$-8
|
||||
MOVW epfd+0(FP), R0
|
||||
MOVD ev+8(FP), R1
|
||||
MOVW nev+16(FP), R2
|
||||
MOVW timeout+20(FP), R3
|
||||
MOVD $0, R4
|
||||
MOVD $SYS_epoll_pwait, R8
|
||||
SVC
|
||||
MOVW R0, ret+24(FP)
|
||||
RET
|
||||
|
||||
// void runtime·closeonexec(int32 fd);
|
||||
TEXT runtime·closeonexec(SB),NOSPLIT,$-8
|
||||
MOVW fd+0(FP), R0 // fd
|
||||
MOVD $2, R1 // F_SETFD
|
||||
MOVD $1, R2 // FD_CLOEXEC
|
||||
MOVD $SYS_fcntl, R8
|
||||
SVC
|
||||
RET
|
||||
|
|
@ -357,6 +357,10 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
|||
if usesLR && waspanic {
|
||||
x := *(*uintptr)(unsafe.Pointer(frame.sp))
|
||||
frame.sp += ptrSize
|
||||
if GOARCH == "arm64" {
|
||||
// arm64 needs 16-byte aligned SP, always
|
||||
frame.sp += ptrSize
|
||||
}
|
||||
f = findfunc(frame.pc)
|
||||
frame.fn = f
|
||||
if f == nil {
|
||||
|
|
|
|||
|
|
@ -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 386 amd64 amd64p32
|
||||
// +build 386 amd64 amd64p32 arm64
|
||||
|
||||
package runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 1
|
|||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 0
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 0
|
|||
const goarch_amd64 = 1
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 0
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 0
|
|||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 1
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 0
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 0
|
|||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 1
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// generated by gengoos.go using 'go generate'
|
||||
|
||||
package runtime
|
||||
|
||||
const theGoarch = `arm64`
|
||||
|
||||
const goarch_386 = 0
|
||||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 1
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 0
|
||||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 0
|
|||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 1
|
||||
const goarch_ppc64le = 0
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ const goarch_386 = 0
|
|||
const goarch_amd64 = 0
|
||||
const goarch_amd64p32 = 0
|
||||
const goarch_arm = 0
|
||||
const goarch_arm64 = 0
|
||||
const goarch_ppc64 = 0
|
||||
const goarch_ppc64le = 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue