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