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 // +build linux
      6 // +build mips mipsle
      7 
      8 //
      9 // System calls and other sys.stuff for mips, Linux
     10 //
     11 
     12 #include "go_asm.h"
     13 #include "go_tls.h"
     14 #include "textflag.h"
     15 
     16 #define SYS_exit		        4001
     17 #define SYS_read		        4003
     18 #define SYS_write		        4004
     19 #define SYS_open		        4005
     20 #define SYS_close		        4006
     21 #define SYS_getpid		        4020
     22 #define SYS_kill		        4037
     23 #define SYS_fcntl		        4055
     24 #define SYS_gettimeofday	    4078
     25 #define SYS_mmap		        4090
     26 #define SYS_munmap		        4091
     27 #define SYS_setitimer		    4104
     28 #define SYS_clone		        4120
     29 #define SYS_newselect		    4142
     30 #define SYS_sched_yield		    4162
     31 #define SYS_rt_sigreturn	    4193
     32 #define SYS_rt_sigaction	    4194
     33 #define SYS_rt_sigprocmask		4195
     34 #define SYS_sigaltstack		    4206
     35 #define SYS_getrlimit		    4076
     36 #define SYS_madvise		        4218
     37 #define SYS_mincore		        4217
     38 #define SYS_gettid		        4222
     39 #define SYS_tkill		        4236
     40 #define SYS_futex		        4238
     41 #define SYS_sched_getaffinity	4240
     42 #define SYS_exit_group		    4246
     43 #define SYS_epoll_create	    4248
     44 #define SYS_epoll_ctl		    4249
     45 #define SYS_epoll_wait		    4250
     46 #define SYS_clock_gettime	    4263
     47 #define SYS_epoll_create1	    4326
     48 #define SYS_brk			    4045
     49 
     50 TEXT runtimeexit(SB),NOSPLIT,$0-4
     51 	MOVW	code+0(FP), R4
     52 	MOVW	$SYS_exit_group, R2
     53 	SYSCALL
     54 	UNDEF
     55 	RET
     56 
     57 // func exitThread(wait *uint32)
     58 TEXT runtimeexitThread(SB),NOSPLIT,$0-4
     59 	MOVW	wait+0(FP), R1
     60 	// We're done using the stack.
     61 	MOVW	$0, R2
     62 	SYNC
     63 	MOVW	R2, (R1)
     64 	SYNC
     65 	MOVW	$0, R4	// exit code
     66 	MOVW	$SYS_exit, R2
     67 	SYSCALL
     68 	UNDEF
     69 	JMP	0(PC)
     70 
     71 TEXT runtimeopen(SB),NOSPLIT,$0-16
     72 	MOVW	name+0(FP), R4
     73 	MOVW	mode+4(FP), R5
     74 	MOVW	perm+8(FP), R6
     75 	MOVW	$SYS_open, R2
     76 	SYSCALL
     77 	BEQ	R7, 2(PC)
     78 	MOVW	$-1, R2
     79 	MOVW	R2, ret+12(FP)
     80 	RET
     81 
     82 TEXT runtimeclosefd(SB),NOSPLIT,$0-8
     83 	MOVW	fd+0(FP), R4
     84 	MOVW	$SYS_close, R2
     85 	SYSCALL
     86 	BEQ	R7, 2(PC)
     87 	MOVW	$-1, R2
     88 	MOVW	R2, ret+4(FP)
     89 	RET
     90 
     91 TEXT runtimewrite(SB),NOSPLIT,$0-16
     92 	MOVW	fd+0(FP), R4
     93 	MOVW	p+4(FP), R5
     94 	MOVW	n+8(FP), R6
     95 	MOVW	$SYS_write, R2
     96 	SYSCALL
     97 	BEQ	R7, 2(PC)
     98 	MOVW	$-1, R2
     99 	MOVW	R2, ret+12(FP)
    100 	RET
    101 
    102 TEXT runtimeread(SB),NOSPLIT,$0-16
    103 	MOVW	fd+0(FP), R4
    104 	MOVW	p+4(FP), R5
    105 	MOVW	n+8(FP), R6
    106 	MOVW	$SYS_read, R2
    107 	SYSCALL
    108 	BEQ	R7, 2(PC)
    109 	MOVW	$-1, R2
    110 	MOVW	R2, ret+12(FP)
    111 	RET
    112 
    113 TEXT runtimegetrlimit(SB),NOSPLIT,$0-12
    114 	MOVW	kind+0(FP), R4
    115 	MOVW	limit+4(FP), R5
    116 	MOVW	$SYS_getrlimit, R2
    117 	SYSCALL
    118 	MOVW	R2, ret+8(FP)
    119 	RET
    120 
    121 TEXT runtimeusleep(SB),NOSPLIT,$28-4
    122 	MOVW	usec+0(FP), R3
    123 	MOVW	R3, R5
    124 	MOVW	$1000000, R4
    125 	DIVU	R4, R3
    126 	MOVW	LO, R3
    127 	MOVW	R3, 24(R29)
    128 	MULU	R3, R4
    129 	MOVW	LO, R4
    130 	SUBU	R4, R5
    131 	MOVW	R5, 28(R29)
    132 
    133 	// select(0, 0, 0, 0, &tv)
    134 	MOVW	$0, R4
    135 	MOVW	$0, R5
    136 	MOVW	$0, R6
    137 	MOVW	$0, R7
    138 	ADDU	$24, R29, R8
    139 	MOVW	R8, 16(R29)
    140 	MOVW	$SYS_newselect, R2
    141 	SYSCALL
    142 	RET
    143 
    144 TEXT runtimegettid(SB),NOSPLIT,$0-4
    145 	MOVW	$SYS_gettid, R2
    146 	SYSCALL
    147 	MOVW	R2, ret+0(FP)
    148 	RET
    149 
    150 TEXT runtimeraise(SB),NOSPLIT,$0-4
    151 	MOVW	$SYS_gettid, R2
    152 	SYSCALL
    153 	MOVW	R2, R4	// arg 1 tid
    154 	MOVW	sig+0(FP), R5	// arg 2
    155 	MOVW	$SYS_tkill, R2
    156 	SYSCALL
    157 	RET
    158 
    159 TEXT runtimeraiseproc(SB),NOSPLIT,$0
    160 	MOVW	$SYS_getpid, R2
    161 	SYSCALL
    162 	MOVW	R2, R4	// arg 1 pid
    163 	MOVW	sig+0(FP), R5	// arg 2
    164 	MOVW	$SYS_kill, R2
    165 	SYSCALL
    166 	RET
    167 
    168 TEXT runtimesetitimer(SB),NOSPLIT,$0-12
    169 	MOVW	mode+0(FP), R4
    170 	MOVW	new+4(FP), R5
    171 	MOVW	old+8(FP), R6
    172 	MOVW	$SYS_setitimer, R2
    173 	SYSCALL
    174 	RET
    175 
    176 TEXT runtimemincore(SB),NOSPLIT,$0-16
    177 	MOVW	addr+0(FP), R4
    178 	MOVW	n+4(FP), R5
    179 	MOVW	dst+8(FP), R6
    180 	MOVW	$SYS_mincore, R2
    181 	SYSCALL
    182 	SUBU	R2, R0, R2	// caller expects negative errno
    183 	MOVW	R2, ret+12(FP)
    184 	RET
    185 
    186 // func walltime() (sec int64, nsec int32)
    187 TEXT runtimewalltime(SB),NOSPLIT,$8-12
    188 	MOVW	$0, R4	// CLOCK_REALTIME
    189 	MOVW	$4(R29), R5
    190 	MOVW	$SYS_clock_gettime, R2
    191 	SYSCALL
    192 	MOVW	4(R29), R3	// sec
    193 	MOVW	8(R29), R5	// nsec
    194 #ifdef GOARCH_mips
    195 	MOVW	R3, sec_lo+4(FP)
    196 	MOVW	R0, sec_hi+0(FP)
    197 #else
    198 	MOVW	R3, sec_lo+0(FP)
    199 	MOVW	R0, sec_hi+4(FP)
    200 #endif
    201 	MOVW	R5, nsec+8(FP)
    202 	RET
    203 
    204 TEXT runtimenanotime(SB),NOSPLIT,$8-8
    205 	MOVW	$1, R4	// CLOCK_MONOTONIC
    206 	MOVW	$4(R29), R5
    207 	MOVW	$SYS_clock_gettime, R2
    208 	SYSCALL
    209 	MOVW	4(R29), R3	// sec
    210 	MOVW	8(R29), R5	// nsec
    211 	// sec is in R3, nsec in R5
    212 	// return nsec in R3
    213 	MOVW	$1000000000, R4
    214 	MULU	R4, R3
    215 	MOVW	LO, R3
    216 	ADDU	R5, R3
    217 	SGTU	R5, R3, R4
    218 #ifdef GOARCH_mips
    219 	MOVW	R3, ret_lo+4(FP)
    220 #else
    221 	MOVW	R3, ret_lo+0(FP)
    222 #endif
    223 	MOVW	HI, R3
    224 	ADDU	R4, R3
    225 #ifdef GOARCH_mips
    226 	MOVW	R3, ret_hi+0(FP)
    227 #else
    228 	MOVW	R3, ret_hi+4(FP)
    229 #endif
    230 	RET
    231 
    232 TEXT runtimertsigprocmask(SB),NOSPLIT,$0-16
    233 	MOVW	how+0(FP), R4
    234 	MOVW	new+4(FP), R5
    235 	MOVW	old+8(FP), R6
    236 	MOVW	size+12(FP), R7
    237 	MOVW	$SYS_rt_sigprocmask, R2
    238 	SYSCALL
    239 	BEQ	R7, 2(PC)
    240 	UNDEF	// crash
    241 	RET
    242 
    243 TEXT runtimert_sigaction(SB),NOSPLIT,$0-20
    244 	MOVW	sig+0(FP), R4
    245 	MOVW	new+4(FP), R5
    246 	MOVW	old+8(FP), R6
    247 	MOVW	size+12(FP), R7
    248 	MOVW	$SYS_rt_sigaction, R2
    249 	SYSCALL
    250 	MOVW	R2, ret+16(FP)
    251 	RET
    252 
    253 TEXT runtimesigfwd(SB),NOSPLIT,$0-16
    254 	MOVW	sig+4(FP), R4
    255 	MOVW	info+8(FP), R5
    256 	MOVW	ctx+12(FP), R6
    257 	MOVW	fn+0(FP), R25
    258 	MOVW	R29, R22
    259 	SUBU	$16, R29
    260 	AND	$~7, R29	// shadow space for 4 args aligned to 8 bytes as per O32 ABI
    261 	JAL	(R25)
    262 	MOVW	R22, R29
    263 	RET
    264 
    265 TEXT runtimesigtramp(SB),NOSPLIT,$12
    266 	// this might be called in external code context,
    267 	// where g is not set.
    268 	MOVB	runtimeiscgo(SB), R1
    269 	BEQ	R1, 2(PC)
    270 	JAL	runtimeload_g(SB)
    271 
    272 	MOVW	R4, 4(R29)
    273 	MOVW	R5, 8(R29)
    274 	MOVW	R6, 12(R29)
    275 	MOVW	$runtimesigtrampgo(SB), R1
    276 	JAL	(R1)
    277 	RET
    278 
    279 TEXT runtimecgoSigtramp(SB),NOSPLIT,$0
    280 	JMP	runtimesigtramp(SB)
    281 
    282 TEXT runtimemmap(SB),NOSPLIT,$20-32
    283 	MOVW	addr+0(FP), R4
    284 	MOVW	n+4(FP), R5
    285 	MOVW	prot+8(FP), R6
    286 	MOVW	flags+12(FP), R7
    287 	MOVW	fd+16(FP), R8
    288 	MOVW	off+20(FP), R9
    289 	MOVW	R8, 16(R29)
    290 	MOVW	R9, 20(R29)
    291 
    292 	MOVW	$SYS_mmap, R2
    293 	SYSCALL
    294 	BEQ	R7, ok
    295 	MOVW	$0, p+24(FP)
    296 	MOVW	R2, err+28(FP)
    297 	RET
    298 ok:
    299 	MOVW	R2, p+24(FP)
    300 	MOVW	$0, err+28(FP)
    301 	RET
    302 
    303 TEXT runtimemunmap(SB),NOSPLIT,$0-8
    304 	MOVW	addr+0(FP), R4
    305 	MOVW	n+4(FP), R5
    306 	MOVW	$SYS_munmap, R2
    307 	SYSCALL
    308 	BEQ	R7, 2(PC)
    309 	UNDEF	// crash
    310 	RET
    311 
    312 TEXT runtimemadvise(SB),NOSPLIT,$0-12
    313 	MOVW	addr+0(FP), R4
    314 	MOVW	n+4(FP), R5
    315 	MOVW	flags+8(FP), R6
    316 	MOVW	$SYS_madvise, R2
    317 	SYSCALL
    318 	// ignore failure - maybe pages are locked
    319 	RET
    320 
    321 // int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2);
    322 TEXT runtimefutex(SB),NOSPLIT,$20-28
    323 	MOVW	addr+0(FP), R4
    324 	MOVW	op+4(FP), R5
    325 	MOVW	val+8(FP), R6
    326 	MOVW	ts+12(FP), R7
    327 
    328 	MOVW	addr2+16(FP), R8
    329 	MOVW	val3+20(FP), R9
    330 
    331 	MOVW	R8, 16(R29)
    332 	MOVW	R9, 20(R29)
    333 
    334 	MOVW	$SYS_futex, R2
    335 	SYSCALL
    336 	MOVW	R2, ret+24(FP)
    337 	RET
    338 
    339 
    340 // int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
    341 TEXT runtimeclone(SB),NOSPLIT,$-4-24
    342 	MOVW	flags+0(FP), R4
    343 	MOVW	stk+4(FP), R5
    344 	MOVW	R0, R6	// ptid
    345 	MOVW	R0, R7	// tls
    346 
    347 	// O32 syscall handler unconditionally copies arguments 5-8 from stack,
    348 	// even for syscalls with less than 8 arguments. Reserve 32 bytes of new
    349 	// stack so that any syscall invoked immediately in the new thread won't fail.
    350 	ADD	$-32, R5
    351 
    352 	// Copy mp, gp, fn off parent stack for use by child.
    353 	MOVW	mp+8(FP), R16
    354 	MOVW	gp+12(FP), R17
    355 	MOVW	fn+16(FP), R18
    356 
    357 	MOVW	$1234, R1
    358 
    359 	MOVW	R16, 0(R5)
    360 	MOVW	R17, 4(R5)
    361 	MOVW	R18, 8(R5)
    362 
    363 	MOVW	R1, 12(R5)
    364 
    365 	MOVW	$SYS_clone, R2
    366 	SYSCALL
    367 
    368 	// In parent, return.
    369 	BEQ	R2, 5(PC)
    370 	SUBU	R2, R0, R3
    371 	CMOVN	R7, R3, R2
    372 	MOVW	R2, ret+20(FP)
    373 	RET
    374 
    375 	// In child, on new stack.
    376 	// Check that SP is as we expect
    377 	MOVW	12(R29), R16
    378 	MOVW	$1234, R1
    379 	BEQ	R16, R1, 2(PC)
    380 	MOVW	(R0), R0
    381 
    382 	// Initialize m->procid to Linux tid
    383 	MOVW	$SYS_gettid, R2
    384 	SYSCALL
    385 
    386 	MOVW	0(R29), R16	// m
    387 	MOVW	4(R29), R17	// g
    388 	MOVW	8(R29), R18	// fn
    389 
    390 	BEQ	R16, nog
    391 	BEQ	R17, nog
    392 
    393 	MOVW	R2, m_procid(R16)
    394 
    395 	// In child, set up new stack
    396 	MOVW	R16, g_m(R17)
    397 	MOVW	R17, g
    398 
    399 // TODO(mips32): doesn't have runtimestackcheck(SB)
    400 
    401 nog:
    402 	// Call fn
    403 	ADDU	$32, R29
    404 	JAL	(R18)
    405 
    406 	// It shouldn't return.	 If it does, exit that thread.
    407 	ADDU	$-32, R29
    408 	MOVW	$0xf4, R4
    409 	MOVW	$SYS_exit, R2
    410 	SYSCALL
    411 	UNDEF
    412 
    413 TEXT runtimesigaltstack(SB),NOSPLIT,$0
    414 	MOVW	new+0(FP), R4
    415 	MOVW	old+4(FP), R5
    416 	MOVW	$SYS_sigaltstack, R2
    417 	SYSCALL
    418 	BEQ	R7, 2(PC)
    419 	UNDEF	// crash
    420 	RET
    421 
    422 TEXT runtimeosyield(SB),NOSPLIT,$0
    423 	MOVW	$SYS_sched_yield, R2
    424 	SYSCALL
    425 	RET
    426 
    427 TEXT runtimesched_getaffinity(SB),NOSPLIT,$0-16
    428 	MOVW	pid+0(FP), R4
    429 	MOVW	len+4(FP), R5
    430 	MOVW	buf+8(FP), R6
    431 	MOVW	$SYS_sched_getaffinity, R2
    432 	SYSCALL
    433 	MOVW	R2, ret+12(FP)
    434 	RET
    435 
    436 // int32 runtimeepollcreate(int32 size);
    437 TEXT runtimeepollcreate(SB),NOSPLIT,$0-8
    438 	MOVW	size+0(FP), R4
    439 	MOVW	$SYS_epoll_create, R2
    440 	SYSCALL
    441 	MOVW	R2, ret+4(FP)
    442 	RET
    443 
    444 // int32 runtimeepollcreate1(int32 flags);
    445 TEXT runtimeepollcreate1(SB),NOSPLIT,$0-8
    446 	MOVW	flags+0(FP), R4
    447 	MOVW	$SYS_epoll_create1, R2
    448 	SYSCALL
    449 	MOVW	R2, ret+4(FP)
    450 	RET
    451 
    452 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
    453 TEXT runtimeepollctl(SB),NOSPLIT,$0-20
    454 	MOVW	epfd+0(FP), R4
    455 	MOVW	op+4(FP), R5
    456 	MOVW	fd+8(FP), R6
    457 	MOVW	ev+12(FP), R7
    458 	MOVW	$SYS_epoll_ctl, R2
    459 	SYSCALL
    460 	MOVW	R2, ret+16(FP)
    461 	RET
    462 
    463 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
    464 TEXT runtimeepollwait(SB),NOSPLIT,$0-20
    465 	MOVW	epfd+0(FP), R4
    466 	MOVW	ev+4(FP), R5
    467 	MOVW	nev+8(FP), R6
    468 	MOVW	timeout+12(FP), R7
    469 	MOVW	$SYS_epoll_wait, R2
    470 	SYSCALL
    471 	MOVW	R2, ret+16(FP)
    472 	RET
    473 
    474 // void runtimecloseonexec(int32 fd);
    475 TEXT runtimecloseonexec(SB),NOSPLIT,$0-4
    476 	MOVW	fd+0(FP), R4	// fd
    477 	MOVW	$2, R5	// F_SETFD
    478 	MOVW	$1, R6	// FD_CLOEXEC
    479 	MOVW	$SYS_fcntl, R2
    480 	SYSCALL
    481 	RET
    482 
    483 // func sbrk0() uintptr
    484 TEXT runtimesbrk0(SB),NOSPLIT,$0-4
    485 	// Implemented as brk(NULL).
    486 	MOVW	$0, R4
    487 	MOVW	$SYS_brk, R2
    488 	SYSCALL
    489 	MOVW	R2, ret+0(FP)
    490 	RET
    491