Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 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 //
      6 // System calls and other sys.stuff for AMD64, Darwin
      7 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
      8 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
      9 //
     10 // The low 24 bits are the system call number.
     11 // The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
     12 //
     13 
     14 #include "go_asm.h"
     15 #include "go_tls.h"
     16 #include "textflag.h"
     17 
     18 // Exit the entire program (like C exit)
     19 TEXT runtimeexit(SB),NOSPLIT,$0
     20 	MOVL	code+0(FP), DI		// arg 1 exit status
     21 	MOVL	$(0x2000000+1), AX	// syscall entry
     22 	SYSCALL
     23 	MOVL	$0xf1, 0xf1  // crash
     24 	RET
     25 
     26 // Exit this OS thread (like pthread_exit, which eventually
     27 // calls __bsdthread_terminate).
     28 TEXT runtimeexit1(SB),NOSPLIT,$0
     29 	MOVL	code+0(FP), DI		// arg 1 exit status
     30 	MOVL	$(0x2000000+361), AX	// syscall entry
     31 	SYSCALL
     32 	MOVL	$0xf1, 0xf1  // crash
     33 	RET
     34 
     35 TEXT runtimeopen(SB),NOSPLIT,$0
     36 	MOVQ	name+0(FP), DI		// arg 1 pathname
     37 	MOVL	mode+8(FP), SI		// arg 2 flags
     38 	MOVL	perm+12(FP), DX		// arg 3 mode
     39 	MOVL	$(0x2000000+5), AX	// syscall entry
     40 	SYSCALL
     41 	JCC	2(PC)
     42 	MOVL	$-1, AX
     43 	MOVL	AX, ret+16(FP)
     44 	RET
     45 
     46 TEXT runtimeclosefd(SB),NOSPLIT,$0
     47 	MOVL	fd+0(FP), DI		// arg 1 fd
     48 	MOVL	$(0x2000000+6), AX	// syscall entry
     49 	SYSCALL
     50 	JCC	2(PC)
     51 	MOVL	$-1, AX
     52 	MOVL	AX, ret+8(FP)
     53 	RET
     54 
     55 TEXT runtimeread(SB),NOSPLIT,$0
     56 	MOVL	fd+0(FP), DI		// arg 1 fd
     57 	MOVQ	p+8(FP), SI		// arg 2 buf
     58 	MOVL	n+16(FP), DX		// arg 3 count
     59 	MOVL	$(0x2000000+3), AX	// syscall entry
     60 	SYSCALL
     61 	JCC	2(PC)
     62 	MOVL	$-1, AX
     63 	MOVL	AX, ret+24(FP)
     64 	RET
     65 
     66 TEXT runtimewrite(SB),NOSPLIT,$0
     67 	MOVQ	fd+0(FP), DI		// arg 1 fd
     68 	MOVQ	p+8(FP), SI		// arg 2 buf
     69 	MOVL	n+16(FP), DX		// arg 3 count
     70 	MOVL	$(0x2000000+4), AX	// syscall entry
     71 	SYSCALL
     72 	JCC	2(PC)
     73 	MOVL	$-1, AX
     74 	MOVL	AX, ret+24(FP)
     75 	RET
     76 
     77 TEXT runtimeraise(SB),NOSPLIT,$0
     78 	// Ideally we'd send the signal to the current thread,
     79 	// not the whole process, but that's too hard on OS X.
     80 	JMP	runtimeraiseproc(SB)
     81 
     82 TEXT runtimeraiseproc(SB),NOSPLIT,$24
     83 	MOVL	$(0x2000000+20), AX // getpid
     84 	SYSCALL
     85 	MOVQ	AX, DI	// arg 1 - pid
     86 	MOVL	sig+0(FP), SI	// arg 2 - signal
     87 	MOVL	$1, DX	// arg 3 - posix
     88 	MOVL	$(0x2000000+37), AX // kill
     89 	SYSCALL
     90 	RET
     91 
     92 TEXT runtimesetitimer(SB), NOSPLIT, $0
     93 	MOVL	mode+0(FP), DI
     94 	MOVQ	new+8(FP), SI
     95 	MOVQ	old+16(FP), DX
     96 	MOVL	$(0x2000000+83), AX	// syscall entry
     97 	SYSCALL
     98 	RET
     99 
    100 TEXT runtimemadvise(SB), NOSPLIT, $0
    101 	MOVQ	addr+0(FP), DI		// arg 1 addr
    102 	MOVQ	n+8(FP), SI		// arg 2 len
    103 	MOVL	flags+16(FP), DX		// arg 3 advice
    104 	MOVL	$(0x2000000+75), AX	// syscall entry madvise
    105 	SYSCALL
    106 	// ignore failure - maybe pages are locked
    107 	RET
    108 
    109 // OS X comm page time offsets
    110 // http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
    111 #define	nt_tsc_base	0x50
    112 #define	nt_scale	0x58
    113 #define	nt_shift	0x5c
    114 #define	nt_ns_base	0x60
    115 #define	nt_generation	0x68
    116 #define	gtod_generation	0x6c
    117 #define	gtod_ns_base	0x70
    118 #define	gtod_sec_base	0x78
    119 
    120 TEXT nanotime<>(SB), NOSPLIT, $32
    121 	MOVQ	$0x7fffffe00000, BP	/* comm page base */
    122 	// Loop trying to take a consistent snapshot
    123 	// of the time parameters.
    124 timeloop:
    125 	MOVL	gtod_generation(BP), R8
    126 	TESTL	R8, R8
    127 	JZ	systime
    128 	MOVL	nt_generation(BP), R9
    129 	TESTL	R9, R9
    130 	JZ	timeloop
    131 	RDTSC
    132 	MOVQ	nt_tsc_base(BP), R10
    133 	MOVL	nt_scale(BP), R11
    134 	MOVQ	nt_ns_base(BP), R12
    135 	CMPL	nt_generation(BP), R9
    136 	JNE	timeloop
    137 	MOVQ	gtod_ns_base(BP), R13
    138 	MOVQ	gtod_sec_base(BP), R14
    139 	CMPL	gtod_generation(BP), R8
    140 	JNE	timeloop
    141 
    142 	// Gathered all the data we need. Compute time.
    143 	//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
    144 	// The multiply and shift extracts the top 64 bits of the 96-bit product.
    145 	SHLQ	$32, DX
    146 	ADDQ	DX, AX
    147 	SUBQ	R10, AX
    148 	MULQ	R11
    149 	SHRQ	$32, AX:DX
    150 	ADDQ	R12, AX
    151 	SUBQ	R13, AX
    152 	IMULQ	$1000000000, R14
    153 	ADDQ	R14, AX
    154 	RET
    155 
    156 systime:
    157 	// Fall back to system call (usually first call in this thread).
    158 	MOVQ	SP, DI	// must be non-nil, unused
    159 	MOVQ	$0, SI
    160 	MOVL	$(0x2000000+116), AX
    161 	SYSCALL
    162 	// sec is in AX, usec in DX
    163 	// return nsec in AX
    164 	IMULQ	$1000000000, AX
    165 	IMULQ	$1000, DX
    166 	ADDQ	DX, AX
    167 	RET
    168 
    169 TEXT runtimenanotime(SB),NOSPLIT,$0-8
    170 	CALL	nanotime<>(SB)
    171 	MOVQ	AX, ret+0(FP)
    172 	RET
    173 
    174 // func now() (sec int64, nsec int32)
    175 TEXT timenow(SB),NOSPLIT,$0-12
    176 	CALL	nanotime<>(SB)
    177 
    178 	// generated code for
    179 	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
    180 	// adapted to reduce duplication
    181 	MOVQ	AX, CX
    182 	MOVQ	$1360296554856532783, AX
    183 	MULQ	CX
    184 	ADDQ	CX, DX
    185 	RCRQ	$1, DX
    186 	SHRQ	$29, DX
    187 	MOVQ	DX, sec+0(FP)
    188 	IMULQ	$1000000000, DX
    189 	SUBQ	DX, CX
    190 	MOVL	CX, nsec+8(FP)
    191 	RET
    192 
    193 TEXT runtimesigprocmask(SB),NOSPLIT,$0
    194 	MOVL	sig+0(FP), DI
    195 	MOVQ	new+8(FP), SI
    196 	MOVQ	old+16(FP), DX
    197 	MOVL	$(0x2000000+329), AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
    198 	SYSCALL
    199 	JCC	2(PC)
    200 	MOVL	$0xf1, 0xf1  // crash
    201 	RET
    202 
    203 TEXT runtimesigaction(SB),NOSPLIT,$0-24
    204 	MOVL	mode+0(FP), DI		// arg 1 sig
    205 	MOVQ	new+8(FP), SI		// arg 2 act
    206 	MOVQ	old+16(FP), DX		// arg 3 oact
    207 	MOVQ	old+16(FP), CX		// arg 3 oact
    208 	MOVQ	old+16(FP), R10		// arg 3 oact
    209 	MOVL	$(0x2000000+46), AX	// syscall entry
    210 	SYSCALL
    211 	JCC	2(PC)
    212 	MOVL	$0xf1, 0xf1  // crash
    213 	RET
    214 
    215 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    216 	MOVQ fn+0(FP),    AX
    217 	MOVQ sig+8(FP),   DI
    218 	MOVQ info+16(FP), SI
    219 	MOVQ ctx+24(FP),  DX
    220 	CALL AX
    221 	RET
    222 
    223 TEXT runtimesigreturn(SB),NOSPLIT,$0-12
    224 	MOVQ ctx+0(FP),        DI
    225 	MOVL infostyle+8(FP),  SI
    226 	MOVL $(0x2000000+184), AX
    227 	SYSCALL
    228 	INT $3 // not reached
    229 
    230 TEXT runtimesigtramp(SB),NOSPLIT,$32
    231 	MOVQ DI,  0(SP) // fn
    232 	MOVL SI,  8(SP) // infostyle
    233 	MOVL DX, 12(SP) // sig
    234 	MOVQ CX, 16(SP) // info
    235 	MOVQ R8, 24(SP) // ctx
    236 	MOVQ $runtimesigtrampgo(SB), AX
    237 	CALL AX
    238 
    239 TEXT runtimemmap(SB),NOSPLIT,$0
    240 	MOVQ	addr+0(FP), DI		// arg 1 addr
    241 	MOVQ	n+8(FP), SI		// arg 2 len
    242 	MOVL	prot+16(FP), DX		// arg 3 prot
    243 	MOVL	flags+20(FP), R10		// arg 4 flags
    244 	MOVL	fd+24(FP), R8		// arg 5 fid
    245 	MOVL	off+28(FP), R9		// arg 6 offset
    246 	MOVL	$(0x2000000+197), AX	// syscall entry
    247 	SYSCALL
    248 	MOVQ	AX, ret+32(FP)
    249 	RET
    250 
    251 TEXT runtimemunmap(SB),NOSPLIT,$0
    252 	MOVQ	addr+0(FP), DI		// arg 1 addr
    253 	MOVQ	n+8(FP), SI		// arg 2 len
    254 	MOVL	$(0x2000000+73), AX	// syscall entry
    255 	SYSCALL
    256 	JCC	2(PC)
    257 	MOVL	$0xf1, 0xf1  // crash
    258 	RET
    259 
    260 TEXT runtimesigaltstack(SB),NOSPLIT,$0
    261 	MOVQ	new+0(FP), DI
    262 	MOVQ	old+8(FP), SI
    263 	MOVQ	$(0x2000000+53), AX
    264 	SYSCALL
    265 	JCC	2(PC)
    266 	MOVL	$0xf1, 0xf1  // crash
    267 	RET
    268 
    269 TEXT runtimeusleep(SB),NOSPLIT,$16
    270 	MOVL	$0, DX
    271 	MOVL	usec+0(FP), AX
    272 	MOVL	$1000000, CX
    273 	DIVL	CX
    274 	MOVQ	AX, 0(SP)  // sec
    275 	MOVL	DX, 8(SP)  // usec
    276 
    277 	// select(0, 0, 0, 0, &tv)
    278 	MOVL	$0, DI
    279 	MOVL	$0, SI
    280 	MOVL	$0, DX
    281 	MOVL	$0, R10
    282 	MOVQ	SP, R8
    283 	MOVL	$(0x2000000+93), AX
    284 	SYSCALL
    285 	RET
    286 
    287 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
    288 TEXT runtimebsdthread_create(SB),NOSPLIT,$0
    289 	// Set up arguments to bsdthread_create system call.
    290 	// The ones in quotes pass through to the thread callback
    291 	// uninterpreted, so we can put whatever we want there.
    292 	MOVQ	fn+16(FP),   DI
    293 	MOVQ	arg+8(FP),  SI
    294 	MOVQ	stk+0(FP),   DX
    295 	MOVQ	$0x01000000, R8  // flags = PTHREAD_START_CUSTOM
    296 	MOVQ	$0,          R9  // paranoia
    297 	MOVQ	$0,          R10 // paranoia, "pthread"
    298 	MOVQ	$(0x2000000+360), AX	// bsdthread_create
    299 	SYSCALL
    300 	JCC 4(PC)
    301 	NEGQ	AX
    302 	MOVL	AX, ret+24(FP)
    303 	RET
    304 	MOVL	$0, AX
    305 	MOVL	AX, ret+24(FP)
    306 	RET
    307 
    308 // The thread that bsdthread_create creates starts executing here,
    309 // because we registered this function using bsdthread_register
    310 // at startup.
    311 //	DI = "pthread"
    312 //	SI = mach thread port
    313 //	DX = "func" (= fn)
    314 //	CX = "arg" (= m)
    315 //	R8 = stack
    316 //	R9 = flags (= 0)
    317 //	SP = stack - C_64_REDZONE_LEN (= stack - 128)
    318 TEXT runtimebsdthread_start(SB),NOSPLIT,$0
    319 	MOVQ	R8, SP		// empirically, SP is very wrong but R8 is right
    320 
    321 	PUSHQ	DX
    322 	PUSHQ	CX
    323 	PUSHQ	SI
    324 
    325 	// set up thread local storage pointing at m->tls.
    326 	LEAQ	m_tls(CX), DI
    327 	CALL	runtimesettls(SB)
    328 
    329 	POPQ	SI
    330 	POPQ	CX
    331 	POPQ	DX
    332 
    333 	get_tls(BX)
    334 	MOVQ	SI, m_procid(CX)	// thread port is m->procid
    335 	MOVQ	m_g0(CX), AX
    336 	MOVQ	AX, g(BX)
    337 	MOVQ	CX, g_m(AX)
    338 	CALL	runtimestackcheck(SB)	// smashes AX, CX
    339 	CALL	DX	// fn
    340 	CALL	runtimeexit1(SB)
    341 	RET
    342 
    343 // func bsdthread_register() int32
    344 // registers callbacks for threadstart (see bsdthread_create above
    345 // and wqthread and pthsize (not used).  returns 0 on success.
    346 TEXT runtimebsdthread_register(SB),NOSPLIT,$0
    347 	MOVQ	$runtimebsdthread_start(SB), DI	// threadstart
    348 	MOVQ	$0, SI	// wqthread, not used by us
    349 	MOVQ	$0, DX	// pthsize, not used by us
    350 	MOVQ	$0, R10	// dummy_value [sic]
    351 	MOVQ	$0, R8	// targetconc_ptr
    352 	MOVQ	$0, R9	// dispatchqueue_offset
    353 	MOVQ	$(0x2000000+366), AX	// bsdthread_register
    354 	SYSCALL
    355 	JCC 4(PC)
    356 	NEGQ	AX
    357 	MOVL	AX, ret+0(FP)
    358 	RET
    359 	MOVL	$0, AX
    360 	MOVL	AX, ret+0(FP)
    361 	RET
    362 
    363 // Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
    364 
    365 // func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
    366 TEXT runtimemach_msg_trap(SB),NOSPLIT,$0
    367 	MOVQ	h+0(FP), DI
    368 	MOVL	op+8(FP), SI
    369 	MOVL	send_size+12(FP), DX
    370 	MOVL	rcv_size+16(FP), R10
    371 	MOVL	rcv_name+20(FP), R8
    372 	MOVL	timeout+24(FP), R9
    373 	MOVL	notify+28(FP), R11
    374 	PUSHQ	R11	// seventh arg, on stack
    375 	MOVL	$(0x1000000+31), AX	// mach_msg_trap
    376 	SYSCALL
    377 	POPQ	R11
    378 	MOVL	AX, ret+32(FP)
    379 	RET
    380 
    381 TEXT runtimemach_task_self(SB),NOSPLIT,$0
    382 	MOVL	$(0x1000000+28), AX	// task_self_trap
    383 	SYSCALL
    384 	MOVL	AX, ret+0(FP)
    385 	RET
    386 
    387 TEXT runtimemach_thread_self(SB),NOSPLIT,$0
    388 	MOVL	$(0x1000000+27), AX	// thread_self_trap
    389 	SYSCALL
    390 	MOVL	AX, ret+0(FP)
    391 	RET
    392 
    393 TEXT runtimemach_reply_port(SB),NOSPLIT,$0
    394 	MOVL	$(0x1000000+26), AX	// mach_reply_port
    395 	SYSCALL
    396 	MOVL	AX, ret+0(FP)
    397 	RET
    398 
    399 // Mach provides trap versions of the semaphore ops,
    400 // instead of requiring the use of RPC.
    401 
    402 // func mach_semaphore_wait(sema uint32) int32
    403 TEXT runtimemach_semaphore_wait(SB),NOSPLIT,$0
    404 	MOVL	sema+0(FP), DI
    405 	MOVL	$(0x1000000+36), AX	// semaphore_wait_trap
    406 	SYSCALL
    407 	MOVL	AX, ret+8(FP)
    408 	RET
    409 
    410 // func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
    411 TEXT runtimemach_semaphore_timedwait(SB),NOSPLIT,$0
    412 	MOVL	sema+0(FP), DI
    413 	MOVL	sec+4(FP), SI
    414 	MOVL	nsec+8(FP), DX
    415 	MOVL	$(0x1000000+38), AX	// semaphore_timedwait_trap
    416 	SYSCALL
    417 	MOVL	AX, ret+16(FP)
    418 	RET
    419 
    420 // func mach_semaphore_signal(sema uint32) int32
    421 TEXT runtimemach_semaphore_signal(SB),NOSPLIT,$0
    422 	MOVL	sema+0(FP), DI
    423 	MOVL	$(0x1000000+33), AX	// semaphore_signal_trap
    424 	SYSCALL
    425 	MOVL	AX, ret+8(FP)
    426 	RET
    427 
    428 // func mach_semaphore_signal_all(sema uint32) int32
    429 TEXT runtimemach_semaphore_signal_all(SB),NOSPLIT,$0
    430 	MOVL	sema+0(FP), DI
    431 	MOVL	$(0x1000000+34), AX	// semaphore_signal_all_trap
    432 	SYSCALL
    433 	MOVL	AX, ret+8(FP)
    434 	RET
    435 
    436 // set tls base to DI
    437 TEXT runtimesettls(SB),NOSPLIT,$32
    438 	/*
    439 	* Same as in sys_darwin_386.s:/ugliness, different constant.
    440 	* See cgo/gcc_darwin_amd64.c for the derivation
    441 	* of the constant.
    442 	*/
    443 	SUBQ $0x8a0, DI
    444 
    445 	MOVL	$(0x3000000+3), AX	// thread_fast_set_cthread_self - machdep call #3
    446 	SYSCALL
    447 	RET
    448 
    449 TEXT runtimesysctl(SB),NOSPLIT,$0
    450 	MOVQ	mib+0(FP), DI
    451 	MOVL	miblen+8(FP), SI
    452 	MOVQ	out+16(FP), DX
    453 	MOVQ	size+24(FP), R10
    454 	MOVQ	dst+32(FP), R8
    455 	MOVQ	ndst+40(FP), R9
    456 	MOVL	$(0x2000000+202), AX	// syscall entry
    457 	SYSCALL
    458 	JCC 4(PC)
    459 	NEGQ	AX
    460 	MOVL	AX, ret+48(FP)
    461 	RET
    462 	MOVL	$0, AX
    463 	MOVL	AX, ret+48(FP)
    464 	RET
    465 
    466 // func kqueue() int32
    467 TEXT runtimekqueue(SB),NOSPLIT,$0
    468 	MOVQ    $0, DI
    469 	MOVQ    $0, SI
    470 	MOVQ    $0, DX
    471 	MOVL	$(0x2000000+362), AX
    472 	SYSCALL
    473 	JCC	2(PC)
    474 	NEGQ	AX
    475 	MOVL	AX, ret+0(FP)
    476 	RET
    477 
    478 // func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
    479 TEXT runtimekevent(SB),NOSPLIT,$0
    480 	MOVL    kq+0(FP), DI
    481 	MOVQ    ch+8(FP), SI
    482 	MOVL    nch+16(FP), DX
    483 	MOVQ    ev+24(FP), R10
    484 	MOVL    nev+32(FP), R8
    485 	MOVQ    ts+40(FP), R9
    486 	MOVL	$(0x2000000+363), AX
    487 	SYSCALL
    488 	JCC	2(PC)
    489 	NEGQ	AX
    490 	MOVL	AX, ret+48(FP)
    491 	RET
    492 
    493 // func closeonexec(fd int32)
    494 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    495 	MOVL    fd+0(FP), DI  // fd
    496 	MOVQ    $2, SI  // F_SETFD
    497 	MOVQ    $1, DX  // FD_CLOEXEC
    498 	MOVL	$(0x2000000+92), AX  // fcntl
    499 	SYSCALL
    500 	RET
    501