Home | History | Annotate | Download | only in runtime
      1 // Copyright 2015 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 sys.stuff for ARM64, Darwin
      6 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
      7 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
      8 
      9 #include "go_asm.h"
     10 #include "go_tls.h"
     11 #include "textflag.h"
     12 
     13 // Copied from /usr/include/sys/syscall.h
     14 #define	SYS_exit           1
     15 #define	SYS_read           3
     16 #define	SYS_write          4
     17 #define	SYS_open           5
     18 #define	SYS_close          6
     19 #define	SYS_mmap           197
     20 #define	SYS_munmap         73
     21 #define	SYS_madvise        75
     22 #define	SYS_gettimeofday   116
     23 #define	SYS_kill           37
     24 #define	SYS_getpid         20
     25 #define	SYS___pthread_kill 328
     26 #define	SYS_pthread_sigmask 329
     27 #define	SYS_setitimer      83
     28 #define	SYS___sysctl       202
     29 #define	SYS_sigaction      46
     30 #define	SYS_sigreturn      184
     31 #define	SYS_select         93
     32 #define	SYS_bsdthread_register 366
     33 #define	SYS_bsdthread_create 360
     34 #define	SYS_bsdthread_terminate 361
     35 #define	SYS_kqueue         362
     36 #define	SYS_kevent         363
     37 #define	SYS_fcntl          92
     38 
     39 TEXT notok<>(SB),NOSPLIT,$0
     40 	MOVD	$0, R8
     41 	MOVD	R8, (R8)
     42 	B	0(PC)
     43 
     44 TEXT runtimeopen(SB),NOSPLIT,$0
     45 	MOVD	name+0(FP), R0
     46 	MOVW	mode+8(FP), R1
     47 	MOVW	perm+12(FP), R2
     48 	MOVD	$SYS_open, R16
     49 	SVC	$0x80
     50 	CSINV	LO, R0, ZR, R0
     51 	MOVW	R0, ret+16(FP)
     52 	RET
     53 
     54 TEXT runtimeclosefd(SB),NOSPLIT,$0
     55 	MOVW	fd+0(FP), R0
     56 	MOVW	$SYS_close, R16
     57 	SVC	$0x80
     58 	CSINV	LO, R0, ZR, R0
     59 	MOVW	R0, ret+8(FP)
     60 	RET
     61 
     62 TEXT runtimewrite(SB),NOSPLIT,$0
     63 	MOVW	fd+0(FP), R0
     64 	MOVD	p+8(FP), R1
     65 	MOVW	n+16(FP), R2
     66 	MOVW	$SYS_write, R16
     67 	SVC	$0x80
     68 	CSINV	LO, R0, ZR, R0
     69 	MOVW	R0, ret+24(FP)
     70 	RET
     71 
     72 TEXT runtimeread(SB),NOSPLIT,$0
     73 	MOVW	fd+0(FP), R0
     74 	MOVD	p+8(FP), R1
     75 	MOVW	n+16(FP), R2
     76 	MOVW	$SYS_read, R16
     77 	SVC	$0x80
     78 	CSINV	LO, R0, ZR, R0
     79 	MOVW	R0, ret+24(FP)
     80 	RET
     81 
     82 TEXT runtimeexit(SB),NOSPLIT,$-8
     83 	MOVW	code+0(FP), R0
     84 	MOVW	$SYS_exit, R16
     85 	SVC	$0x80
     86 	MOVD	$1234, R0
     87 	MOVD	$1002, R1
     88 	MOVD	R0, (R1)	// fail hard
     89 
     90 // Exit this OS thread (like pthread_exit, which eventually
     91 // calls __bsdthread_terminate).
     92 TEXT exit1<>(SB),NOSPLIT,$0
     93 	// Because of exitThread below, this must not use the stack.
     94 	// __bsdthread_terminate takes 4 word-size arguments.
     95 	// Set them all to 0. (None are an exit status.)
     96 	MOVW	$0, R0
     97 	MOVW	$0, R1
     98 	MOVW	$0, R2
     99 	MOVW	$0, R3
    100 	MOVW	$SYS_bsdthread_terminate, R16
    101 	SVC	$0x80
    102 	MOVD	$1234, R0
    103 	MOVD	$1003, R1
    104 	MOVD	R0, (R1)	// fail hard
    105 
    106 // func exitThread(wait *uint32)
    107 TEXT runtimeexitThread(SB),NOSPLIT,$0-8
    108 	MOVD	wait+0(FP), R0
    109 	// We're done using the stack.
    110 	MOVW	$0, R1
    111 	STLRW	R1, (R0)
    112 	JMP	exit1<>(SB)
    113 
    114 TEXT runtimeraise(SB),NOSPLIT,$0
    115 	// Ideally we'd send the signal to the current thread,
    116 	// not the whole process, but that's too hard on OS X.
    117 	JMP	runtimeraiseproc(SB)
    118 
    119 TEXT runtimeraiseproc(SB),NOSPLIT,$0
    120 	MOVW	$SYS_getpid, R16
    121 	SVC	$0x80
    122 	// arg 1 pid already in R0 from getpid
    123 	MOVW	sig+0(FP), R1	// arg 2 - signal
    124 	MOVW	$1, R2	// arg 3 - posix
    125 	MOVW	$SYS_kill, R16
    126 	SVC	$0x80
    127 	RET
    128 
    129 TEXT runtimemmap(SB),NOSPLIT,$0
    130 	MOVD	addr+0(FP), R0
    131 	MOVD	n+8(FP), R1
    132 	MOVW	prot+16(FP), R2
    133 	MOVW	flags+20(FP), R3
    134 	MOVW	fd+24(FP), R4
    135 	MOVW	off+28(FP), R5
    136 	MOVW	$SYS_mmap, R16
    137 	SVC	$0x80
    138 	BCC	ok
    139 	MOVD	$0, p+32(FP)
    140 	MOVD	R0, err+40(FP)
    141 	RET
    142 ok:
    143 	MOVD	R0, p+32(FP)
    144 	MOVD	$0, err+40(FP)
    145 	RET
    146 
    147 TEXT runtimemunmap(SB),NOSPLIT,$0
    148 	MOVD	addr+0(FP), R0
    149 	MOVD	n+8(FP), R1
    150 	MOVW	$SYS_munmap, R16
    151 	SVC	$0x80
    152 	BCC	2(PC)
    153 	BL	notok<>(SB)
    154 	RET
    155 
    156 TEXT runtimemadvise(SB),NOSPLIT,$0
    157 	MOVD	addr+0(FP), R0
    158 	MOVD	n+8(FP), R1
    159 	MOVW	flags+16(FP), R2
    160 	MOVW	$SYS_madvise, R16
    161 	SVC	$0x80
    162 	BCC	2(PC)
    163 	BL	notok<>(SB)
    164 	RET
    165 
    166 TEXT runtimesetitimer(SB),NOSPLIT,$0
    167 	MOVW	mode+0(FP), R0
    168 	MOVD	new+8(FP), R1
    169 	MOVD	old+16(FP), R2
    170 	MOVW	$SYS_setitimer, R16
    171 	SVC	$0x80
    172 	RET
    173 
    174 TEXT runtimewalltime(SB),NOSPLIT,$40-12
    175 	MOVD	RSP, R0	// timeval
    176 	MOVD	R0, R9	// this is how dyld calls gettimeofday
    177 	MOVW	$0, R1	// zone
    178 	MOVD	$0, R2	// see issue 16570
    179 	MOVW	$SYS_gettimeofday, R16
    180 	SVC	$0x80	// Note: x0 is tv_sec, w1 is tv_usec
    181 	CMP	$0, R0
    182 	BNE	inreg
    183 	MOVD	0(RSP), R0
    184 	MOVW	8(RSP), R1
    185 inreg:
    186 	MOVD	R0, sec+0(FP)
    187 	MOVW	$1000, R3
    188 	MUL	R3, R1
    189 	MOVW	R1, nsec+8(FP)
    190 	RET
    191 
    192 TEXT runtimenanotime(SB),NOSPLIT,$40
    193 	MOVD	RSP, R0	// timeval
    194 	MOVD	R0, R9	// this is how dyld calls gettimeofday
    195 	MOVW	$0, R1	// zone
    196 	MOVD	$0, R2	// see issue 16570
    197 	MOVW	$SYS_gettimeofday, R16
    198 	SVC	$0x80	// Note: x0 is tv_sec, w1 is tv_usec
    199 	CMP	$0, R0
    200 	BNE	inreg
    201 	MOVD	0(RSP), R0
    202 	MOVW	8(RSP), R1
    203 inreg:
    204 	MOVW	$1000000000, R3
    205 	MUL	R3, R0
    206 	MOVW	$1000, R3
    207 	MUL	R3, R1
    208 	ADD	R1, R0
    209 
    210 	MOVD	R0, ret+0(FP)
    211 	RET
    212 
    213 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    214 	MOVW	sig+8(FP), R0
    215 	MOVD	info+16(FP), R1
    216 	MOVD	ctx+24(FP), R2
    217 	MOVD	fn+0(FP), R11
    218 	BL	(R11)
    219 	RET
    220 
    221 // Sigtramp's job is to call the actual signal handler.
    222 // It is called with the following arguments on the stack:
    223 //	LR	"return address" - ignored
    224 //	R0	actual handler
    225 //	R1	siginfo style - ignored
    226 //	R2	signal number
    227 //	R3	siginfo
    228 //	R4	context
    229 TEXT runtimesigtramp(SB),NOSPLIT,$0
    230 	// this might be called in external code context,
    231 	// where g is not set.
    232 	// first save R0, because runtimeload_g will clobber it
    233 	MOVD.W	R0, -16(RSP)	// note: stack must be 16-byte aligned
    234 	MOVB	runtimeiscgo(SB), R0
    235 	CMP	$0, R0
    236 	BEQ	2(PC)
    237 	BL	runtimeload_g(SB)
    238 
    239 	CMP	$0, g
    240 	BNE	cont
    241 	// fake function call stack frame for badsignal
    242 	// we only need to pass R2 (signal number), but
    243 	// badsignal will expect R2 at 8(RSP), so we also
    244 	// push R1 onto stack. turns out we do need R1
    245 	// to do sigreturn.
    246 	MOVD.W	R1, -16(RSP)
    247 	MOVD	R2, 8(RSP)
    248 	MOVD	R4, 24(RSP)	// save ucontext, badsignal might clobber R4
    249 	MOVD	$runtimebadsignal(SB), R26
    250 	BL	(R26)
    251 	MOVD	0(RSP), R1	// saved infostype
    252 	MOVD	24(RSP), R0	// the ucontext
    253 	ADD	$(16+16), RSP
    254 	B	ret
    255 
    256 cont:
    257 	// Restore R0
    258 	MOVD.P	16(RSP), R0
    259 
    260 	// NOTE: some Darwin/ARM kernels always use the main stack to run the
    261 	// signal handler. We need to switch to gsignal ourselves.
    262 	MOVD	g_m(g), R11
    263 	MOVD	m_gsignal(R11), R5
    264 	MOVD	(g_stack+stack_hi)(R5), R6
    265 	SUB	$64, R6
    266 
    267 	// copy arguments for call to sighandler
    268 	MOVD	R2, 8(R6)	// signal num
    269 	MOVD	R3, 16(R6)	// signal info
    270 	MOVD	R4, 24(R6)	// context
    271 	MOVD	g, 32(R6)	// old_g
    272 
    273 	// Backup ucontext and infostyle
    274 	MOVD	R4, 40(R6)
    275 	MOVD	R1, 48(R6)
    276 
    277 	// switch stack and g
    278 	MOVD	R6, RSP	// sigtramp is not re-entrant, so no need to back up RSP.
    279 	MOVD	R5, g
    280 
    281 	BL	(R0)
    282 
    283 	// call sigreturn
    284 	MOVD	40(RSP), R0	// saved ucontext
    285 	MOVD	48(RSP), R1	// saved infostyle
    286 ret:
    287 	MOVW	$SYS_sigreturn, R16 // sigreturn(ucontext, infostyle)
    288 	SVC	$0x80
    289 
    290 	// if sigreturn fails, we can do nothing but exit
    291 	B	runtimeexit(SB)
    292 
    293 TEXT runtimesigprocmask(SB),NOSPLIT,$0
    294 	MOVW	how+0(FP), R0
    295 	MOVD	new+8(FP), R1
    296 	MOVD	old+16(FP), R2
    297 	MOVW	$SYS_pthread_sigmask, R16
    298 	SVC	$0x80
    299 	BCC	2(PC)
    300 	BL	notok<>(SB)
    301 	RET
    302 
    303 TEXT runtimesigaction(SB),NOSPLIT,$0
    304 	MOVW	mode+0(FP), R0
    305 	MOVD	new+8(FP), R1
    306 	MOVD	old+16(FP), R2
    307 	MOVW	$SYS_sigaction, R16
    308 	SVC	$0x80
    309 	BCC	2(PC)
    310 	BL	notok<>(SB)
    311 	RET
    312 
    313 TEXT runtimeusleep(SB),NOSPLIT,$24
    314 	MOVW	usec+0(FP), R0
    315 	MOVW	R0, R1
    316 	MOVW	$1000000, R2
    317 	UDIV	R2, R0
    318 	MUL	R0, R2
    319 	SUB	R2, R1
    320 	MOVD	R0, 0(RSP)
    321 	MOVW	R1, 8(RSP)
    322 
    323 	// select(0, 0, 0, 0, &tv)
    324 	MOVW	$0, R0
    325 	MOVW	$0, R1
    326 	MOVW	$0, R2
    327 	MOVW	$0, R3
    328 	MOVD	RSP, R4
    329 	MOVW	$SYS_select, R16
    330 	SVC	$0x80
    331 	RET
    332 
    333 TEXT runtimesysctl(SB),NOSPLIT,$0
    334 	MOVD	mib+0(FP), R0
    335 	MOVW	miblen+8(FP), R1
    336 	MOVD	out+16(FP), R2
    337 	MOVD	size+24(FP), R3
    338 	MOVD	dst+32(FP), R4
    339 	MOVD	ndst+40(FP), R5
    340 	MOVW	$SYS___sysctl, R16
    341 	SVC	$0x80
    342 	BCC	ok
    343 	NEG	R0, R0
    344 	MOVW	R0, ret+48(FP)
    345 	RET
    346 ok:
    347 	MOVW	$0, R0
    348 	MOVW	R0, ret+48(FP)
    349 	RET
    350 
    351 // Thread related functions
    352 // Note: On darwin/arm64, it is no longer possible to use bsdthread_register
    353 // as the libc is always linked in. The runtime must use runtime/cgo to
    354 // create threads, so all thread related functions will just exit with a
    355 // unique status.
    356 // void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
    357 TEXT runtimebsdthread_create(SB),NOSPLIT,$0
    358 	MOVD	$44, R0
    359 	MOVW	$SYS_exit, R16
    360 	SVC	$0x80
    361 	RET
    362 
    363 // The thread that bsdthread_create creates starts executing here,
    364 // because we registered this function using bsdthread_register
    365 // at startup.
    366 //	R0 = "pthread"
    367 //	R1 = mach thread port
    368 //	R2 = "func" (= fn)
    369 //	R3 = "arg" (= m)
    370 //	R4 = stack
    371 //	R5 = flags (= 0)
    372 TEXT runtimebsdthread_start(SB),NOSPLIT,$0
    373 	MOVD	$45, R0
    374 	MOVW	$SYS_exit, R16
    375 	SVC	$0x80
    376 	RET
    377 
    378 // int32 bsdthread_register(void)
    379 // registers callbacks for threadstart (see bsdthread_create above
    380 // and wqthread and pthsize (not used).  returns 0 on success.
    381 TEXT runtimebsdthread_register(SB),NOSPLIT,$0
    382 	MOVD	$46, R0
    383 	MOVW	$SYS_exit, R16
    384 	SVC	$0x80
    385 	RET
    386 
    387 // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
    388 TEXT runtimemach_msg_trap(SB),NOSPLIT,$0
    389 	MOVD	h+0(FP), R0
    390 	MOVW	op+8(FP), R1
    391 	MOVW	send_size+12(FP), R2
    392 	MOVW	rcv_size+16(FP), R3
    393 	MOVW	rcv_name+20(FP), R4
    394 	MOVW	timeout+24(FP), R5
    395 	MOVW	notify+28(FP), R6
    396 	MOVN	$30, R16
    397 	SVC	$0x80
    398 	MOVW	R0, ret+32(FP)
    399 	RET
    400 
    401 TEXT runtimemach_task_self(SB),NOSPLIT,$0
    402 	MOVN	$27, R16 // task_self_trap
    403 	SVC	$0x80
    404 	MOVW	R0, ret+0(FP)
    405 	RET
    406 
    407 TEXT runtimemach_thread_self(SB),NOSPLIT,$0
    408 	MOVN	$26, R16 // thread_self_trap
    409 	SVC	$0x80
    410 	MOVW	R0, ret+0(FP)
    411 	RET
    412 
    413 TEXT runtimemach_reply_port(SB),NOSPLIT,$0
    414 	MOVN	$25, R16	// mach_reply_port
    415 	SVC	$0x80
    416 	MOVW	R0, ret+0(FP)
    417 	RET
    418 
    419 // Mach provides trap versions of the semaphore ops,
    420 // instead of requiring the use of RPC.
    421 
    422 // uint32 mach_semaphore_wait(uint32)
    423 TEXT runtimemach_semaphore_wait(SB),NOSPLIT,$0
    424 	MOVW	sema+0(FP), R0
    425 	MOVN	$35, R16	// semaphore_wait_trap
    426 	SVC	$0x80
    427 	MOVW	R0, ret+8(FP)
    428 	RET
    429 
    430 // uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
    431 TEXT runtimemach_semaphore_timedwait(SB),NOSPLIT,$0
    432 	MOVW	sema+0(FP), R0
    433 	MOVW	sec+4(FP), R1
    434 	MOVW	nsec+8(FP), R2
    435 	MOVN	$37, R16	// semaphore_timedwait_trap
    436 	SVC	$0x80
    437 	MOVW	R0, ret+16(FP)
    438 	RET
    439 
    440 // uint32 mach_semaphore_signal(uint32)
    441 TEXT runtimemach_semaphore_signal(SB),NOSPLIT,$0
    442 	MOVW	sema+0(FP), R0
    443 	MOVN	$32, R16	// semaphore_signal_trap
    444 	SVC	$0x80
    445 	MOVW	R0, ret+8(FP)
    446 	RET
    447 
    448 // uint32 mach_semaphore_signal_all(uint32)
    449 TEXT runtimemach_semaphore_signal_all(SB),NOSPLIT,$0
    450 	MOVW	sema+0(FP), R0
    451 	MOVN	$33, R16	// semaphore_signal_all_trap
    452 	SVC	$0x80
    453 	MOVW	R0, ret+8(FP)
    454 	RET
    455 
    456 // int32 runtimekqueue(void)
    457 TEXT runtimekqueue(SB),NOSPLIT,$0
    458 	MOVW	$SYS_kqueue, R16
    459 	SVC	$0x80
    460 	BCC	2(PC)
    461 	NEG	R0, R0
    462 	MOVW	R0, ret+0(FP)
    463 	RET
    464 
    465 // int32 runtimekevent(int kq, Kevent *ch, int nch, Kevent *ev, int nev, Timespec *ts)
    466 TEXT runtimekevent(SB),NOSPLIT,$0
    467 	MOVW	kq+0(FP), R0
    468 	MOVD	ch+8(FP), R1
    469 	MOVW	nch+16(FP), R2
    470 	MOVD	ev+24(FP), R3
    471 	MOVW	nev+32(FP), R4
    472 	MOVD	ts+40(FP), R5
    473 	MOVW	$SYS_kevent, R16
    474 	SVC	$0x80
    475 	BCC	2(PC)
    476 	NEG	R0, R0
    477 	MOVW	R0, ret+48(FP)
    478 	RET
    479 
    480 // int32 runtimecloseonexec(int32 fd)
    481 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    482 	MOVW	fd+0(FP), R0
    483 	MOVW	$2, R1	// F_SETFD
    484 	MOVW	$1, R2	// FD_CLOEXEC
    485 	MOVW	$SYS_fcntl, R16
    486 	SVC	$0x80
    487 	RET
    488 
    489 // sigaltstack on some darwin/arm version is buggy and will always
    490 // run the signal handler on the main stack, so our sigtramp has
    491 // to do the stack switch ourselves.
    492 TEXT runtimesigaltstack(SB),NOSPLIT,$0
    493 	RET
    494