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
    159 	MOVQ	$0, SI
    160 	MOVQ	$0, DX  // required as of Sierra; Issue 16570
    161 	MOVL	$(0x2000000+116), AX // gettimeofday
    162 	SYSCALL
    163 	CMPQ	AX, $0
    164 	JNE	inreg
    165 	MOVQ	0(SP), AX
    166 	MOVL	8(SP), DX
    167 inreg:
    168 	// sec is in AX, usec in DX
    169 	// return nsec in AX
    170 	IMULQ	$1000000000, AX
    171 	IMULQ	$1000, DX
    172 	ADDQ	DX, AX
    173 	RET
    174 
    175 TEXT runtimenanotime(SB),NOSPLIT,$0-8
    176 	CALL	nanotime<>(SB)
    177 	MOVQ	AX, ret+0(FP)
    178 	RET
    179 
    180 // func now() (sec int64, nsec int32)
    181 TEXT timenow(SB),NOSPLIT,$0-12
    182 	CALL	nanotime<>(SB)
    183 
    184 	// generated code for
    185 	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
    186 	// adapted to reduce duplication
    187 	MOVQ	AX, CX
    188 	MOVQ	$1360296554856532783, AX
    189 	MULQ	CX
    190 	ADDQ	CX, DX
    191 	RCRQ	$1, DX
    192 	SHRQ	$29, DX
    193 	MOVQ	DX, sec+0(FP)
    194 	IMULQ	$1000000000, DX
    195 	SUBQ	DX, CX
    196 	MOVL	CX, nsec+8(FP)
    197 	RET
    198 
    199 TEXT runtimesigprocmask(SB),NOSPLIT,$0
    200 	MOVL	how+0(FP), DI
    201 	MOVQ	new+8(FP), SI
    202 	MOVQ	old+16(FP), DX
    203 	MOVL	$(0x2000000+329), AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
    204 	SYSCALL
    205 	JCC	2(PC)
    206 	MOVL	$0xf1, 0xf1  // crash
    207 	RET
    208 
    209 TEXT runtimesigaction(SB),NOSPLIT,$0-24
    210 	MOVL	mode+0(FP), DI		// arg 1 sig
    211 	MOVQ	new+8(FP), SI		// arg 2 act
    212 	MOVQ	old+16(FP), DX		// arg 3 oact
    213 	MOVQ	old+16(FP), CX		// arg 3 oact
    214 	MOVQ	old+16(FP), R10		// arg 3 oact
    215 	MOVL	$(0x2000000+46), AX	// syscall entry
    216 	SYSCALL
    217 	JCC	2(PC)
    218 	MOVL	$0xf1, 0xf1  // crash
    219 	RET
    220 
    221 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    222 	MOVQ	fn+0(FP),    AX
    223 	MOVL	sig+8(FP),   DI
    224 	MOVQ	info+16(FP), SI
    225 	MOVQ	ctx+24(FP),  DX
    226 	PUSHQ	BP
    227 	MOVQ	SP, BP
    228 	ANDQ	$~15, SP     // alignment for x86_64 ABI
    229 	CALL	AX
    230 	MOVQ	BP, SP
    231 	POPQ	BP
    232 	RET
    233 
    234 TEXT runtimesigtramp(SB),NOSPLIT,$32
    235 	MOVL SI, 24(SP) // save infostyle for sigreturn below
    236 	MOVL DX, 0(SP)  // sig
    237 	MOVQ CX, 8(SP)  // info
    238 	MOVQ R8, 16(SP) // ctx
    239 	MOVQ $runtimesigtrampgo(SB), AX
    240 	CALL AX
    241 	MOVQ 16(SP), DI // ctx
    242 	MOVL 24(SP), SI // infostyle
    243 	MOVL $(0x2000000+184), AX
    244 	SYSCALL
    245 	INT $3 // not reached
    246 
    247 TEXT runtimemmap(SB),NOSPLIT,$0
    248 	MOVQ	addr+0(FP), DI		// arg 1 addr
    249 	MOVQ	n+8(FP), SI		// arg 2 len
    250 	MOVL	prot+16(FP), DX		// arg 3 prot
    251 	MOVL	flags+20(FP), R10		// arg 4 flags
    252 	MOVL	fd+24(FP), R8		// arg 5 fid
    253 	MOVL	off+28(FP), R9		// arg 6 offset
    254 	MOVL	$(0x2000000+197), AX	// syscall entry
    255 	SYSCALL
    256 	MOVQ	AX, ret+32(FP)
    257 	RET
    258 
    259 TEXT runtimemunmap(SB),NOSPLIT,$0
    260 	MOVQ	addr+0(FP), DI		// arg 1 addr
    261 	MOVQ	n+8(FP), SI		// arg 2 len
    262 	MOVL	$(0x2000000+73), AX	// syscall entry
    263 	SYSCALL
    264 	JCC	2(PC)
    265 	MOVL	$0xf1, 0xf1  // crash
    266 	RET
    267 
    268 TEXT runtimesigaltstack(SB),NOSPLIT,$0
    269 	MOVQ	new+0(FP), DI
    270 	MOVQ	old+8(FP), SI
    271 	MOVQ	$(0x2000000+53), AX
    272 	SYSCALL
    273 	JCC	2(PC)
    274 	MOVL	$0xf1, 0xf1  // crash
    275 	RET
    276 
    277 TEXT runtimeusleep(SB),NOSPLIT,$16
    278 	MOVL	$0, DX
    279 	MOVL	usec+0(FP), AX
    280 	MOVL	$1000000, CX
    281 	DIVL	CX
    282 	MOVQ	AX, 0(SP)  // sec
    283 	MOVL	DX, 8(SP)  // usec
    284 
    285 	// select(0, 0, 0, 0, &tv)
    286 	MOVL	$0, DI
    287 	MOVL	$0, SI
    288 	MOVL	$0, DX
    289 	MOVL	$0, R10
    290 	MOVQ	SP, R8
    291 	MOVL	$(0x2000000+93), AX
    292 	SYSCALL
    293 	RET
    294 
    295 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
    296 TEXT runtimebsdthread_create(SB),NOSPLIT,$0
    297 	// Set up arguments to bsdthread_create system call.
    298 	// The ones in quotes pass through to the thread callback
    299 	// uninterpreted, so we can put whatever we want there.
    300 	MOVQ	fn+16(FP),   DI
    301 	MOVQ	arg+8(FP),  SI
    302 	MOVQ	stk+0(FP),   DX
    303 	MOVQ	$0x01000000, R8  // flags = PTHREAD_START_CUSTOM
    304 	MOVQ	$0,          R9  // paranoia
    305 	MOVQ	$0,          R10 // paranoia, "pthread"
    306 	MOVQ	$(0x2000000+360), AX	// bsdthread_create
    307 	SYSCALL
    308 	JCC 4(PC)
    309 	NEGQ	AX
    310 	MOVL	AX, ret+24(FP)
    311 	RET
    312 	MOVL	$0, AX
    313 	MOVL	AX, ret+24(FP)
    314 	RET
    315 
    316 // The thread that bsdthread_create creates starts executing here,
    317 // because we registered this function using bsdthread_register
    318 // at startup.
    319 //	DI = "pthread"
    320 //	SI = mach thread port
    321 //	DX = "func" (= fn)
    322 //	CX = "arg" (= m)
    323 //	R8 = stack
    324 //	R9 = flags (= 0)
    325 //	SP = stack - C_64_REDZONE_LEN (= stack - 128)
    326 TEXT runtimebsdthread_start(SB),NOSPLIT,$0
    327 	MOVQ	R8, SP		// empirically, SP is very wrong but R8 is right
    328 
    329 	PUSHQ	DX
    330 	PUSHQ	CX
    331 	PUSHQ	SI
    332 
    333 	// set up thread local storage pointing at m->tls.
    334 	LEAQ	m_tls(CX), DI
    335 	CALL	runtimesettls(SB)
    336 
    337 	POPQ	SI
    338 	POPQ	CX
    339 	POPQ	DX
    340 
    341 	get_tls(BX)
    342 	MOVQ	SI, m_procid(CX)	// thread port is m->procid
    343 	MOVQ	m_g0(CX), AX
    344 	MOVQ	AX, g(BX)
    345 	MOVQ	CX, g_m(AX)
    346 	CALL	runtimestackcheck(SB)	// smashes AX, CX
    347 	CALL	DX	// fn
    348 	CALL	runtimeexit1(SB)
    349 	RET
    350 
    351 // func bsdthread_register() int32
    352 // registers callbacks for threadstart (see bsdthread_create above
    353 // and wqthread and pthsize (not used).  returns 0 on success.
    354 TEXT runtimebsdthread_register(SB),NOSPLIT,$0
    355 	MOVQ	$runtimebsdthread_start(SB), DI	// threadstart
    356 	MOVQ	$0, SI	// wqthread, not used by us
    357 	MOVQ	$0, DX	// pthsize, not used by us
    358 	MOVQ	$0, R10	// dummy_value [sic]
    359 	MOVQ	$0, R8	// targetconc_ptr
    360 	MOVQ	$0, R9	// dispatchqueue_offset
    361 	MOVQ	$(0x2000000+366), AX	// bsdthread_register
    362 	SYSCALL
    363 	JCC 4(PC)
    364 	NEGQ	AX
    365 	MOVL	AX, ret+0(FP)
    366 	RET
    367 	MOVL	$0, AX
    368 	MOVL	AX, ret+0(FP)
    369 	RET
    370 
    371 // Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
    372 
    373 // func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
    374 TEXT runtimemach_msg_trap(SB),NOSPLIT,$0
    375 	MOVQ	h+0(FP), DI
    376 	MOVL	op+8(FP), SI
    377 	MOVL	send_size+12(FP), DX
    378 	MOVL	rcv_size+16(FP), R10
    379 	MOVL	rcv_name+20(FP), R8
    380 	MOVL	timeout+24(FP), R9
    381 	MOVL	notify+28(FP), R11
    382 	PUSHQ	R11	// seventh arg, on stack
    383 	MOVL	$(0x1000000+31), AX	// mach_msg_trap
    384 	SYSCALL
    385 	POPQ	R11
    386 	MOVL	AX, ret+32(FP)
    387 	RET
    388 
    389 TEXT runtimemach_task_self(SB),NOSPLIT,$0
    390 	MOVL	$(0x1000000+28), AX	// task_self_trap
    391 	SYSCALL
    392 	MOVL	AX, ret+0(FP)
    393 	RET
    394 
    395 TEXT runtimemach_thread_self(SB),NOSPLIT,$0
    396 	MOVL	$(0x1000000+27), AX	// thread_self_trap
    397 	SYSCALL
    398 	MOVL	AX, ret+0(FP)
    399 	RET
    400 
    401 TEXT runtimemach_reply_port(SB),NOSPLIT,$0
    402 	MOVL	$(0x1000000+26), AX	// mach_reply_port
    403 	SYSCALL
    404 	MOVL	AX, ret+0(FP)
    405 	RET
    406 
    407 // Mach provides trap versions of the semaphore ops,
    408 // instead of requiring the use of RPC.
    409 
    410 // func mach_semaphore_wait(sema uint32) int32
    411 TEXT runtimemach_semaphore_wait(SB),NOSPLIT,$0
    412 	MOVL	sema+0(FP), DI
    413 	MOVL	$(0x1000000+36), AX	// semaphore_wait_trap
    414 	SYSCALL
    415 	MOVL	AX, ret+8(FP)
    416 	RET
    417 
    418 // func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
    419 TEXT runtimemach_semaphore_timedwait(SB),NOSPLIT,$0
    420 	MOVL	sema+0(FP), DI
    421 	MOVL	sec+4(FP), SI
    422 	MOVL	nsec+8(FP), DX
    423 	MOVL	$(0x1000000+38), AX	// semaphore_timedwait_trap
    424 	SYSCALL
    425 	MOVL	AX, ret+16(FP)
    426 	RET
    427 
    428 // func mach_semaphore_signal(sema uint32) int32
    429 TEXT runtimemach_semaphore_signal(SB),NOSPLIT,$0
    430 	MOVL	sema+0(FP), DI
    431 	MOVL	$(0x1000000+33), AX	// semaphore_signal_trap
    432 	SYSCALL
    433 	MOVL	AX, ret+8(FP)
    434 	RET
    435 
    436 // func mach_semaphore_signal_all(sema uint32) int32
    437 TEXT runtimemach_semaphore_signal_all(SB),NOSPLIT,$0
    438 	MOVL	sema+0(FP), DI
    439 	MOVL	$(0x1000000+34), AX	// semaphore_signal_all_trap
    440 	SYSCALL
    441 	MOVL	AX, ret+8(FP)
    442 	RET
    443 
    444 // set tls base to DI
    445 TEXT runtimesettls(SB),NOSPLIT,$32
    446 	/*
    447 	* Same as in sys_darwin_386.s:/ugliness, different constant.
    448 	* See cgo/gcc_darwin_amd64.c for the derivation
    449 	* of the constant.
    450 	*/
    451 	SUBQ $0x8a0, DI
    452 
    453 	MOVL	$(0x3000000+3), AX	// thread_fast_set_cthread_self - machdep call #3
    454 	SYSCALL
    455 	RET
    456 
    457 TEXT runtimesysctl(SB),NOSPLIT,$0
    458 	MOVQ	mib+0(FP), DI
    459 	MOVL	miblen+8(FP), SI
    460 	MOVQ	out+16(FP), DX
    461 	MOVQ	size+24(FP), R10
    462 	MOVQ	dst+32(FP), R8
    463 	MOVQ	ndst+40(FP), R9
    464 	MOVL	$(0x2000000+202), AX	// syscall entry
    465 	SYSCALL
    466 	JCC 4(PC)
    467 	NEGQ	AX
    468 	MOVL	AX, ret+48(FP)
    469 	RET
    470 	MOVL	$0, AX
    471 	MOVL	AX, ret+48(FP)
    472 	RET
    473 
    474 // func kqueue() int32
    475 TEXT runtimekqueue(SB),NOSPLIT,$0
    476 	MOVQ    $0, DI
    477 	MOVQ    $0, SI
    478 	MOVQ    $0, DX
    479 	MOVL	$(0x2000000+362), AX
    480 	SYSCALL
    481 	JCC	2(PC)
    482 	NEGQ	AX
    483 	MOVL	AX, ret+0(FP)
    484 	RET
    485 
    486 // func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
    487 TEXT runtimekevent(SB),NOSPLIT,$0
    488 	MOVL    kq+0(FP), DI
    489 	MOVQ    ch+8(FP), SI
    490 	MOVL    nch+16(FP), DX
    491 	MOVQ    ev+24(FP), R10
    492 	MOVL    nev+32(FP), R8
    493 	MOVQ    ts+40(FP), R9
    494 	MOVL	$(0x2000000+363), AX
    495 	SYSCALL
    496 	JCC	2(PC)
    497 	NEGQ	AX
    498 	MOVL	AX, ret+48(FP)
    499 	RET
    500 
    501 // func closeonexec(fd int32)
    502 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    503 	MOVL    fd+0(FP), DI  // fd
    504 	MOVQ    $2, SI  // F_SETFD
    505 	MOVQ    $1, DX  // FD_CLOEXEC
    506 	MOVL	$(0x2000000+92), AX  // fcntl
    507 	SYSCALL
    508 	RET
    509