Home | History | Annotate | Download | only in runtime
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // System calls and other system stuff for Linux s390x; see
      6 // /usr/include/asm/unistd.h for the syscall number definitions.
      7 
      8 #include "go_asm.h"
      9 #include "go_tls.h"
     10 #include "textflag.h"
     11 
     12 #define SYS_exit                  1
     13 #define SYS_read                  3
     14 #define SYS_write                 4
     15 #define SYS_open                  5
     16 #define SYS_close                 6
     17 #define SYS_getpid               20
     18 #define SYS_kill                 37
     19 #define SYS_brk			 45
     20 #define SYS_fcntl                55
     21 #define SYS_gettimeofday         78
     22 #define SYS_mmap                 90
     23 #define SYS_munmap               91
     24 #define SYS_setitimer           104
     25 #define SYS_clone               120
     26 #define SYS_select              142
     27 #define SYS_sched_yield         158
     28 #define SYS_rt_sigreturn        173
     29 #define SYS_rt_sigaction        174
     30 #define SYS_rt_sigprocmask      175
     31 #define SYS_sigaltstack         186
     32 #define SYS_ugetrlimit          191
     33 #define SYS_madvise             219
     34 #define SYS_mincore             218
     35 #define SYS_gettid              236
     36 #define SYS_tkill               237
     37 #define SYS_futex               238
     38 #define SYS_sched_getaffinity   240
     39 #define SYS_exit_group          248
     40 #define SYS_epoll_create        249
     41 #define SYS_epoll_ctl           250
     42 #define SYS_epoll_wait          251
     43 #define SYS_clock_gettime       260
     44 #define SYS_epoll_create1       327
     45 
     46 TEXT runtimeexit(SB),NOSPLIT|NOFRAME,$0-4
     47 	MOVW	code+0(FP), R2
     48 	MOVW	$SYS_exit_group, R1
     49 	SYSCALL
     50 	RET
     51 
     52 // func exitThread(wait *uint32)
     53 TEXT runtimeexitThread(SB),NOSPLIT|NOFRAME,$0-8
     54 	MOVD	wait+0(FP), R1
     55 	// We're done using the stack.
     56 	MOVW	$0, R2
     57 	MOVW	R2, (R1)
     58 	MOVW	$0, R2	// exit code
     59 	MOVW	$SYS_exit, R1
     60 	SYSCALL
     61 	JMP	0(PC)
     62 
     63 TEXT runtimeopen(SB),NOSPLIT|NOFRAME,$0-20
     64 	MOVD	name+0(FP), R2
     65 	MOVW	mode+8(FP), R3
     66 	MOVW	perm+12(FP), R4
     67 	MOVW	$SYS_open, R1
     68 	SYSCALL
     69 	MOVD	$-4095, R3
     70 	CMPUBLT	R2, R3, 2(PC)
     71 	MOVW	$-1, R2
     72 	MOVW	R2, ret+16(FP)
     73 	RET
     74 
     75 TEXT runtimeclosefd(SB),NOSPLIT|NOFRAME,$0-12
     76 	MOVW	fd+0(FP), R2
     77 	MOVW	$SYS_close, R1
     78 	SYSCALL
     79 	MOVD	$-4095, R3
     80 	CMPUBLT	R2, R3, 2(PC)
     81 	MOVW	$-1, R2
     82 	MOVW	R2, ret+8(FP)
     83 	RET
     84 
     85 TEXT runtimewrite(SB),NOSPLIT|NOFRAME,$0-28
     86 	MOVD	fd+0(FP), R2
     87 	MOVD	p+8(FP), R3
     88 	MOVW	n+16(FP), R4
     89 	MOVW	$SYS_write, R1
     90 	SYSCALL
     91 	MOVD	$-4095, R3
     92 	CMPUBLT	R2, R3, 2(PC)
     93 	MOVW	$-1, R2
     94 	MOVW	R2, ret+24(FP)
     95 	RET
     96 
     97 TEXT runtimeread(SB),NOSPLIT|NOFRAME,$0-28
     98 	MOVW	fd+0(FP), R2
     99 	MOVD	p+8(FP), R3
    100 	MOVW	n+16(FP), R4
    101 	MOVW	$SYS_read, R1
    102 	SYSCALL
    103 	MOVD	$-4095, R3
    104 	CMPUBLT	R2, R3, 2(PC)
    105 	MOVW	$-1, R2
    106 	MOVW	R2, ret+24(FP)
    107 	RET
    108 
    109 TEXT runtimegetrlimit(SB),NOSPLIT|NOFRAME,$0-20
    110 	MOVW	kind+0(FP), R2
    111 	MOVD	limit+8(FP), R3
    112 	MOVW	$SYS_ugetrlimit, R1
    113 	SYSCALL
    114 	MOVW	R2, ret+16(FP)
    115 	RET
    116 
    117 TEXT runtimeusleep(SB),NOSPLIT,$16-4
    118 	MOVW	usec+0(FP), R2
    119 	MOVD	R2, R4
    120 	MOVW	$1000000, R3
    121 	DIVD	R3, R2
    122 	MOVD	R2, 8(R15)
    123 	MULLD	R2, R3
    124 	SUB	R3, R4
    125 	MOVD	R4, 16(R15)
    126 
    127 	// select(0, 0, 0, 0, &tv)
    128 	MOVW	$0, R2
    129 	MOVW	$0, R3
    130 	MOVW	$0, R4
    131 	MOVW	$0, R5
    132 	ADD	$8, R15, R6
    133 	MOVW	$SYS_select, R1
    134 	SYSCALL
    135 	RET
    136 
    137 TEXT runtimegettid(SB),NOSPLIT,$0-4
    138 	MOVW	$SYS_gettid, R1
    139 	SYSCALL
    140 	MOVW	R2, ret+0(FP)
    141 	RET
    142 
    143 TEXT runtimeraise(SB),NOSPLIT|NOFRAME,$0
    144 	MOVW	$SYS_gettid, R1
    145 	SYSCALL
    146 	MOVW	R2, R2	// arg 1 tid
    147 	MOVW	sig+0(FP), R3	// arg 2
    148 	MOVW	$SYS_tkill, R1
    149 	SYSCALL
    150 	RET
    151 
    152 TEXT runtimeraiseproc(SB),NOSPLIT|NOFRAME,$0
    153 	MOVW	$SYS_getpid, R1
    154 	SYSCALL
    155 	MOVW	R2, R2	// arg 1 pid
    156 	MOVW	sig+0(FP), R3	// arg 2
    157 	MOVW	$SYS_kill, R1
    158 	SYSCALL
    159 	RET
    160 
    161 TEXT runtimesetitimer(SB),NOSPLIT|NOFRAME,$0-24
    162 	MOVW	mode+0(FP), R2
    163 	MOVD	new+8(FP), R3
    164 	MOVD	old+16(FP), R4
    165 	MOVW	$SYS_setitimer, R1
    166 	SYSCALL
    167 	RET
    168 
    169 TEXT runtimemincore(SB),NOSPLIT|NOFRAME,$0-28
    170 	MOVD	addr+0(FP), R2
    171 	MOVD	n+8(FP), R3
    172 	MOVD	dst+16(FP), R4
    173 	MOVW	$SYS_mincore, R1
    174 	SYSCALL
    175 	MOVW	R2, ret+24(FP)
    176 	RET
    177 
    178 // func walltime() (sec int64, nsec int32)
    179 TEXT runtimewalltime(SB),NOSPLIT,$16
    180 	MOVW	$0, R2 // CLOCK_REALTIME
    181 	MOVD	$tp-16(SP), R3
    182 	MOVW	$SYS_clock_gettime, R1
    183 	SYSCALL
    184 	LMG	tp-16(SP), R2, R3
    185 	// sec is in R2, nsec in R3
    186 	MOVD	R2, sec+0(FP)
    187 	MOVW	R3, nsec+8(FP)
    188 	RET
    189 
    190 TEXT runtimenanotime(SB),NOSPLIT,$16
    191 	MOVW	$1, R2 // CLOCK_MONOTONIC
    192 	MOVD	$tp-16(SP), R3
    193 	MOVW	$SYS_clock_gettime, R1
    194 	SYSCALL
    195 	LMG	tp-16(SP), R2, R3
    196 	// sec is in R2, nsec in R3
    197 	// return nsec in R2
    198 	MULLD	$1000000000, R2
    199 	ADD	R3, R2
    200 	MOVD	R2, ret+0(FP)
    201 	RET
    202 
    203 TEXT runtimertsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
    204 	MOVW	how+0(FP), R2
    205 	MOVD	new+8(FP), R3
    206 	MOVD	old+16(FP), R4
    207 	MOVW	size+24(FP), R5
    208 	MOVW	$SYS_rt_sigprocmask, R1
    209 	SYSCALL
    210 	MOVD	$-4095, R3
    211 	CMPUBLT	R2, R3, 2(PC)
    212 	MOVD	R0, 0(R0) // crash
    213 	RET
    214 
    215 TEXT runtimert_sigaction(SB),NOSPLIT|NOFRAME,$0-36
    216 	MOVD	sig+0(FP), R2
    217 	MOVD	new+8(FP), R3
    218 	MOVD	old+16(FP), R4
    219 	MOVD	size+24(FP), R5
    220 	MOVW	$SYS_rt_sigaction, R1
    221 	SYSCALL
    222 	MOVW	R2, ret+32(FP)
    223 	RET
    224 
    225 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    226 	MOVW	sig+8(FP), R2
    227 	MOVD	info+16(FP), R3
    228 	MOVD	ctx+24(FP), R4
    229 	MOVD	fn+0(FP), R5
    230 	BL	R5
    231 	RET
    232 
    233 TEXT runtimesigtramp(SB),NOSPLIT,$64
    234 	// initialize essential registers (just in case)
    235 	XOR	R0, R0
    236 
    237 	// this might be called in external code context,
    238 	// where g is not set.
    239 	MOVB	runtimeiscgo(SB), R6
    240 	CMPBEQ	R6, $0, 2(PC)
    241 	BL	runtimeload_g(SB)
    242 
    243 	MOVW	R2, 8(R15)
    244 	MOVD	R3, 16(R15)
    245 	MOVD	R4, 24(R15)
    246 	MOVD	$runtimesigtrampgo(SB), R5
    247 	BL	R5
    248 	RET
    249 
    250 TEXT runtimecgoSigtramp(SB),NOSPLIT,$0
    251 	BR	runtimesigtramp(SB)
    252 
    253 // func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
    254 TEXT runtimemmap(SB),NOSPLIT,$48-48
    255 	MOVD	addr+0(FP), R2
    256 	MOVD	n+8(FP), R3
    257 	MOVW	prot+16(FP), R4
    258 	MOVW	flags+20(FP), R5
    259 	MOVW	fd+24(FP), R6
    260 	MOVWZ	off+28(FP), R7
    261 
    262 	// s390x uses old_mmap, so the arguments need to be placed into
    263 	// a struct and a pointer to the struct passed to mmap.
    264 	MOVD	R2, addr-48(SP)
    265 	MOVD	R3, n-40(SP)
    266 	MOVD	R4, prot-32(SP)
    267 	MOVD	R5, flags-24(SP)
    268 	MOVD	R6, fd-16(SP)
    269 	MOVD	R7, off-8(SP)
    270 
    271 	MOVD	$addr-48(SP), R2
    272 	MOVW	$SYS_mmap, R1
    273 	SYSCALL
    274 	MOVD	$-4095, R3
    275 	CMPUBLT	R2, R3, ok
    276 	NEG	R2
    277 	MOVD	$0, p+32(FP)
    278 	MOVD	R2, err+40(FP)
    279 	RET
    280 ok:
    281 	MOVD	R2, p+32(FP)
    282 	MOVD	$0, err+40(FP)
    283 	RET
    284 
    285 TEXT runtimemunmap(SB),NOSPLIT|NOFRAME,$0
    286 	MOVD	addr+0(FP), R2
    287 	MOVD	n+8(FP), R3
    288 	MOVW	$SYS_munmap, R1
    289 	SYSCALL
    290 	MOVD	$-4095, R3
    291 	CMPUBLT	R2, R3, 2(PC)
    292 	MOVD	R0, 0(R0) // crash
    293 	RET
    294 
    295 TEXT runtimemadvise(SB),NOSPLIT|NOFRAME,$0
    296 	MOVD	addr+0(FP), R2
    297 	MOVD	n+8(FP), R3
    298 	MOVW	flags+16(FP), R4
    299 	MOVW	$SYS_madvise, R1
    300 	SYSCALL
    301 	// ignore failure - maybe pages are locked
    302 	RET
    303 
    304 // int64 futex(int32 *uaddr, int32 op, int32 val,
    305 //	struct timespec *timeout, int32 *uaddr2, int32 val2);
    306 TEXT runtimefutex(SB),NOSPLIT|NOFRAME,$0
    307 	MOVD	addr+0(FP), R2
    308 	MOVW	op+8(FP), R3
    309 	MOVW	val+12(FP), R4
    310 	MOVD	ts+16(FP), R5
    311 	MOVD	addr2+24(FP), R6
    312 	MOVW	val3+32(FP),  R7
    313 	MOVW	$SYS_futex, R1
    314 	SYSCALL
    315 	MOVW	R2, ret+40(FP)
    316 	RET
    317 
    318 // int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
    319 TEXT runtimeclone(SB),NOSPLIT|NOFRAME,$0
    320 	MOVW	flags+0(FP), R3
    321 	MOVD	stk+8(FP), R2
    322 
    323 	// Copy mp, gp, fn off parent stack for use by child.
    324 	// Careful: Linux system call clobbers ???.
    325 	MOVD	mp+16(FP), R7
    326 	MOVD	gp+24(FP), R8
    327 	MOVD	fn+32(FP), R9
    328 
    329 	MOVD	R7, -8(R2)
    330 	MOVD	R8, -16(R2)
    331 	MOVD	R9, -24(R2)
    332 	MOVD	$1234, R7
    333 	MOVD	R7, -32(R2)
    334 
    335 	SYSCALL $SYS_clone
    336 
    337 	// In parent, return.
    338 	CMPBEQ	R2, $0, 3(PC)
    339 	MOVW	R2, ret+40(FP)
    340 	RET
    341 
    342 	// In child, on new stack.
    343 	// initialize essential registers
    344 	XOR	R0, R0
    345 	MOVD	-32(R15), R7
    346 	CMP	R7, $1234
    347 	BEQ	2(PC)
    348 	MOVD	R0, 0(R0)
    349 
    350 	// Initialize m->procid to Linux tid
    351 	SYSCALL $SYS_gettid
    352 
    353 	MOVD	-24(R15), R9        // fn
    354 	MOVD	-16(R15), R8        // g
    355 	MOVD	-8(R15), R7         // m
    356 
    357 	CMPBEQ	R7, $0, nog
    358 	CMP	R8, $0
    359 	BEQ	nog
    360 
    361 	MOVD	R2, m_procid(R7)
    362 
    363 	// In child, set up new stack
    364 	MOVD	R7, g_m(R8)
    365 	MOVD	R8, g
    366 	//CALL	runtimestackcheck(SB)
    367 
    368 nog:
    369 	// Call fn
    370 	BL	R9
    371 
    372 	// It shouldn't return.	 If it does, exit that thread.
    373 	MOVW	$111, R2
    374 	MOVW	$SYS_exit, R1
    375 	SYSCALL
    376 	BR	-2(PC)	// keep exiting
    377 
    378 TEXT runtimesigaltstack(SB),NOSPLIT|NOFRAME,$0
    379 	MOVD	new+0(FP), R2
    380 	MOVD	old+8(FP), R3
    381 	MOVW	$SYS_sigaltstack, R1
    382 	SYSCALL
    383 	MOVD	$-4095, R3
    384 	CMPUBLT	R2, R3, 2(PC)
    385 	MOVD	R0, 0(R0) // crash
    386 	RET
    387 
    388 TEXT runtimeosyield(SB),NOSPLIT|NOFRAME,$0
    389 	MOVW	$SYS_sched_yield, R1
    390 	SYSCALL
    391 	RET
    392 
    393 TEXT runtimesched_getaffinity(SB),NOSPLIT|NOFRAME,$0
    394 	MOVD	pid+0(FP), R2
    395 	MOVD	len+8(FP), R3
    396 	MOVD	buf+16(FP), R4
    397 	MOVW	$SYS_sched_getaffinity, R1
    398 	SYSCALL
    399 	MOVW	R2, ret+24(FP)
    400 	RET
    401 
    402 // int32 runtimeepollcreate(int32 size);
    403 TEXT runtimeepollcreate(SB),NOSPLIT|NOFRAME,$0
    404 	MOVW    size+0(FP), R2
    405 	MOVW	$SYS_epoll_create, R1
    406 	SYSCALL
    407 	MOVW	R2, ret+8(FP)
    408 	RET
    409 
    410 // int32 runtimeepollcreate1(int32 flags);
    411 TEXT runtimeepollcreate1(SB),NOSPLIT|NOFRAME,$0
    412 	MOVW	flags+0(FP), R2
    413 	MOVW	$SYS_epoll_create1, R1
    414 	SYSCALL
    415 	MOVW	R2, ret+8(FP)
    416 	RET
    417 
    418 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
    419 TEXT runtimeepollctl(SB),NOSPLIT|NOFRAME,$0
    420 	MOVW	epfd+0(FP), R2
    421 	MOVW	op+4(FP), R3
    422 	MOVW	fd+8(FP), R4
    423 	MOVD	ev+16(FP), R5
    424 	MOVW	$SYS_epoll_ctl, R1
    425 	SYSCALL
    426 	MOVW	R2, ret+24(FP)
    427 	RET
    428 
    429 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
    430 TEXT runtimeepollwait(SB),NOSPLIT|NOFRAME,$0
    431 	MOVW	epfd+0(FP), R2
    432 	MOVD	ev+8(FP), R3
    433 	MOVW	nev+16(FP), R4
    434 	MOVW	timeout+20(FP), R5
    435 	MOVW	$SYS_epoll_wait, R1
    436 	SYSCALL
    437 	MOVW	R2, ret+24(FP)
    438 	RET
    439 
    440 // void runtimecloseonexec(int32 fd);
    441 TEXT runtimecloseonexec(SB),NOSPLIT|NOFRAME,$0
    442 	MOVW    fd+0(FP), R2  // fd
    443 	MOVD    $2, R3  // F_SETFD
    444 	MOVD    $1, R4  // FD_CLOEXEC
    445 	MOVW	$SYS_fcntl, R1
    446 	SYSCALL
    447 	RET
    448 
    449 // func sbrk0() uintptr
    450 TEXT runtimesbrk0(SB),NOSPLIT|NOFRAME,$0-8
    451 	// Implemented as brk(NULL).
    452 	MOVD	$0, R2
    453 	MOVW	$SYS_brk, R1
    454 	SYSCALL
    455 	MOVD	R2, ret+0(FP)
    456 	RET
    457