mirror of
https://github.com/golang/go
synced 2024-11-19 01:04:40 -07:00
runtime: add s390x support (new files and lfstack_64bit.go modifications)
Change-Id: I51c0a332e3cbdab348564e5dcd27583e75e4b881 Reviewed-on: https://go-review.googlesource.com/20946 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
9658b7ef83
commit
e6f36f0cd5
1130
src/runtime/asm_s390x.s
Normal file
1130
src/runtime/asm_s390x.s
Normal file
File diff suppressed because it is too large
Load Diff
167
src/runtime/defs_linux_s390x.go
Normal file
167
src/runtime/defs_linux_s390x.go
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
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_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_cgo_0 [4]byte
|
||||
data [8]byte // unaligned uintptr
|
||||
}
|
||||
|
||||
const (
|
||||
_O_RDONLY = 0x0
|
||||
_O_CLOEXEC = 0x80000
|
||||
_SA_RESTORER = 0
|
||||
)
|
||||
|
||||
type sigaltstackt struct {
|
||||
ss_sp *byte
|
||||
ss_flags int32
|
||||
ss_size uintptr
|
||||
}
|
||||
|
||||
type sigcontext struct {
|
||||
psw_mask uint64
|
||||
psw_addr uint64
|
||||
gregs [16]uint64
|
||||
aregs [16]uint32
|
||||
fpc uint32
|
||||
fpregs [16]uint64
|
||||
}
|
||||
|
||||
type ucontext struct {
|
||||
uc_flags uint64
|
||||
uc_link *ucontext
|
||||
uc_stack sigaltstackt
|
||||
uc_mcontext sigcontext
|
||||
uc_sigmask uint64
|
||||
}
|
@ -2,26 +2,32 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build arm64 mips64 mips64le ppc64 ppc64le
|
||||
// +build arm64 mips64 mips64le ppc64 ppc64le s390x
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// On ppc64, Linux limits the user address space to 46 bits (see
|
||||
// TASK_SIZE_USER64 in the Linux kernel). This has grown over time,
|
||||
// so here we allow 48 bit addresses.
|
||||
//
|
||||
// On mips64, Linux limits the user address space to 40 bits (see
|
||||
// TASK_SIZE64 in the Linux kernel). This has grown over time,
|
||||
// so here we allow 48 bit addresses.
|
||||
//
|
||||
// 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 is the number of bits needed to represent a virtual address.
|
||||
//
|
||||
// In Linux the user address space for each architecture is limited as
|
||||
// follows (taken from the processor.h file for the architecture):
|
||||
//
|
||||
// Architecture Name Maximum Value (exclusive)
|
||||
// ---------------------------------------------------------------------
|
||||
// arm64 TASK_SIZE_64 Depends on configuration.
|
||||
// ppc64{,le} TASK_SIZE_USER64 0x400000000000UL (46 bit addresses)
|
||||
// mips64{,le} TASK_SIZE64 0x010000000000UL (40 bit addresses)
|
||||
// s390x TASK_SIZE 0x020000000000UL (41 bit addresses)
|
||||
//
|
||||
// These values may increase over time.
|
||||
addrBits = 48
|
||||
cntBits = 64 - addrBits + 3
|
||||
|
||||
// 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.
|
||||
cntBits = 64 - addrBits + 3
|
||||
)
|
||||
|
||||
func lfstackPack(node *lfnode, cnt uintptr) uint64 {
|
||||
|
122
src/runtime/memclr_s390x.s
Normal file
122
src/runtime/memclr_s390x.s
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// void runtime·memclr(void*, uintptr)
|
||||
TEXT runtime·memclr(SB),NOSPLIT|NOFRAME,$0-16
|
||||
MOVD ptr+0(FP), R4
|
||||
MOVD n+8(FP), R5
|
||||
|
||||
start:
|
||||
CMPBLE R5, $3, clear0to3
|
||||
CMPBLE R5, $7, clear4to7
|
||||
CMPBLE R5, $11, clear8to11
|
||||
CMPBLE R5, $15, clear12to15
|
||||
CMP R5, $32
|
||||
BGE clearmt32
|
||||
MOVD R0, 0(R4)
|
||||
MOVD R0, 8(R4)
|
||||
ADD $16, R4
|
||||
SUB $16, R5
|
||||
BR start
|
||||
|
||||
clear0to3:
|
||||
CMPBEQ R5, $0, done
|
||||
CMPBNE R5, $1, clear2
|
||||
MOVB R0, 0(R4)
|
||||
RET
|
||||
clear2:
|
||||
CMPBNE R5, $2, clear3
|
||||
MOVH R0, 0(R4)
|
||||
RET
|
||||
clear3:
|
||||
MOVH R0, 0(R4)
|
||||
MOVB R0, 2(R4)
|
||||
RET
|
||||
|
||||
clear4to7:
|
||||
CMPBNE R5, $4, clear5
|
||||
MOVW R0, 0(R4)
|
||||
RET
|
||||
clear5:
|
||||
CMPBNE R5, $5, clear6
|
||||
MOVW R0, 0(R4)
|
||||
MOVB R0, 4(R4)
|
||||
RET
|
||||
clear6:
|
||||
CMPBNE R5, $6, clear7
|
||||
MOVW R0, 0(R4)
|
||||
MOVH R0, 4(R4)
|
||||
RET
|
||||
clear7:
|
||||
MOVW R0, 0(R4)
|
||||
MOVH R0, 4(R4)
|
||||
MOVB R0, 6(R4)
|
||||
RET
|
||||
|
||||
clear8to11:
|
||||
CMPBNE R5, $8, clear9
|
||||
MOVD R0, 0(R4)
|
||||
RET
|
||||
clear9:
|
||||
CMPBNE R5, $9, clear10
|
||||
MOVD R0, 0(R4)
|
||||
MOVB R0, 8(R4)
|
||||
RET
|
||||
clear10:
|
||||
CMPBNE R5, $10, clear11
|
||||
MOVD R0, 0(R4)
|
||||
MOVH R0, 8(R4)
|
||||
RET
|
||||
clear11:
|
||||
MOVD R0, 0(R4)
|
||||
MOVH R0, 8(R4)
|
||||
MOVB R0, 10(R4)
|
||||
RET
|
||||
|
||||
clear12to15:
|
||||
CMPBNE R5, $12, clear13
|
||||
MOVD R0, 0(R4)
|
||||
MOVW R0, 8(R4)
|
||||
RET
|
||||
clear13:
|
||||
CMPBNE R5, $13, clear14
|
||||
MOVD R0, 0(R4)
|
||||
MOVW R0, 8(R4)
|
||||
MOVB R0, 12(R4)
|
||||
RET
|
||||
clear14:
|
||||
CMPBNE R5, $14, clear15
|
||||
MOVD R0, 0(R4)
|
||||
MOVW R0, 8(R4)
|
||||
MOVH R0, 12(R4)
|
||||
RET
|
||||
clear15:
|
||||
MOVD R0, 0(R4)
|
||||
MOVW R0, 8(R4)
|
||||
MOVH R0, 12(R4)
|
||||
MOVB R0, 14(R4)
|
||||
RET
|
||||
|
||||
clearmt32:
|
||||
CMP R5, $256
|
||||
BLT clearlt256
|
||||
XC $256, 0(R4), 0(R4)
|
||||
ADD $256, R4
|
||||
ADD $-256, R5
|
||||
BR clearmt32
|
||||
clearlt256:
|
||||
CMPBEQ R5, $0, done
|
||||
ADD $-1, R5
|
||||
EXRL $runtime·memclr_s390x_exrl_xc(SB), R5
|
||||
done:
|
||||
RET
|
||||
|
||||
// DO NOT CALL - target for exrl (execute relative long) instruction.
|
||||
TEXT runtime·memclr_s390x_exrl_xc(SB),NOSPLIT|NOFRAME,$0-0
|
||||
XC $1, 0(R4), 0(R4)
|
||||
MOVD R0, 0(R0)
|
||||
RET
|
||||
|
189
src/runtime/memmove_s390x.s
Normal file
189
src/runtime/memmove_s390x.s
Normal file
@ -0,0 +1,189 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// void runtime·memmove(void*, void*, uintptr)
|
||||
TEXT runtime·memmove(SB),NOSPLIT|NOFRAME,$0-24
|
||||
MOVD to+0(FP), R6
|
||||
MOVD from+8(FP), R4
|
||||
MOVD n+16(FP), R5
|
||||
|
||||
CMPBEQ R6, R4, done
|
||||
|
||||
start:
|
||||
CMPBLE R5, $3, move0to3
|
||||
CMPBLE R5, $7, move4to7
|
||||
CMPBLE R5, $11, move8to11
|
||||
CMPBLE R5, $15, move12to15
|
||||
CMPBNE R5, $16, movemt16
|
||||
MOVD 0(R4), R7
|
||||
MOVD 8(R4), R8
|
||||
MOVD R7, 0(R6)
|
||||
MOVD R8, 8(R6)
|
||||
RET
|
||||
|
||||
movemt16:
|
||||
CMPBGT R4, R6, forwards
|
||||
ADD R5, R4, R7
|
||||
CMPBLE R7, R6, forwards
|
||||
ADD R5, R6, R8
|
||||
backwards:
|
||||
MOVD -8(R7), R3
|
||||
MOVD R3, -8(R8)
|
||||
MOVD -16(R7), R3
|
||||
MOVD R3, -16(R8)
|
||||
ADD $-16, R5
|
||||
ADD $-16, R7
|
||||
ADD $-16, R8
|
||||
CMP R5, $16
|
||||
BGE backwards
|
||||
BR start
|
||||
|
||||
forwards:
|
||||
CMPBGT R5, $64, forwards_fast
|
||||
MOVD 0(R4), R3
|
||||
MOVD R3, 0(R6)
|
||||
MOVD 8(R4), R3
|
||||
MOVD R3, 8(R6)
|
||||
ADD $16, R4
|
||||
ADD $16, R6
|
||||
ADD $-16, R5
|
||||
CMP R5, $16
|
||||
BGE forwards
|
||||
BR start
|
||||
|
||||
forwards_fast:
|
||||
CMP R5, $256
|
||||
BLE forwards_small
|
||||
MVC $256, 0(R4), 0(R6)
|
||||
ADD $256, R4
|
||||
ADD $256, R6
|
||||
ADD $-256, R5
|
||||
BR forwards_fast
|
||||
|
||||
forwards_small:
|
||||
CMPBEQ R5, $0, done
|
||||
ADD $-1, R5
|
||||
EXRL $runtime·memmove_s390x_exrl_mvc(SB), R5
|
||||
RET
|
||||
|
||||
move0to3:
|
||||
CMPBEQ R5, $0, done
|
||||
move1:
|
||||
CMPBNE R5, $1, move2
|
||||
MOVB 0(R4), R3
|
||||
MOVB R3, 0(R6)
|
||||
RET
|
||||
move2:
|
||||
CMPBNE R5, $2, move3
|
||||
MOVH 0(R4), R3
|
||||
MOVH R3, 0(R6)
|
||||
RET
|
||||
move3:
|
||||
MOVH 0(R4), R3
|
||||
MOVB 2(R4), R7
|
||||
MOVH R3, 0(R6)
|
||||
MOVB R7, 2(R6)
|
||||
RET
|
||||
|
||||
move4to7:
|
||||
CMPBNE R5, $4, move5
|
||||
MOVW 0(R4), R3
|
||||
MOVW R3, 0(R6)
|
||||
RET
|
||||
move5:
|
||||
CMPBNE R5, $5, move6
|
||||
MOVW 0(R4), R3
|
||||
MOVB 4(R4), R7
|
||||
MOVW R3, 0(R6)
|
||||
MOVB R7, 4(R6)
|
||||
RET
|
||||
move6:
|
||||
CMPBNE R5, $6, move7
|
||||
MOVW 0(R4), R3
|
||||
MOVH 4(R4), R7
|
||||
MOVW R3, 0(R6)
|
||||
MOVH R7, 4(R6)
|
||||
RET
|
||||
move7:
|
||||
MOVW 0(R4), R3
|
||||
MOVH 4(R4), R7
|
||||
MOVB 6(R4), R8
|
||||
MOVW R3, 0(R6)
|
||||
MOVH R7, 4(R6)
|
||||
MOVB R8, 6(R6)
|
||||
RET
|
||||
|
||||
move8to11:
|
||||
CMPBNE R5, $8, move9
|
||||
MOVD 0(R4), R3
|
||||
MOVD R3, 0(R6)
|
||||
RET
|
||||
move9:
|
||||
CMPBNE R5, $9, move10
|
||||
MOVD 0(R4), R3
|
||||
MOVB 8(R4), R7
|
||||
MOVD R3, 0(R6)
|
||||
MOVB R7, 8(R6)
|
||||
RET
|
||||
move10:
|
||||
CMPBNE R5, $10, move11
|
||||
MOVD 0(R4), R3
|
||||
MOVH 8(R4), R7
|
||||
MOVD R3, 0(R6)
|
||||
MOVH R7, 8(R6)
|
||||
RET
|
||||
move11:
|
||||
MOVD 0(R4), R3
|
||||
MOVH 8(R4), R7
|
||||
MOVB 10(R4), R8
|
||||
MOVD R3, 0(R6)
|
||||
MOVH R7, 8(R6)
|
||||
MOVB R8, 10(R6)
|
||||
RET
|
||||
|
||||
move12to15:
|
||||
CMPBNE R5, $12, move13
|
||||
MOVD 0(R4), R3
|
||||
MOVW 8(R4), R7
|
||||
MOVD R3, 0(R6)
|
||||
MOVW R7, 8(R6)
|
||||
RET
|
||||
move13:
|
||||
CMPBNE R5, $13, move14
|
||||
MOVD 0(R4), R3
|
||||
MOVW 8(R4), R7
|
||||
MOVB 12(R4), R8
|
||||
MOVD R3, 0(R6)
|
||||
MOVW R7, 8(R6)
|
||||
MOVB R8, 12(R6)
|
||||
RET
|
||||
move14:
|
||||
CMPBNE R5, $14, move15
|
||||
MOVD 0(R4), R3
|
||||
MOVW 8(R4), R7
|
||||
MOVH 12(R4), R8
|
||||
MOVD R3, 0(R6)
|
||||
MOVW R7, 8(R6)
|
||||
MOVH R8, 12(R6)
|
||||
RET
|
||||
move15:
|
||||
MOVD 0(R4), R3
|
||||
MOVW 8(R4), R7
|
||||
MOVH 12(R4), R8
|
||||
MOVB 14(R4), R10
|
||||
MOVD R3, 0(R6)
|
||||
MOVW R7, 8(R6)
|
||||
MOVH R8, 12(R6)
|
||||
MOVB R10, 14(R6)
|
||||
done:
|
||||
RET
|
||||
|
||||
// DO NOT CALL - target for exrl (execute relative long) instruction.
|
||||
TEXT runtime·memmove_s390x_exrl_mvc(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MVC $1, 0(R4), 0(R6)
|
||||
MOVD R0, 0(R0)
|
||||
RET
|
||||
|
46
src/runtime/os_linux_s390x.go
Normal file
46
src/runtime/os_linux_s390x.go
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
_SS_DISABLE = 2
|
||||
_NSIG = 65
|
||||
_SI_USER = 0
|
||||
_SIG_BLOCK = 0
|
||||
_SIG_UNBLOCK = 1
|
||||
_SIG_SETMASK = 2
|
||||
_RLIMIT_AS = 9
|
||||
)
|
||||
|
||||
type sigset uint64
|
||||
|
||||
type rlimit struct {
|
||||
rlim_cur uintptr
|
||||
rlim_max uintptr
|
||||
}
|
||||
|
||||
var sigset_all = sigset(^uint64(0))
|
||||
|
||||
func sigaddset(mask *sigset, i int) {
|
||||
if i > 64 {
|
||||
throw("unexpected signal greater than 64")
|
||||
}
|
||||
*mask |= 1 << (uint(i) - 1)
|
||||
}
|
||||
|
||||
func sigdelset(mask *sigset, i int) {
|
||||
if i > 64 {
|
||||
throw("unexpected signal greater than 64")
|
||||
}
|
||||
*mask &^= 1 << (uint(i) - 1)
|
||||
}
|
||||
|
||||
func sigfillset(mask *uint64) {
|
||||
*mask = ^uint64(0)
|
||||
}
|
||||
|
||||
func sigcopyset(mask *sigset, m sigmask) {
|
||||
*mask = sigset(uint64(m[0]) | uint64(m[1])<<32)
|
||||
}
|
20
src/runtime/rt0_linux_s390x.s
Normal file
20
src/runtime/rt0_linux_s390x.s
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT _rt0_s390x_linux(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.
|
||||
//
|
||||
// TODO: Support dynamic linking entry point
|
||||
MOVD 0(R15), R2 // argc
|
||||
ADD $8, R15, R3 // argv
|
||||
BR main(SB)
|
||||
|
||||
TEXT main(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD $runtime·rt0_go(SB), R11
|
||||
BR R11
|
208
src/runtime/signal_linux_s390x.go
Normal file
208
src/runtime/signal_linux_s390x.go
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"runtime/internal/sys"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type sigctxt struct {
|
||||
info *siginfo
|
||||
ctxt unsafe.Pointer
|
||||
}
|
||||
|
||||
func (c *sigctxt) regs() *sigcontext {
|
||||
return (*sigcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
|
||||
}
|
||||
func (c *sigctxt) r0() uint64 { return c.regs().gregs[0] }
|
||||
func (c *sigctxt) r1() uint64 { return c.regs().gregs[1] }
|
||||
func (c *sigctxt) r2() uint64 { return c.regs().gregs[2] }
|
||||
func (c *sigctxt) r3() uint64 { return c.regs().gregs[3] }
|
||||
func (c *sigctxt) r4() uint64 { return c.regs().gregs[4] }
|
||||
func (c *sigctxt) r5() uint64 { return c.regs().gregs[5] }
|
||||
func (c *sigctxt) r6() uint64 { return c.regs().gregs[6] }
|
||||
func (c *sigctxt) r7() uint64 { return c.regs().gregs[7] }
|
||||
func (c *sigctxt) r8() uint64 { return c.regs().gregs[8] }
|
||||
func (c *sigctxt) r9() uint64 { return c.regs().gregs[9] }
|
||||
func (c *sigctxt) r10() uint64 { return c.regs().gregs[10] }
|
||||
func (c *sigctxt) r11() uint64 { return c.regs().gregs[11] }
|
||||
func (c *sigctxt) r12() uint64 { return c.regs().gregs[12] }
|
||||
func (c *sigctxt) r13() uint64 { return c.regs().gregs[13] }
|
||||
func (c *sigctxt) r14() uint64 { return c.regs().gregs[14] }
|
||||
func (c *sigctxt) r15() uint64 { return c.regs().gregs[15] }
|
||||
func (c *sigctxt) link() uint64 { return c.regs().gregs[14] }
|
||||
func (c *sigctxt) sp() uint64 { return c.regs().gregs[15] }
|
||||
func (c *sigctxt) pc() uint64 { return c.regs().psw_addr }
|
||||
func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
|
||||
func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
|
||||
|
||||
func (c *sigctxt) set_r0(x uint64) { c.regs().gregs[0] = x }
|
||||
func (c *sigctxt) set_r13(x uint64) { c.regs().gregs[13] = x }
|
||||
func (c *sigctxt) set_link(x uint64) { c.regs().gregs[14] = x }
|
||||
func (c *sigctxt) set_sp(x uint64) { c.regs().gregs[15] = x }
|
||||
func (c *sigctxt) set_pc(x uint64) { c.regs().psw_addr = 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*sys.PtrSize)) = uintptr(x)
|
||||
}
|
||||
|
||||
func dumpregs(c *sigctxt) {
|
||||
print("r0 ", hex(c.r0()), "\t")
|
||||
print("r1 ", hex(c.r1()), "\n")
|
||||
print("r2 ", hex(c.r2()), "\t")
|
||||
print("r3 ", hex(c.r3()), "\n")
|
||||
print("r4 ", hex(c.r4()), "\t")
|
||||
print("r5 ", hex(c.r5()), "\n")
|
||||
print("r6 ", hex(c.r6()), "\t")
|
||||
print("r7 ", hex(c.r7()), "\n")
|
||||
print("r8 ", hex(c.r8()), "\t")
|
||||
print("r9 ", hex(c.r9()), "\n")
|
||||
print("r10 ", hex(c.r10()), "\t")
|
||||
print("r11 ", hex(c.r11()), "\n")
|
||||
print("r12 ", hex(c.r12()), "\t")
|
||||
print("r13 ", hex(c.r13()), "\n")
|
||||
print("r14 ", hex(c.r14()), "\t")
|
||||
print("r15 ", hex(c.r15()), "\n")
|
||||
print("pc ", hex(c.pc()), "\t")
|
||||
print("link ", hex(c.link()), "\n")
|
||||
}
|
||||
|
||||
var crashing int32
|
||||
|
||||
// May run during STW, so write barriers are not allowed.
|
||||
//
|
||||
//go:nowritebarrierrec
|
||||
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.link()), 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.sigaddr())
|
||||
gp.sigpc = uintptr(c.pc())
|
||||
|
||||
// We arrange link, and pc to pretend the panicking
|
||||
// function calls sigpanic directly.
|
||||
// Always save LINK 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() - sys.MinFrameSize
|
||||
c.set_sp(sp)
|
||||
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
|
||||
|
||||
pc := uintptr(gp.sigpc)
|
||||
|
||||
// If we don't recognize the PC as code
|
||||
// but we do recognize the link register as code,
|
||||
// then assume this was a call to non-code and treat like
|
||||
// pc == 0, to make unwinding show the context.
|
||||
if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil {
|
||||
pc = 0
|
||||
}
|
||||
|
||||
// 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 pc != 0 {
|
||||
c.set_link(uint64(pc))
|
||||
}
|
||||
|
||||
// In case we are panicking from external C code
|
||||
c.set_r0(0)
|
||||
c.set_r13(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 c.sigcode() == _SI_USER && signal_ignored(sig) {
|
||||
return
|
||||
}
|
||||
|
||||
if flags&_SigKill != 0 {
|
||||
dieFromSignal(int32(sig))
|
||||
}
|
||||
|
||||
if flags&_SigThrow == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_g_.m.throwing = 1
|
||||
_g_.m.caughtsig.set(gp)
|
||||
|
||||
if crashing == 0 {
|
||||
startpanic()
|
||||
}
|
||||
|
||||
if sig < uint32(len(sigtable)) {
|
||||
print(sigtable[sig].name, "\n")
|
||||
} else {
|
||||
print("Signal ", sig, "\n")
|
||||
}
|
||||
|
||||
print("PC=", hex(c.pc()), " m=", _g_.m.id, "\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")
|
||||
|
||||
level, _, docrash := gotraceback()
|
||||
if level > 0 {
|
||||
goroutineheader(gp)
|
||||
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
|
||||
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
|
||||
// tracebackothers on original m skipped this one; trace it now.
|
||||
goroutineheader(_g_.m.curg)
|
||||
traceback(^uintptr(0), ^uintptr(0), 0, gp)
|
||||
} else if crashing == 0 {
|
||||
tracebackothers(gp)
|
||||
print("\n")
|
||||
}
|
||||
dumpregs(c)
|
||||
}
|
||||
|
||||
if docrash {
|
||||
crashing++
|
||||
if crashing < sched.mcount {
|
||||
// There are other m's that need to dump their stacks.
|
||||
// Relay SIGQUIT to the next m by sending it to the current process.
|
||||
// All m's that have already received SIGQUIT have signal masks blocking
|
||||
// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
|
||||
// When the last m receives the SIGQUIT, it will fall through to the call to
|
||||
// crash below. Just in case the relaying gets botched, each m involved in
|
||||
// the relay sleeps for 5 seconds and then does the crash/exit itself.
|
||||
// In expected operation, the last m has received the SIGQUIT and run
|
||||
// crash/exit and the process is gone, all long before any of the
|
||||
// 5-second sleeps have finished.
|
||||
print("\n-----\n\n")
|
||||
raiseproc(_SIGQUIT)
|
||||
usleep(5 * 1000 * 1000)
|
||||
}
|
||||
crash()
|
||||
}
|
||||
|
||||
exit(2)
|
||||
}
|
440
src/runtime/sys_linux_s390x.s
Normal file
440
src/runtime/sys_linux_s390x.s
Normal file
@ -0,0 +1,440 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// System calls and other system stuff for Linux s390x; see
|
||||
// /usr/include/asm/unistd.h for the syscall number definitions.
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "textflag.h"
|
||||
|
||||
#define SYS_exit 1
|
||||
#define SYS_read 3
|
||||
#define SYS_write 4
|
||||
#define SYS_open 5
|
||||
#define SYS_close 6
|
||||
#define SYS_getpid 20
|
||||
#define SYS_kill 37
|
||||
#define SYS_fcntl 55
|
||||
#define SYS_gettimeofday 78
|
||||
#define SYS_mmap 90
|
||||
#define SYS_munmap 91
|
||||
#define SYS_setitimer 104
|
||||
#define SYS_clone 120
|
||||
#define SYS_select 142
|
||||
#define SYS_sched_yield 158
|
||||
#define SYS_rt_sigreturn 173
|
||||
#define SYS_rt_sigaction 174
|
||||
#define SYS_rt_sigprocmask 175
|
||||
#define SYS_sigaltstack 186
|
||||
#define SYS_ugetrlimit 191
|
||||
#define SYS_madvise 219
|
||||
#define SYS_mincore 218
|
||||
#define SYS_gettid 236
|
||||
#define SYS_tkill 237
|
||||
#define SYS_futex 238
|
||||
#define SYS_sched_getaffinity 240
|
||||
#define SYS_exit_group 248
|
||||
#define SYS_epoll_create 249
|
||||
#define SYS_epoll_ctl 250
|
||||
#define SYS_epoll_wait 251
|
||||
#define SYS_clock_gettime 260
|
||||
#define SYS_epoll_create1 327
|
||||
|
||||
TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
|
||||
MOVW code+0(FP), R2
|
||||
MOVW $SYS_exit_group, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·exit1(SB),NOSPLIT|NOFRAME,$0-4
|
||||
MOVW code+0(FP), R2
|
||||
MOVW $SYS_exit, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
|
||||
MOVD name+0(FP), R2
|
||||
MOVW mode+8(FP), R3
|
||||
MOVW perm+12(FP), R4
|
||||
MOVW $SYS_open, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVW $-1, R2
|
||||
MOVW R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
|
||||
MOVW fd+0(FP), R2
|
||||
MOVW $SYS_close, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVW $-1, R2
|
||||
MOVW R2, ret+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·write(SB),NOSPLIT|NOFRAME,$0-28
|
||||
MOVD fd+0(FP), R2
|
||||
MOVD p+8(FP), R3
|
||||
MOVW n+16(FP), R4
|
||||
MOVW $SYS_write, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVW $-1, R2
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
|
||||
MOVW fd+0(FP), R2
|
||||
MOVD p+8(FP), R3
|
||||
MOVW n+16(FP), R4
|
||||
MOVW $SYS_read, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVW $-1, R2
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·getrlimit(SB),NOSPLIT|NOFRAME,$0-20
|
||||
MOVW kind+0(FP), R2
|
||||
MOVD limit+8(FP), R3
|
||||
MOVW $SYS_ugetrlimit, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+16(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·usleep(SB),NOSPLIT,$16-4
|
||||
MOVW usec+0(FP), R2
|
||||
MOVD R2, R4
|
||||
MOVW $1000000, R3
|
||||
DIVD R3, R2
|
||||
MOVD R2, 8(R15)
|
||||
MULLD R2, R3
|
||||
SUB R3, R4
|
||||
MOVD R4, 16(R15)
|
||||
|
||||
// select(0, 0, 0, 0, &tv)
|
||||
MOVW $0, R2
|
||||
MOVW $0, R3
|
||||
MOVW $0, R4
|
||||
MOVW $0, R5
|
||||
ADD $8, R15, R6
|
||||
MOVW $SYS_select, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·gettid(SB),NOSPLIT,$0-4
|
||||
MOVW $SYS_gettid, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW $SYS_gettid, R1
|
||||
SYSCALL
|
||||
MOVW R2, R2 // arg 1 tid
|
||||
MOVW sig+0(FP), R3 // arg 2
|
||||
MOVW $SYS_tkill, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW $SYS_getpid, R1
|
||||
SYSCALL
|
||||
MOVW R2, R2 // arg 1 pid
|
||||
MOVW sig+0(FP), R3 // arg 2
|
||||
MOVW $SYS_kill, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
|
||||
MOVW mode+0(FP), R2
|
||||
MOVD new+8(FP), R3
|
||||
MOVD old+16(FP), R4
|
||||
MOVW $SYS_setitimer, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
|
||||
MOVD addr+0(FP), R2
|
||||
MOVD n+8(FP), R3
|
||||
MOVD dst+16(FP), R4
|
||||
MOVW $SYS_mincore, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
// func now() (sec int64, nsec int32)
|
||||
TEXT time·now(SB),NOSPLIT,$16
|
||||
MOVD $0(R15), R2
|
||||
MOVD $0, R3
|
||||
MOVW $SYS_gettimeofday, R1
|
||||
SYSCALL
|
||||
MOVD 0(R15), R2 // sec
|
||||
MOVD 8(R15), R4 // usec
|
||||
MOVD $1000, R3
|
||||
MULLD R3, R4
|
||||
MOVD R2, sec+0(FP)
|
||||
MOVW R4, nsec+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·nanotime(SB),NOSPLIT,$16
|
||||
MOVW $1, R2 // CLOCK_MONOTONIC
|
||||
MOVD $0(R15), R3
|
||||
MOVW $SYS_clock_gettime, R1
|
||||
SYSCALL
|
||||
MOVD 0(R15), R2 // sec
|
||||
MOVD 8(R15), R4 // nsec
|
||||
// sec is in R2, nsec in R4
|
||||
// return nsec in R2
|
||||
MOVD $1000000000, R3
|
||||
MULLD R3, R2
|
||||
ADD R4, R2
|
||||
MOVD R2, ret+0(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
|
||||
MOVW sig+0(FP), R2
|
||||
MOVD new+8(FP), R3
|
||||
MOVD old+16(FP), R4
|
||||
MOVW size+24(FP), R5
|
||||
MOVW $SYS_rt_sigprocmask, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVD R0, 0(R0) // crash
|
||||
RET
|
||||
|
||||
TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
|
||||
MOVD sig+0(FP), R2
|
||||
MOVD new+8(FP), R3
|
||||
MOVD old+16(FP), R4
|
||||
MOVD size+24(FP), R5
|
||||
MOVW $SYS_rt_sigaction, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+32(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
|
||||
MOVW sig+8(FP), R2
|
||||
MOVD info+16(FP), R3
|
||||
MOVD ctx+24(FP), R4
|
||||
MOVD fn+0(FP), R5
|
||||
BL R5
|
||||
RET
|
||||
|
||||
TEXT runtime·sigtramp(SB),NOSPLIT,$64
|
||||
// initialize essential registers (just in case)
|
||||
XOR R0, R0
|
||||
|
||||
// this might be called in external code context,
|
||||
// where g is not set.
|
||||
MOVB runtime·iscgo(SB), R6
|
||||
CMPBEQ R6, $0, 2(PC)
|
||||
BL runtime·load_g(SB)
|
||||
|
||||
MOVW R2, 8(R15)
|
||||
MOVD R3, 16(R15)
|
||||
MOVD R4, 24(R15)
|
||||
MOVD $runtime·sigtrampgo(SB), R5
|
||||
BL R5
|
||||
RET
|
||||
|
||||
TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
|
||||
BR runtime·sigtramp(SB)
|
||||
|
||||
// func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
|
||||
TEXT runtime·mmap(SB),NOSPLIT,$48-40
|
||||
MOVD addr+0(FP), R2
|
||||
MOVD n+8(FP), R3
|
||||
MOVW prot+16(FP), R4
|
||||
MOVW flags+20(FP), R5
|
||||
MOVW fd+24(FP), R6
|
||||
MOVWZ off+28(FP), R7
|
||||
|
||||
// s390x uses old_mmap, so the arguments need to be placed into
|
||||
// a struct and a pointer to the struct passed to mmap.
|
||||
MOVD R2, addr-48(SP)
|
||||
MOVD R3, n-40(SP)
|
||||
MOVD R4, prot-32(SP)
|
||||
MOVD R5, flags-24(SP)
|
||||
MOVD R6, fd-16(SP)
|
||||
MOVD R7, off-8(SP)
|
||||
|
||||
MOVD $addr-48(SP), R2
|
||||
MOVW $SYS_mmap, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
NEG R2
|
||||
MOVD R2, ret+32(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD addr+0(FP), R2
|
||||
MOVD n+8(FP), R3
|
||||
MOVW $SYS_munmap, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVD R0, 0(R0) // crash
|
||||
RET
|
||||
|
||||
TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD addr+0(FP), R2
|
||||
MOVD n+8(FP), R3
|
||||
MOVW flags+16(FP), R4
|
||||
MOVW $SYS_madvise, R1
|
||||
SYSCALL
|
||||
// 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|NOFRAME,$0
|
||||
MOVD addr+0(FP), R2
|
||||
MOVW op+8(FP), R3
|
||||
MOVW val+12(FP), R4
|
||||
MOVD ts+16(FP), R5
|
||||
MOVD addr2+24(FP), R6
|
||||
MOVW val3+32(FP), R7
|
||||
MOVW $SYS_futex, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+40(FP)
|
||||
RET
|
||||
|
||||
// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
|
||||
TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW flags+0(FP), R3
|
||||
MOVD stk+8(FP), R2
|
||||
|
||||
// Copy mp, gp, fn off parent stack for use by child.
|
||||
// Careful: Linux system call clobbers ???.
|
||||
MOVD mm+16(FP), R7
|
||||
MOVD gg+24(FP), R8
|
||||
MOVD fn+32(FP), R9
|
||||
|
||||
MOVD R7, -8(R2)
|
||||
MOVD R8, -16(R2)
|
||||
MOVD R9, -24(R2)
|
||||
MOVD $1234, R7
|
||||
MOVD R7, -32(R2)
|
||||
|
||||
SYSCALL $SYS_clone
|
||||
|
||||
// In parent, return.
|
||||
CMPBEQ R2, $0, 3(PC)
|
||||
MOVW R2, ret+40(FP)
|
||||
RET
|
||||
|
||||
// In child, on new stack.
|
||||
// initialize essential registers
|
||||
XOR R0, R0
|
||||
MOVD -32(R15), R7
|
||||
CMP R7, $1234
|
||||
BEQ 2(PC)
|
||||
MOVD R0, 0(R0)
|
||||
|
||||
// Initialize m->procid to Linux tid
|
||||
SYSCALL $SYS_gettid
|
||||
|
||||
MOVD -24(R15), R9 // fn
|
||||
MOVD -16(R15), R8 // g
|
||||
MOVD -8(R15), R7 // m
|
||||
|
||||
CMPBEQ R7, $0, nog
|
||||
CMP R8, $0
|
||||
BEQ nog
|
||||
|
||||
MOVD R2, m_procid(R7)
|
||||
|
||||
// In child, set up new stack
|
||||
MOVD R7, g_m(R8)
|
||||
MOVD R8, g
|
||||
//CALL runtime·stackcheck(SB)
|
||||
|
||||
nog:
|
||||
// Call fn
|
||||
BL R9
|
||||
|
||||
// It shouldn't return. If it does, exit that thread.
|
||||
MOVW $111, R2
|
||||
MOVW $SYS_exit, R1
|
||||
SYSCALL
|
||||
BR -2(PC) // keep exiting
|
||||
|
||||
TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD new+0(FP), R2
|
||||
MOVD old+8(FP), R3
|
||||
MOVW $SYS_sigaltstack, R1
|
||||
SYSCALL
|
||||
MOVD $-4095, R3
|
||||
CMPUBLT R2, R3, 2(PC)
|
||||
MOVD R0, 0(R0) // crash
|
||||
RET
|
||||
|
||||
TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW $SYS_sched_yield, R1
|
||||
SYSCALL
|
||||
RET
|
||||
|
||||
TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVD pid+0(FP), R2
|
||||
MOVD len+8(FP), R3
|
||||
MOVD buf+16(FP), R4
|
||||
MOVW $SYS_sched_getaffinity, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollcreate(int32 size);
|
||||
TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW size+0(FP), R2
|
||||
MOVW $SYS_epoll_create, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+8(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollcreate1(int32 flags);
|
||||
TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW flags+0(FP), R2
|
||||
MOVW $SYS_epoll_create1, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+8(FP)
|
||||
RET
|
||||
|
||||
// func epollctl(epfd, op, fd int32, ev *epollEvent) int
|
||||
TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW epfd+0(FP), R2
|
||||
MOVW op+4(FP), R3
|
||||
MOVW fd+8(FP), R4
|
||||
MOVD ev+16(FP), R5
|
||||
MOVW $SYS_epoll_ctl, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
|
||||
TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW epfd+0(FP), R2
|
||||
MOVD ev+8(FP), R3
|
||||
MOVW nev+16(FP), R4
|
||||
MOVW timeout+20(FP), R5
|
||||
MOVW $SYS_epoll_wait, R1
|
||||
SYSCALL
|
||||
MOVW R2, ret+24(FP)
|
||||
RET
|
||||
|
||||
// void runtime·closeonexec(int32 fd);
|
||||
TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW fd+0(FP), R2 // fd
|
||||
MOVD $2, R3 // F_SETFD
|
||||
MOVD $1, R4 // FD_CLOEXEC
|
||||
MOVW $SYS_fcntl, R1
|
||||
SYSCALL
|
||||
RET
|
45
src/runtime/sys_s390x.go
Normal file
45
src/runtime/sys_s390x.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
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 uint64
|
||||
if buf.pc&1 == 0 && buf.pc != 0 {
|
||||
inst = *(*uint64)(unsafe.Pointer(buf.pc))
|
||||
switch inst >> 48 {
|
||||
case 0xa7f4: // BRC (branch relative on condition) instruction.
|
||||
inst >>= 32
|
||||
inst &= 0xFFFF
|
||||
offset := int64(int16(inst))
|
||||
offset <<= 1
|
||||
buf.pc += uintptr(offset)
|
||||
return
|
||||
case 0xc0f4: // BRCL (branch relative on condition long) instruction.
|
||||
inst >>= 16
|
||||
inst = inst & 0xFFFFFFFF
|
||||
inst = (inst << 1) & 0xFFFFFFFF
|
||||
buf.pc += uintptr(int32(inst))
|
||||
return
|
||||
}
|
||||
}
|
||||
print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
|
||||
throw("runtime: misuse of rewindmorestack")
|
||||
}
|
51
src/runtime/tls_s390x.s
Normal file
51
src/runtime/tls_s390x.s
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// We have to resort to TLS variable to save g (R13).
|
||||
// One reason is that external code might trigger
|
||||
// SIGSEGV, and our runtime.sigtramp don't even know we
|
||||
// are in external code, and will continue to use R13,
|
||||
// this might well result in another SIGSEGV.
|
||||
|
||||
// save_g saves the g register into pthread-provided
|
||||
// thread-local memory, so that we can call externally compiled
|
||||
// s390x code that will overwrite this register.
|
||||
//
|
||||
// If !iscgo, this is a no-op.
|
||||
//
|
||||
// NOTE: setg_gcc<> assume this clobbers only R10 and R11.
|
||||
TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOVB runtime·iscgo(SB), R10
|
||||
CMPBEQ R10, $0, nocgo
|
||||
MOVW AR0, R11
|
||||
SLD $32, R11
|
||||
MOVW AR1, R11
|
||||
MOVD runtime·tls_g(SB), R10
|
||||
MOVD g, 0(R10)(R11*1)
|
||||
nocgo:
|
||||
RET
|
||||
|
||||
// load_g loads the g register from pthread-provided
|
||||
// thread-local memory, for use after calling externally compiled
|
||||
// s390x code that overwrote those registers.
|
||||
//
|
||||
// This is never called directly from C code (it doesn't have to
|
||||
// follow the C ABI), but it may be called from a C context, where the
|
||||
// usual Go registers aren't set up.
|
||||
//
|
||||
// NOTE: _cgo_topofstack assumes this only clobbers g (R13), R10 and R11.
|
||||
TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOVW AR0, R11
|
||||
SLD $32, R11
|
||||
MOVW AR1, R11
|
||||
MOVD runtime·tls_g(SB), R10
|
||||
MOVD 0(R10)(R11*1), g
|
||||
RET
|
||||
|
||||
GLOBL runtime·tls_g+0(SB),TLSBSS,$8
|
Loading…
Reference in New Issue
Block a user