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 // System calls and other sys.stuff for ARM, 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 	MOVW	$0, R8
     41 	MOVW	R8, (R8)
     42 	B		0(PC)
     43 
     44 TEXT runtimeopen(SB),NOSPLIT,$0
     45 	MOVW	name+0(FP), R0
     46 	MOVW	mode+4(FP), R1
     47 	MOVW	perm+8(FP), R2
     48 	MOVW	$SYS_open, R12
     49 	SWI	$0x80
     50 	MOVW.CS	$-1, R0
     51 	MOVW	R0, ret+12(FP)
     52 	RET
     53 
     54 TEXT runtimeclosefd(SB),NOSPLIT,$0
     55 	MOVW	fd+0(FP), R0
     56 	MOVW	$SYS_close, R12
     57 	SWI	$0x80
     58 	MOVW.CS	$-1, R0
     59 	MOVW	R0, ret+4(FP)
     60 	RET
     61 
     62 TEXT runtimewrite(SB),NOSPLIT,$0
     63 	MOVW	fd+0(FP), R0
     64 	MOVW	p+4(FP), R1
     65 	MOVW	n+8(FP), R2
     66 	MOVW	$SYS_write, R12
     67 	SWI	$0x80
     68 	MOVW.CS	$-1, R0
     69 	MOVW	R0, ret+12(FP)
     70 	RET
     71 
     72 TEXT runtimeread(SB),NOSPLIT,$0
     73 	MOVW	fd+0(FP), R0
     74 	MOVW	p+4(FP), R1
     75 	MOVW	n+8(FP), R2
     76 	MOVW	$SYS_read, R12
     77 	SWI	$0x80
     78 	MOVW.CS	$-1, R0
     79 	MOVW	R0, ret+12(FP)
     80 	RET
     81 
     82 TEXT runtimeexit(SB),NOSPLIT,$-4
     83 	MOVW	code+0(FP), R0
     84 	MOVW	$SYS_exit, R12
     85 	SWI	$0x80
     86 	MOVW	$1234, R0
     87 	MOVW	$1002, R1
     88 	MOVW	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, R12
    101 	SWI	$0x80
    102 	MOVW	$1234, R0
    103 	MOVW	$1003, R1
    104 	MOVW	R0, (R1)	// fail hard
    105 
    106 // func exitThread(wait *uint32)
    107 TEXT runtimeexitThread(SB),NOSPLIT,$0-4
    108 	MOVW	wait+0(FP), R0
    109 	// We're done using the stack.
    110 	MOVW	$0, R2
    111 storeloop:
    112 	LDREX	(R0), R4          // loads R4
    113 	STREX	R2, (R0), R1      // stores R2
    114 	CMP	$0, R1
    115 	BNE	storeloop
    116 	JMP	exit1<>(SB)
    117 
    118 TEXT runtimeraise(SB),NOSPLIT,$0
    119 	// Ideally we'd send the signal to the current thread,
    120 	// not the whole process, but that's too hard on OS X.
    121 	JMP	runtimeraiseproc(SB)
    122 
    123 TEXT runtimeraiseproc(SB),NOSPLIT,$24
    124 	MOVW	$SYS_getpid, R12
    125 	SWI	$0x80
    126 	// arg 1 pid already in R0 from getpid
    127 	MOVW	sig+0(FP), R1	// arg 2 - signal
    128 	MOVW	$1, R2	// arg 3 - posix
    129 	MOVW	$SYS_kill, R12
    130 	SWI $0x80
    131 	RET
    132 
    133 TEXT runtimemmap(SB),NOSPLIT,$0
    134 	MOVW	addr+0(FP), R0
    135 	MOVW	n+4(FP), R1
    136 	MOVW	prot+8(FP), R2
    137 	MOVW	flags+12(FP), R3
    138 	MOVW	fd+16(FP), R4
    139 	MOVW	off+20(FP), R5
    140 	MOVW	$0, R6 // off_t is uint64_t
    141 	MOVW	$SYS_mmap, R12
    142 	SWI	$0x80
    143 	MOVW	$0, R1
    144 	BCC     ok
    145 	MOVW	R1, p+24(FP)
    146 	MOVW	R0, err+28(FP)
    147 	RET
    148 ok:
    149 	MOVW	R0, p+24(FP)
    150 	MOVW	R1, err+28(FP)
    151 	RET
    152 
    153 TEXT runtimemunmap(SB),NOSPLIT,$0
    154 	MOVW	addr+0(FP), R0
    155 	MOVW	n+4(FP), R1
    156 	MOVW	$SYS_munmap, R12
    157 	SWI	$0x80
    158 	BL.CS	notok<>(SB)
    159 	RET
    160 
    161 TEXT runtimemadvise(SB),NOSPLIT,$0
    162 	MOVW	addr+0(FP), R0
    163 	MOVW	n+4(FP), R1
    164 	MOVW	flags+8(FP), R2
    165 	MOVW	$SYS_madvise, R12
    166 	SWI	$0x80
    167 	BL.CS	notok<>(SB)
    168 	RET
    169 
    170 TEXT runtimesetitimer(SB),NOSPLIT,$0
    171 	MOVW	mode+0(FP), R0
    172 	MOVW	new+4(FP), R1
    173 	MOVW	old+8(FP), R2
    174 	MOVW	$SYS_setitimer, R12
    175 	SWI	$0x80
    176 	RET
    177 
    178 TEXT runtimewalltime(SB), 7, $32
    179 	MOVW	$8(R13), R0  // timeval
    180 	MOVW	$0, R1  // zone
    181 	MOVW	$0, R2	// see issue 16570
    182 	MOVW	$SYS_gettimeofday, R12
    183 	SWI	$0x80 // Note: R0 is tv_sec, R1 is tv_usec
    184 	CMP	$0, R0
    185 	BNE	inreg
    186 	MOVW	8(R13), R0
    187 	MOVW	12(R13), R1
    188 inreg:
    189 	MOVW    R1, R2  // usec
    190 	MOVW	R0, sec_lo+0(FP)
    191 	MOVW	$0, R1
    192 	MOVW	R1, sec_hi+4(FP)
    193 	MOVW	$1000, R3
    194 	MUL	R3, R2
    195 	MOVW	R2, nsec+8(FP)
    196 	RET
    197 
    198 TEXT runtimenanotime(SB),NOSPLIT,$32
    199 	MOVW	$8(R13), R0  // timeval
    200 	MOVW	$0, R1  // zone
    201 	MOVW	$0, R2	// see issue 16570
    202 	MOVW	$SYS_gettimeofday, R12
    203 	SWI	$0x80 // Note: R0 is tv_sec, R1 is tv_usec
    204 	CMP	$0, R0
    205 	BNE	inreg
    206 	MOVW	8(R13), R0
    207 	MOVW	12(R13), R1
    208 inreg:
    209 	MOVW    R1, R2
    210 	MOVW	$1000000000, R3
    211 	MULLU	R0, R3, (R1, R0)
    212 	MOVW	$1000, R3
    213 	MOVW	$0, R4
    214 	MUL	R3, R2
    215 	ADD.S	R2, R0
    216 	ADC	R4, R1
    217 
    218 	MOVW	R0, ret_lo+0(FP)
    219 	MOVW	R1, ret_hi+4(FP)
    220 	RET
    221 
    222 TEXT runtimesigfwd(SB),NOSPLIT,$0-16
    223 	MOVW	sig+4(FP), R0
    224 	MOVW	info+8(FP), R1
    225 	MOVW	ctx+12(FP), R2
    226 	MOVW	fn+0(FP), R11
    227 	MOVW	R13, R4
    228 	SUB	$24, R13
    229 	BIC	$0x7, R13 // alignment for ELF ABI
    230 	BL	(R11)
    231 	MOVW	R4, R13
    232 	RET
    233 
    234 // Sigtramp's job is to call the actual signal handler.
    235 // It is called with the following arguments on the stack:
    236 //	 LR  	"return address" - ignored
    237 //	 R0  	actual handler
    238 //	 R1  	siginfo style - ignored
    239 //	 R2   	signal number
    240 //	 R3   	siginfo
    241 //	 -4(FP)	context, beware that 0(FP) is the saved LR
    242 TEXT runtimesigtramp(SB),NOSPLIT,$0
    243 	// this might be called in external code context,
    244 	// where g is not set.
    245 	// first save R0, because runtimeload_g will clobber it
    246 	MOVM.DB.W [R0], (R13)
    247 	MOVB	runtimeiscgo(SB), R0
    248 	CMP 	$0, R0
    249 	BL.NE	runtimeload_g(SB)
    250 
    251 	CMP 	$0, g
    252 	BNE 	cont
    253 	// fake function call stack frame for badsignal
    254 	// we only need to pass R2 (signal number), but
    255 	// badsignal will expect R2 at 4(R13), so we also
    256 	// push R1 onto stack. turns out we do need R1
    257 	// to do sigreturn.
    258 	MOVM.DB.W [R1,R2], (R13)
    259 	MOVW  	$runtimebadsignal(SB), R11
    260 	BL	(R11)
    261 	MOVM.IA.W [R1], (R13) // saved infostype
    262 	ADD		$(4+4), R13 // +4: also need to remove the pushed R0.
    263 	MOVW    ucontext-4(FP), R0 // load ucontext
    264 	B	ret
    265 
    266 cont:
    267 	// Restore R0
    268 	MOVM.IA.W (R13), [R0]
    269 
    270 	// NOTE: some Darwin/ARM kernels always use the main stack to run the
    271 	// signal handler. We need to switch to gsignal ourselves.
    272 	MOVW	g_m(g), R11
    273 	MOVW	m_gsignal(R11), R5
    274 	MOVW	(g_stack+stack_hi)(R5), R6
    275 	SUB		$28, R6
    276 
    277 	// copy arguments for call to sighandler
    278 	MOVW	R2, 4(R6) // signal num
    279 	MOVW	R3, 8(R6) // signal info
    280 	MOVW	g, 16(R6) // old_g
    281 	MOVW	context-4(FP), R4
    282 	MOVW	R4, 12(R6) // context
    283 
    284 	// Backup ucontext and infostyle
    285 	MOVW    R4, 20(R6)
    286 	MOVW    R1, 24(R6)
    287 
    288 	// switch stack and g
    289 	MOVW	R6, R13 // sigtramp is not re-entrant, so no need to back up R13.
    290 	MOVW	R5, g
    291 
    292 	BL	(R0)
    293 
    294 	// call sigreturn
    295 	MOVW	20(R13), R0	// saved ucontext
    296 	MOVW	24(R13), R1	// saved infostyle
    297 ret:
    298 	MOVW	$SYS_sigreturn, R12 // sigreturn(ucontext, infostyle)
    299 	SWI	$0x80
    300 
    301 	// if sigreturn fails, we can do nothing but exit
    302 	B	runtimeexit(SB)
    303 
    304 TEXT runtimesigprocmask(SB),NOSPLIT,$0
    305 	MOVW	how+0(FP), R0
    306 	MOVW	new+4(FP), R1
    307 	MOVW	old+8(FP), R2
    308 	MOVW	$SYS_pthread_sigmask, R12
    309 	SWI	$0x80
    310 	BL.CS	notok<>(SB)
    311 	RET
    312 
    313 TEXT runtimesigaction(SB),NOSPLIT,$0
    314 	MOVW	mode+0(FP), R0
    315 	MOVW	new+4(FP), R1
    316 	MOVW	old+8(FP), R2
    317 	MOVW	$SYS_sigaction, R12
    318 	SWI	$0x80
    319 	RET
    320 
    321 TEXT runtimeusleep(SB),NOSPLIT,$12
    322 	MOVW	usec+0(FP), R0
    323 	CALL	runtimeusplitR0(SB)
    324 	MOVW	R0, a-12(SP)
    325 	MOVW	R1, b-8(SP)
    326 
    327 	// select(0, 0, 0, 0, &tv)
    328 	MOVW	$0, R0
    329 	MOVW	$0, R1
    330 	MOVW	$0, R2
    331 	MOVW	$0, R3
    332 	MOVW	$a-12(SP), R4
    333 	MOVW	$SYS_select, R12
    334 	SWI	$0x80
    335 	RET
    336 
    337 TEXT publicationBarrier(SB),NOSPLIT,$-4-0
    338 	B	runtimearmPublicationBarrier(SB)
    339 
    340 TEXT runtimesysctl(SB),NOSPLIT,$0
    341 	MOVW	mib+0(FP), R0
    342 	MOVW	miblen+4(FP), R1
    343 	MOVW	out+8(FP), R2
    344 	MOVW	size+12(FP), R3
    345 	MOVW	dst+16(FP), R4
    346 	MOVW	ndst+20(FP), R5
    347 	MOVW	$SYS___sysctl, R12 // syscall entry
    348 	SWI	$0x80
    349 	BCC     sysctl_ret
    350 	RSB     $0, R0, R0
    351 	MOVW	R0, ret+24(FP)
    352 	RET
    353 sysctl_ret:
    354 	MOVW	$0, R0
    355 	MOVW	R0, ret+24(FP)
    356 	RET
    357 
    358 // Thread related functions
    359 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
    360 TEXT runtimebsdthread_create(SB),NOSPLIT,$0
    361 	// Set up arguments to bsdthread_create system call.
    362 	// The ones in quotes pass through to the thread callback
    363 	// uninterpreted, so we can put whatever we want there.
    364 	MOVW    fn+8(FP),    R0 // "func"
    365 	MOVW    arg+4(FP),   R1 // "arg"
    366 	MOVW    stk+0(FP),   R2 // stack
    367 	MOVW	$0x01000000, R4	// flags = PTHREAD_START_CUSTOM
    368 	MOVW	$0,          R5 // paranoia
    369 	MOVW	$SYS_bsdthread_create, R12
    370 	SWI	$0x80
    371 	BCC		create_ret
    372 	RSB 	$0, R0, R0
    373 	MOVW	R0, ret+12(FP)
    374 	RET
    375 create_ret:
    376 	MOVW	$0, R0
    377 	MOVW	R0, ret+12(FP)
    378 	RET
    379 
    380 // The thread that bsdthread_create creates starts executing here,
    381 // because we registered this function using bsdthread_register
    382 // at startup.
    383 //	R0 = "pthread"
    384 //	R1 = mach thread port
    385 //	R2 = "func" (= fn)
    386 //	R3 = "arg" (= m)
    387 //	R4 = stack
    388 //	R5 = flags (= 0)
    389 // XXX: how to deal with R4/SP? ref: Libc-594.9.1/arm/pthreads/thread_start.s
    390 TEXT runtimebsdthread_start(SB),NOSPLIT,$0
    391 	MOVW    R1, m_procid(R3) // thread port is m->procid
    392 	MOVW	m_g0(R3), g
    393 	MOVW	R3, g_m(g)
    394 	// ARM don't have runtimestackcheck(SB)
    395 	// disable runfast mode of vfp
    396 	EOR     R12, R12
    397 	WORD    $0xeee1ca10 // fmxr	fpscr, ip
    398 	BL      (R2) // fn
    399 	BL      exit1<>(SB)
    400 	RET
    401 
    402 // int32 bsdthread_register(void)
    403 // registers callbacks for threadstart (see bsdthread_create above
    404 // and wqthread and pthsize (not used).  returns 0 on success.
    405 TEXT runtimebsdthread_register(SB),NOSPLIT,$0
    406 	MOVW	$runtimebsdthread_start(SB), R0	// threadstart
    407 	MOVW	$0, R1	// wqthread, not used by us
    408 	MOVW	$0, R2	// pthsize, not used by us
    409 	MOVW	$0, R3 	// dummy_value [sic]
    410 	MOVW	$0, R4	// targetconc_ptr
    411 	MOVW	$0, R5	// dispatchqueue_offset
    412 	MOVW	$SYS_bsdthread_register, R12	// bsdthread_register
    413 	SWI	$0x80
    414 	MOVW	R0, ret+0(FP)
    415 	RET
    416 
    417 // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
    418 TEXT runtimemach_msg_trap(SB),NOSPLIT,$0
    419 	MOVW    h+0(FP), R0
    420 	MOVW    op+4(FP), R1
    421 	MOVW    send_size+8(FP), R2
    422 	MOVW    rcv_size+12(FP), R3
    423 	MOVW    rcv_name+16(FP), R4
    424 	MOVW    timeout+20(FP), R5
    425 	MOVW    notify+24(FP), R6
    426 	MVN     $30, R12
    427 	SWI	$0x80
    428 	MOVW	R0, ret+28(FP)
    429 	RET
    430 
    431 TEXT runtimemach_task_self(SB),NOSPLIT,$0
    432 	MVN     $27, R12 // task_self_trap
    433 	SWI	$0x80
    434 	MOVW	R0, ret+0(FP)
    435 	RET
    436 
    437 TEXT runtimemach_thread_self(SB),NOSPLIT,$0
    438 	MVN 	$26, R12 // thread_self_trap
    439 	SWI	$0x80
    440 	MOVW	R0, ret+0(FP)
    441 	RET
    442 
    443 TEXT runtimemach_reply_port(SB),NOSPLIT,$0
    444 	MVN 	$25, R12	// mach_reply_port
    445 	SWI	$0x80
    446 	MOVW	R0, ret+0(FP)
    447 	RET
    448 
    449 // Mach provides trap versions of the semaphore ops,
    450 // instead of requiring the use of RPC.
    451 
    452 // uint32 mach_semaphore_wait(uint32)
    453 TEXT runtimemach_semaphore_wait(SB),NOSPLIT,$0
    454 	MOVW	sema+0(FP), R0
    455 	MVN 	$35, R12	// semaphore_wait_trap
    456 	SWI	$0x80
    457 	MOVW	R0, ret+4(FP)
    458 	RET
    459 
    460 // uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
    461 TEXT runtimemach_semaphore_timedwait(SB),NOSPLIT,$0
    462 	MOVW	sema+0(FP), R0
    463 	MOVW	sec+4(FP), R1
    464 	MOVW	nsec+8(FP), R2
    465 	MVN 	$37, R12	// semaphore_timedwait_trap
    466 	SWI	$0x80
    467 	MOVW	R0, ret+12(FP)
    468 	RET
    469 
    470 // uint32 mach_semaphore_signal(uint32)
    471 TEXT runtimemach_semaphore_signal(SB),NOSPLIT,$0
    472 	MOVW    sema+0(FP), R0
    473 	MVN 	$32, R12	// semaphore_signal_trap
    474 	SWI	$0x80
    475 	MOVW	R0, ret+4(FP)
    476 	RET
    477 
    478 // uint32 mach_semaphore_signal_all(uint32)
    479 TEXT runtimemach_semaphore_signal_all(SB),NOSPLIT,$0
    480 	MOVW	sema+0(FP), R0
    481 	MVN 	$33, R12	// semaphore_signal_all_trap
    482 	SWI	$0x80
    483 	MOVW	R0, ret+4(FP)
    484 	RET
    485 
    486 // int32 runtimekqueue(void)
    487 TEXT runtimekqueue(SB),NOSPLIT,$0
    488 	MOVW	$SYS_kqueue, R12
    489 	SWI	$0x80
    490 	RSB.CS	$0, R0, R0
    491 	MOVW	R0, ret+0(FP)
    492 	RET
    493 
    494 // int32 runtimekevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout)
    495 TEXT runtimekevent(SB),NOSPLIT,$0
    496 	MOVW	$SYS_kevent, R12
    497 	MOVW	kq+0(FP), R0
    498 	MOVW	ch+4(FP), R1
    499 	MOVW	nch+8(FP), R2
    500 	MOVW	ev+12(FP), R3
    501 	MOVW	nev+16(FP), R4
    502 	MOVW	ts+20(FP), R5
    503 	SWI	$0x80
    504 	RSB.CS	$0, R0, R0
    505 	MOVW	R0, ret+24(FP)
    506 	RET
    507 
    508 // int32 runtimecloseonexec(int32 fd)
    509 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    510 	MOVW	$SYS_fcntl, R12
    511 	MOVW	fd+0(FP), R0
    512 	MOVW	$2, R1	// F_SETFD
    513 	MOVW	$1, R2	// FD_CLOEXEC
    514 	SWI	$0x80
    515 	RET
    516 
    517 // sigaltstack on some darwin/arm version is buggy and will always
    518 // run the signal handler on the main stack, so our sigtramp has
    519 // to do the stack switch ourselves.
    520 TEXT runtimesigaltstack(SB),NOSPLIT,$0
    521 	RET
    522