Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 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 // +build linux
      6 // +build ppc64 ppc64le
      7 
      8 //
      9 // System calls and other sys.stuff for ppc64, Linux
     10 //
     11 
     12 #include "go_asm.h"
     13 #include "go_tls.h"
     14 #include "textflag.h"
     15 #include "asm_ppc64x.h"
     16 
     17 #define SYS_exit		  1
     18 #define SYS_read		  3
     19 #define SYS_write		  4
     20 #define SYS_open		  5
     21 #define SYS_close		  6
     22 #define SYS_getpid		 20
     23 #define SYS_kill		 37
     24 #define SYS_brk			 45
     25 #define SYS_fcntl		 55
     26 #define SYS_gettimeofday	 78
     27 #define SYS_select		 82	// always return -ENOSYS
     28 #define SYS_mmap		 90
     29 #define SYS_munmap		 91
     30 #define SYS_setitimer		104
     31 #define SYS_clone		120
     32 #define SYS_newselect		142
     33 #define SYS_sched_yield		158
     34 #define SYS_rt_sigreturn	172
     35 #define SYS_rt_sigaction	173
     36 #define SYS_rt_sigprocmask	174
     37 #define SYS_sigaltstack		185
     38 #define SYS_ugetrlimit		190
     39 #define SYS_madvise		205
     40 #define SYS_mincore		206
     41 #define SYS_gettid		207
     42 #define SYS_tkill		208
     43 #define SYS_futex		221
     44 #define SYS_sched_getaffinity	223
     45 #define SYS_exit_group		234
     46 #define SYS_epoll_create	236
     47 #define SYS_epoll_ctl		237
     48 #define SYS_epoll_wait		238
     49 #define SYS_clock_gettime	246
     50 #define SYS_epoll_create1	315
     51 
     52 TEXT runtimeexit(SB),NOSPLIT|NOFRAME,$0-4
     53 	MOVW	code+0(FP), R3
     54 	SYSCALL	$SYS_exit_group
     55 	RET
     56 
     57 // func exitThread(wait *uint32)
     58 TEXT runtimeexitThread(SB),NOSPLIT|NOFRAME,$0-8
     59 	MOVD	wait+0(FP), R1
     60 	// We're done using the stack.
     61 	MOVW	$0, R2
     62 	SYNC
     63 	MOVW	R2, (R1)
     64 	MOVW	$0, R3	// exit code
     65 	SYSCALL	$SYS_exit
     66 	JMP	0(PC)
     67 
     68 TEXT runtimeopen(SB),NOSPLIT|NOFRAME,$0-20
     69 	MOVD	name+0(FP), R3
     70 	MOVW	mode+8(FP), R4
     71 	MOVW	perm+12(FP), R5
     72 	SYSCALL	$SYS_open
     73 	BVC	2(PC)
     74 	MOVW	$-1, R3
     75 	MOVW	R3, ret+16(FP)
     76 	RET
     77 
     78 TEXT runtimeclosefd(SB),NOSPLIT|NOFRAME,$0-12
     79 	MOVW	fd+0(FP), R3
     80 	SYSCALL	$SYS_close
     81 	BVC	2(PC)
     82 	MOVW	$-1, R3
     83 	MOVW	R3, ret+8(FP)
     84 	RET
     85 
     86 TEXT runtimewrite(SB),NOSPLIT|NOFRAME,$0-28
     87 	MOVD	fd+0(FP), R3
     88 	MOVD	p+8(FP), R4
     89 	MOVW	n+16(FP), R5
     90 	SYSCALL	$SYS_write
     91 	BVC	2(PC)
     92 	MOVW	$-1, R3
     93 	MOVW	R3, ret+24(FP)
     94 	RET
     95 
     96 TEXT runtimeread(SB),NOSPLIT|NOFRAME,$0-28
     97 	MOVW	fd+0(FP), R3
     98 	MOVD	p+8(FP), R4
     99 	MOVW	n+16(FP), R5
    100 	SYSCALL	$SYS_read
    101 	BVC	2(PC)
    102 	MOVW	$-1, R3
    103 	MOVW	R3, ret+24(FP)
    104 	RET
    105 
    106 TEXT runtimegetrlimit(SB),NOSPLIT|NOFRAME,$0-20
    107 	MOVW	kind+0(FP), R3
    108 	MOVD	limit+8(FP), R4
    109 	SYSCALL	$SYS_ugetrlimit
    110 	MOVW	R3, ret+16(FP)
    111 	RET
    112 
    113 TEXT runtimeusleep(SB),NOSPLIT,$16-4
    114 	MOVW	usec+0(FP), R3
    115 	MOVD	R3, R5
    116 	MOVW	$1000000, R4
    117 	DIVD	R4, R3
    118 	MOVD	R3, 8(R1)
    119 	MULLD	R3, R4
    120 	SUB	R4, R5
    121 	MOVD	R5, 16(R1)
    122 
    123 	// select(0, 0, 0, 0, &tv)
    124 	MOVW	$0, R3
    125 	MOVW	$0, R4
    126 	MOVW	$0, R5
    127 	MOVW	$0, R6
    128 	ADD	$8, R1, R7
    129 	SYSCALL	$SYS_newselect
    130 	RET
    131 
    132 TEXT runtimegettid(SB),NOSPLIT,$0-4
    133 	SYSCALL	$SYS_gettid
    134 	MOVW	R3, ret+0(FP)
    135 	RET
    136 
    137 TEXT runtimeraise(SB),NOSPLIT|NOFRAME,$0
    138 	SYSCALL	$SYS_gettid
    139 	MOVW	R3, R3	// arg 1 tid
    140 	MOVW	sig+0(FP), R4	// arg 2
    141 	SYSCALL	$SYS_tkill
    142 	RET
    143 
    144 TEXT runtimeraiseproc(SB),NOSPLIT|NOFRAME,$0
    145 	SYSCALL	$SYS_getpid
    146 	MOVW	R3, R3	// arg 1 pid
    147 	MOVW	sig+0(FP), R4	// arg 2
    148 	SYSCALL	$SYS_kill
    149 	RET
    150 
    151 TEXT runtimesetitimer(SB),NOSPLIT|NOFRAME,$0-24
    152 	MOVW	mode+0(FP), R3
    153 	MOVD	new+8(FP), R4
    154 	MOVD	old+16(FP), R5
    155 	SYSCALL	$SYS_setitimer
    156 	RET
    157 
    158 TEXT runtimemincore(SB),NOSPLIT|NOFRAME,$0-28
    159 	MOVD	addr+0(FP), R3
    160 	MOVD	n+8(FP), R4
    161 	MOVD	dst+16(FP), R5
    162 	SYSCALL	$SYS_mincore
    163 	NEG	R3		// caller expects negative errno
    164 	MOVW	R3, ret+24(FP)
    165 	RET
    166 
    167 // func walltime() (sec int64, nsec int32)
    168 TEXT runtimewalltime(SB),NOSPLIT,$16
    169 	MOVD	$0, R3 // CLOCK_REALTIME
    170 	MOVD	$0(R1), R4
    171 	SYSCALL	$SYS_clock_gettime
    172 	MOVD	0(R1), R3	// sec
    173 	MOVD	8(R1), R5	// nsec
    174 	MOVD	R3, sec+0(FP)
    175 	MOVW	R5, nsec+8(FP)
    176 	RET
    177 
    178 TEXT runtimenanotime(SB),NOSPLIT,$16
    179 	MOVW	$1, R3 // CLOCK_MONOTONIC
    180 	MOVD	$0(R1), R4
    181 	SYSCALL	$SYS_clock_gettime
    182 	MOVD	0(R1), R3	// sec
    183 	MOVD	8(R1), R5	// nsec
    184 	// sec is in R3, nsec in R5
    185 	// return nsec in R3
    186 	MOVD	$1000000000, R4
    187 	MULLD	R4, R3
    188 	ADD	R5, R3
    189 	MOVD	R3, ret+0(FP)
    190 	RET
    191 
    192 TEXT runtimertsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
    193 	MOVW	how+0(FP), R3
    194 	MOVD	new+8(FP), R4
    195 	MOVD	old+16(FP), R5
    196 	MOVW	size+24(FP), R6
    197 	SYSCALL	$SYS_rt_sigprocmask
    198 	BVC	2(PC)
    199 	MOVD	R0, 0xf0(R0)	// crash
    200 	RET
    201 
    202 TEXT runtimert_sigaction(SB),NOSPLIT|NOFRAME,$0-36
    203 	MOVD	sig+0(FP), R3
    204 	MOVD	new+8(FP), R4
    205 	MOVD	old+16(FP), R5
    206 	MOVD	size+24(FP), R6
    207 	SYSCALL	$SYS_rt_sigaction
    208 	MOVW	R3, ret+32(FP)
    209 	RET
    210 
    211 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    212 	MOVW	sig+8(FP), R3
    213 	MOVD	info+16(FP), R4
    214 	MOVD	ctx+24(FP), R5
    215 	MOVD	fn+0(FP), R12
    216 	MOVD	R12, CTR
    217 	BL	(CTR)
    218 	MOVD	24(R1), R2
    219 	RET
    220 
    221 #ifdef GOARCH_ppc64le
    222 // ppc64le doesn't need function descriptors
    223 TEXT runtimesigtramp(SB),NOSPLIT,$64
    224 #else
    225 // function descriptor for the real sigtramp
    226 TEXT runtimesigtramp(SB),NOSPLIT|NOFRAME,$0
    227 	DWORD	$runtime_sigtramp(SB)
    228 	DWORD	$0
    229 	DWORD	$0
    230 TEXT runtime_sigtramp(SB),NOSPLIT,$64
    231 #endif
    232 	// initialize essential registers (just in case)
    233 	BL	runtimereginit(SB)
    234 
    235 	// this might be called in external code context,
    236 	// where g is not set.
    237 	MOVB	runtimeiscgo(SB), R6
    238 	CMP 	R6, $0
    239 	BEQ	2(PC)
    240 	BL	runtimeload_g(SB)
    241 
    242 	MOVW	R3, FIXED_FRAME+0(R1)
    243 	MOVD	R4, FIXED_FRAME+8(R1)
    244 	MOVD	R5, FIXED_FRAME+16(R1)
    245 	MOVD	$runtimesigtrampgo(SB), R12
    246 	MOVD	R12, CTR
    247 	BL	(CTR)
    248 	MOVD	24(R1), R2
    249 	RET
    250 
    251 #ifdef GOARCH_ppc64le
    252 // ppc64le doesn't need function descriptors
    253 TEXT runtimecgoSigtramp(SB),NOSPLIT|NOFRAME,$0
    254 	// The stack unwinder, presumably written in C, may not be able to
    255 	// handle Go frame correctly. So, this function is NOFRAME, and we
    256 	// we save/restore LR manually.
    257 	MOVD	LR, R10
    258 
    259 	// We're coming from C code, initialize essential registers.
    260 	CALL	runtimereginit(SB)
    261 
    262 	// If no traceback function, do usual sigtramp.
    263 	MOVD	runtimecgoTraceback(SB), R6
    264 	CMP	$0, R6
    265 	BEQ	sigtramp
    266 
    267 	// If no traceback support function, which means that
    268 	// runtime/cgo was not linked in, do usual sigtramp.
    269 	MOVD	_cgo_callers(SB), R6
    270 	CMP	$0, R6
    271 	BEQ	sigtramp
    272 
    273 	// Set up g register.
    274 	CALL	runtimeload_g(SB)
    275 
    276 	// Figure out if we are currently in a cgo call.
    277 	// If not, just do usual sigtramp.
    278 	CMP	$0, g
    279 	BEQ	sigtrampnog // g == nil
    280 	MOVD	g_m(g), R6
    281 	CMP	$0, R6
    282 	BEQ	sigtramp    // g.m == nil
    283 	MOVW	m_ncgo(R6), R7
    284 	CMPW	$0, R7
    285 	BEQ	sigtramp    // g.m.ncgo = 0
    286 	MOVD	m_curg(R6), R7
    287 	CMP	$0, R7
    288 	BEQ	sigtramp    // g.m.curg == nil
    289 	MOVD	g_syscallsp(R7), R7
    290 	CMP	$0, R7
    291 	BEQ	sigtramp    // g.m.curg.syscallsp == 0
    292 	MOVD	m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention.
    293 	CMP	$0, R7
    294 	BEQ	sigtramp    // g.m.cgoCallers == nil
    295 	MOVW	m_cgoCallersUse(R6), R8
    296 	CMPW	$0, R8
    297 	BNE	sigtramp    // g.m.cgoCallersUse != 0
    298 
    299 	// Jump to a function in runtime/cgo.
    300 	// That function, written in C, will call the user's traceback
    301 	// function with proper unwind info, and will then call back here.
    302 	// The first three arguments, and the fifth, are already in registers.
    303 	// Set the two remaining arguments now.
    304 	MOVD	runtimecgoTraceback(SB), R6
    305 	MOVD	$runtimesigtramp(SB), R8
    306 	MOVD	_cgo_callers(SB), R12
    307 	MOVD	R12, CTR
    308 	MOVD	R10, LR // restore LR
    309 	JMP	(CTR)
    310 
    311 sigtramp:
    312 	MOVD	R10, LR // restore LR
    313 	JMP	runtimesigtramp(SB)
    314 
    315 sigtrampnog:
    316 	// Signal arrived on a non-Go thread. If this is SIGPROF, get a
    317 	// stack trace.
    318 	CMPW	R3, $27 // 27 == SIGPROF
    319 	BNE	sigtramp
    320 
    321 	// Lock sigprofCallersUse (cas from 0 to 1).
    322 	MOVW	$1, R7
    323 	MOVD	$runtimesigprofCallersUse(SB), R8
    324 	SYNC
    325 	LWAR    (R8), R6
    326 	CMPW    $0, R6
    327 	BNE     sigtramp
    328 	STWCCC  R7, (R8)
    329 	BNE     -4(PC)
    330 	ISYNC
    331 
    332 	// Jump to the traceback function in runtime/cgo.
    333 	// It will call back to sigprofNonGo, which will ignore the
    334 	// arguments passed in registers.
    335 	// First three arguments to traceback function are in registers already.
    336 	MOVD	runtimecgoTraceback(SB), R6
    337 	MOVD	$runtimesigprofCallers(SB), R7
    338 	MOVD	$runtimesigprofNonGoWrapper<>(SB), R8
    339 	MOVD	_cgo_callers(SB), R12
    340 	MOVD	R12, CTR
    341 	MOVD	R10, LR // restore LR
    342 	JMP	(CTR)
    343 #else
    344 // function descriptor for the real sigtramp
    345 TEXT runtimecgoSigtramp(SB),NOSPLIT|NOFRAME,$0
    346 	DWORD	$runtime_cgoSigtramp(SB)
    347 	DWORD	$0
    348 	DWORD	$0
    349 TEXT runtime_cgoSigtramp(SB),NOSPLIT,$0
    350 	JMP	runtimesigtramp(SB)
    351 #endif
    352 
    353 TEXT runtimesigprofNonGoWrapper<>(SB),NOSPLIT,$0
    354 	// We're coming from C code, set up essential register, then call sigprofNonGo.
    355 	CALL	runtimereginit(SB)
    356 	CALL	runtimesigprofNonGo(SB)
    357 	RET
    358 
    359 TEXT runtimemmap(SB),NOSPLIT|NOFRAME,$0
    360 	MOVD	addr+0(FP), R3
    361 	MOVD	n+8(FP), R4
    362 	MOVW	prot+16(FP), R5
    363 	MOVW	flags+20(FP), R6
    364 	MOVW	fd+24(FP), R7
    365 	MOVW	off+28(FP), R8
    366 
    367 	SYSCALL	$SYS_mmap
    368 	BVC	ok
    369 	MOVD	$0, p+32(FP)
    370 	MOVD	R3, err+40(FP)
    371 	RET
    372 ok:
    373 	MOVD	R3, p+32(FP)
    374 	MOVD	$0, err+40(FP)
    375 	RET
    376 
    377 TEXT runtimemunmap(SB),NOSPLIT|NOFRAME,$0
    378 	MOVD	addr+0(FP), R3
    379 	MOVD	n+8(FP), R4
    380 	SYSCALL	$SYS_munmap
    381 	BVC	2(PC)
    382 	MOVD	R0, 0xf0(R0)
    383 	RET
    384 
    385 TEXT runtimemadvise(SB),NOSPLIT|NOFRAME,$0
    386 	MOVD	addr+0(FP), R3
    387 	MOVD	n+8(FP), R4
    388 	MOVW	flags+16(FP), R5
    389 	SYSCALL	$SYS_madvise
    390 	// ignore failure - maybe pages are locked
    391 	RET
    392 
    393 // int64 futex(int32 *uaddr, int32 op, int32 val,
    394 //	struct timespec *timeout, int32 *uaddr2, int32 val2);
    395 TEXT runtimefutex(SB),NOSPLIT|NOFRAME,$0
    396 	MOVD	addr+0(FP), R3
    397 	MOVW	op+8(FP), R4
    398 	MOVW	val+12(FP), R5
    399 	MOVD	ts+16(FP), R6
    400 	MOVD	addr2+24(FP), R7
    401 	MOVW	val3+32(FP), R8
    402 	SYSCALL	$SYS_futex
    403 	MOVW	R3, ret+40(FP)
    404 	RET
    405 
    406 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
    407 TEXT runtimeclone(SB),NOSPLIT|NOFRAME,$0
    408 	MOVW	flags+0(FP), R3
    409 	MOVD	stk+8(FP), R4
    410 
    411 	// Copy mp, gp, fn off parent stack for use by child.
    412 	// Careful: Linux system call clobbers ???.
    413 	MOVD	mp+16(FP), R7
    414 	MOVD	gp+24(FP), R8
    415 	MOVD	fn+32(FP), R12
    416 
    417 	MOVD	R7, -8(R4)
    418 	MOVD	R8, -16(R4)
    419 	MOVD	R12, -24(R4)
    420 	MOVD	$1234, R7
    421 	MOVD	R7, -32(R4)
    422 
    423 	SYSCALL $SYS_clone
    424 
    425 	// In parent, return.
    426 	CMP	R3, $0
    427 	BEQ	3(PC)
    428 	MOVW	R3, ret+40(FP)
    429 	RET
    430 
    431 	// In child, on new stack.
    432 	// initialize essential registers
    433 	BL	runtimereginit(SB)
    434 	MOVD	-32(R1), R7
    435 	CMP	R7, $1234
    436 	BEQ	2(PC)
    437 	MOVD	R0, 0(R0)
    438 
    439 	// Initialize m->procid to Linux tid
    440 	SYSCALL $SYS_gettid
    441 
    442 	MOVD	-24(R1), R12       // fn
    443 	MOVD	-16(R1), R8        // g
    444 	MOVD	-8(R1), R7         // m
    445 
    446 	CMP	R7, $0
    447 	BEQ	nog
    448 	CMP	R8, $0
    449 	BEQ	nog
    450 
    451 	MOVD	R3, m_procid(R7)
    452 
    453 	// TODO: setup TLS.
    454 
    455 	// In child, set up new stack
    456 	MOVD	R7, g_m(R8)
    457 	MOVD	R8, g
    458 	//CALL	runtimestackcheck(SB)
    459 
    460 nog:
    461 	// Call fn
    462 	MOVD	R12, CTR
    463 	BL	(CTR)
    464 
    465 	// It shouldn't return.	 If it does, exit that thread.
    466 	MOVW	$111, R3
    467 	SYSCALL	$SYS_exit
    468 	BR	-2(PC)	// keep exiting
    469 
    470 TEXT runtimesigaltstack(SB),NOSPLIT|NOFRAME,$0
    471 	MOVD	new+0(FP), R3
    472 	MOVD	old+8(FP), R4
    473 	SYSCALL	$SYS_sigaltstack
    474 	BVC	2(PC)
    475 	MOVD	R0, 0xf0(R0)  // crash
    476 	RET
    477 
    478 TEXT runtimeosyield(SB),NOSPLIT|NOFRAME,$0
    479 	SYSCALL	$SYS_sched_yield
    480 	RET
    481 
    482 TEXT runtimesched_getaffinity(SB),NOSPLIT|NOFRAME,$0
    483 	MOVD	pid+0(FP), R3
    484 	MOVD	len+8(FP), R4
    485 	MOVD	buf+16(FP), R5
    486 	SYSCALL	$SYS_sched_getaffinity
    487 	MOVW	R3, ret+24(FP)
    488 	RET
    489 
    490 // int32 runtimeepollcreate(int32 size);
    491 TEXT runtimeepollcreate(SB),NOSPLIT|NOFRAME,$0
    492 	MOVW    size+0(FP), R3
    493 	SYSCALL	$SYS_epoll_create
    494 	MOVW	R3, ret+8(FP)
    495 	RET
    496 
    497 // int32 runtimeepollcreate1(int32 flags);
    498 TEXT runtimeepollcreate1(SB),NOSPLIT|NOFRAME,$0
    499 	MOVW	flags+0(FP), R3
    500 	SYSCALL	$SYS_epoll_create1
    501 	MOVW	R3, ret+8(FP)
    502 	RET
    503 
    504 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
    505 TEXT runtimeepollctl(SB),NOSPLIT|NOFRAME,$0
    506 	MOVW	epfd+0(FP), R3
    507 	MOVW	op+4(FP), R4
    508 	MOVW	fd+8(FP), R5
    509 	MOVD	ev+16(FP), R6
    510 	SYSCALL	$SYS_epoll_ctl
    511 	MOVW	R3, ret+24(FP)
    512 	RET
    513 
    514 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
    515 TEXT runtimeepollwait(SB),NOSPLIT|NOFRAME,$0
    516 	MOVW	epfd+0(FP), R3
    517 	MOVD	ev+8(FP), R4
    518 	MOVW	nev+16(FP), R5
    519 	MOVW	timeout+20(FP), R6
    520 	SYSCALL	$SYS_epoll_wait
    521 	MOVW	R3, ret+24(FP)
    522 	RET
    523 
    524 // void runtimecloseonexec(int32 fd);
    525 TEXT runtimecloseonexec(SB),NOSPLIT|NOFRAME,$0
    526 	MOVW    fd+0(FP), R3  // fd
    527 	MOVD    $2, R4  // F_SETFD
    528 	MOVD    $1, R5  // FD_CLOEXEC
    529 	SYSCALL	$SYS_fcntl
    530 	RET
    531 
    532 // func sbrk0() uintptr
    533 TEXT runtimesbrk0(SB),NOSPLIT|NOFRAME,$0
    534 	// Implemented as brk(NULL).
    535 	MOVD	$0, R3
    536 	SYSCALL	$SYS_brk
    537 	MOVD	R3, ret+0(FP)
    538 	RET
    539