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, Linux
      7 //
      8 
      9 #include "go_asm.h"
     10 #include "go_tls.h"
     11 #include "textflag.h"
     12 
     13 #define SYS_read		0
     14 #define SYS_write		1
     15 #define SYS_open		2
     16 #define SYS_close		3
     17 #define SYS_mmap		9
     18 #define SYS_munmap		11
     19 #define SYS_brk 		12
     20 #define SYS_rt_sigaction	13
     21 #define SYS_rt_sigprocmask	14
     22 #define SYS_rt_sigreturn	15
     23 #define SYS_access		21
     24 #define SYS_sched_yield 	24
     25 #define SYS_mincore		27
     26 #define SYS_madvise		28
     27 #define SYS_setittimer		38
     28 #define SYS_getpid		39
     29 #define SYS_socket		41
     30 #define SYS_connect		42
     31 #define SYS_clone		56
     32 #define SYS_exit		60
     33 #define SYS_kill		62
     34 #define SYS_fcntl		72
     35 #define SYS_getrlimit		97
     36 #define SYS_sigaltstack 	131
     37 #define SYS_arch_prctl		158
     38 #define SYS_gettid		186
     39 #define SYS_tkill		200
     40 #define SYS_futex		202
     41 #define SYS_sched_getaffinity	204
     42 #define SYS_epoll_create	213
     43 #define SYS_exit_group		231
     44 #define SYS_epoll_wait		232
     45 #define SYS_epoll_ctl		233
     46 #define SYS_pselect6		270
     47 #define SYS_epoll_create1	291
     48 
     49 TEXT runtimeexit(SB),NOSPLIT,$0-4
     50 	MOVL	code+0(FP), DI
     51 	MOVL	$SYS_exit_group, AX
     52 	SYSCALL
     53 	RET
     54 
     55 // func exitThread(wait *uint32)
     56 TEXT runtimeexitThread(SB),NOSPLIT,$0-8
     57 	MOVQ	wait+0(FP), AX
     58 	// We're done using the stack.
     59 	MOVL	$0, (AX)
     60 	MOVL	$0, DI	// exit code
     61 	MOVL	$SYS_exit, AX
     62 	SYSCALL
     63 	// We may not even have a stack any more.
     64 	INT	$3
     65 	JMP	0(PC)
     66 
     67 TEXT runtimeopen(SB),NOSPLIT,$0-20
     68 	MOVQ	name+0(FP), DI
     69 	MOVL	mode+8(FP), SI
     70 	MOVL	perm+12(FP), DX
     71 	MOVL	$SYS_open, AX
     72 	SYSCALL
     73 	CMPQ	AX, $0xfffffffffffff001
     74 	JLS	2(PC)
     75 	MOVL	$-1, AX
     76 	MOVL	AX, ret+16(FP)
     77 	RET
     78 
     79 TEXT runtimeclosefd(SB),NOSPLIT,$0-12
     80 	MOVL	fd+0(FP), DI
     81 	MOVL	$SYS_close, AX
     82 	SYSCALL
     83 	CMPQ	AX, $0xfffffffffffff001
     84 	JLS	2(PC)
     85 	MOVL	$-1, AX
     86 	MOVL	AX, ret+8(FP)
     87 	RET
     88 
     89 TEXT runtimewrite(SB),NOSPLIT,$0-28
     90 	MOVQ	fd+0(FP), DI
     91 	MOVQ	p+8(FP), SI
     92 	MOVL	n+16(FP), DX
     93 	MOVL	$SYS_write, AX
     94 	SYSCALL
     95 	CMPQ	AX, $0xfffffffffffff001
     96 	JLS	2(PC)
     97 	MOVL	$-1, AX
     98 	MOVL	AX, ret+24(FP)
     99 	RET
    100 
    101 TEXT runtimeread(SB),NOSPLIT,$0-28
    102 	MOVL	fd+0(FP), DI
    103 	MOVQ	p+8(FP), SI
    104 	MOVL	n+16(FP), DX
    105 	MOVL	$SYS_read, AX
    106 	SYSCALL
    107 	CMPQ	AX, $0xfffffffffffff001
    108 	JLS	2(PC)
    109 	MOVL	$-1, AX
    110 	MOVL	AX, ret+24(FP)
    111 	RET
    112 
    113 TEXT runtimegetrlimit(SB),NOSPLIT,$0-20
    114 	MOVL	kind+0(FP), DI
    115 	MOVQ	limit+8(FP), SI
    116 	MOVL	$SYS_getrlimit, AX
    117 	SYSCALL
    118 	MOVL	AX, ret+16(FP)
    119 	RET
    120 
    121 TEXT runtimeusleep(SB),NOSPLIT,$16
    122 	MOVL	$0, DX
    123 	MOVL	usec+0(FP), AX
    124 	MOVL	$1000000, CX
    125 	DIVL	CX
    126 	MOVQ	AX, 0(SP)
    127 	MOVL	$1000, AX	// usec to nsec
    128 	MULL	DX
    129 	MOVQ	AX, 8(SP)
    130 
    131 	// pselect6(0, 0, 0, 0, &ts, 0)
    132 	MOVL	$0, DI
    133 	MOVL	$0, SI
    134 	MOVL	$0, DX
    135 	MOVL	$0, R10
    136 	MOVQ	SP, R8
    137 	MOVL	$0, R9
    138 	MOVL	$SYS_pselect6, AX
    139 	SYSCALL
    140 	RET
    141 
    142 TEXT runtimegettid(SB),NOSPLIT,$0-4
    143 	MOVL	$SYS_gettid, AX
    144 	SYSCALL
    145 	MOVL	AX, ret+0(FP)
    146 	RET
    147 
    148 TEXT runtimeraise(SB),NOSPLIT,$0
    149 	MOVL	$SYS_gettid, AX
    150 	SYSCALL
    151 	MOVL	AX, DI	// arg 1 tid
    152 	MOVL	sig+0(FP), SI	// arg 2
    153 	MOVL	$SYS_tkill, AX
    154 	SYSCALL
    155 	RET
    156 
    157 TEXT runtimeraiseproc(SB),NOSPLIT,$0
    158 	MOVL	$SYS_getpid, AX
    159 	SYSCALL
    160 	MOVL	AX, DI	// arg 1 pid
    161 	MOVL	sig+0(FP), SI	// arg 2
    162 	MOVL	$SYS_kill, AX
    163 	SYSCALL
    164 	RET
    165 
    166 TEXT runtimesetitimer(SB),NOSPLIT,$0-24
    167 	MOVL	mode+0(FP), DI
    168 	MOVQ	new+8(FP), SI
    169 	MOVQ	old+16(FP), DX
    170 	MOVL	$SYS_setittimer, AX
    171 	SYSCALL
    172 	RET
    173 
    174 TEXT runtimemincore(SB),NOSPLIT,$0-28
    175 	MOVQ	addr+0(FP), DI
    176 	MOVQ	n+8(FP), SI
    177 	MOVQ	dst+16(FP), DX
    178 	MOVL	$SYS_mincore, AX
    179 	SYSCALL
    180 	MOVL	AX, ret+24(FP)
    181 	RET
    182 
    183 // func walltime() (sec int64, nsec int32)
    184 TEXT runtimewalltime(SB),NOSPLIT,$0-12
    185 	// We don't know how much stack space the VDSO code will need,
    186 	// so switch to g0.
    187 	// In particular, a kernel configured with CONFIG_OPTIMIZE_INLINING=n
    188 	// and hardening can use a full page of stack space in gettime_sym
    189 	// due to stack probes inserted to avoid stack/heap collisions.
    190 	// See issue #20427.
    191 
    192 	MOVQ	SP, BP	// Save old SP; BP unchanged by C code.
    193 
    194 	get_tls(CX)
    195 	MOVQ	g(CX), AX
    196 	MOVQ	g_m(AX), CX
    197 	MOVQ	m_curg(CX), DX
    198 
    199 	CMPQ	AX, DX		// Only switch if on curg.
    200 	JNE	noswitch
    201 
    202 	MOVQ	m_g0(CX), DX
    203 	MOVQ	(g_sched+gobuf_sp)(DX), SP	// Set SP to g0 stack
    204 
    205 noswitch:
    206 	SUBQ	$16, SP		// Space for results
    207 	ANDQ	$~15, SP	// Align for C code
    208 
    209 	MOVQ	runtime__vdso_clock_gettime_sym(SB), AX
    210 	CMPQ	AX, $0
    211 	JEQ	fallback
    212 	MOVL	$0, DI // CLOCK_REALTIME
    213 	LEAQ	0(SP), SI
    214 	CALL	AX
    215 	MOVQ	0(SP), AX	// sec
    216 	MOVQ	8(SP), DX	// nsec
    217 	MOVQ	BP, SP		// Restore real SP
    218 	MOVQ	AX, sec+0(FP)
    219 	MOVL	DX, nsec+8(FP)
    220 	RET
    221 fallback:
    222 	LEAQ	0(SP), DI
    223 	MOVQ	$0, SI
    224 	MOVQ	runtime__vdso_gettimeofday_sym(SB), AX
    225 	CALL	AX
    226 	MOVQ	0(SP), AX	// sec
    227 	MOVL	8(SP), DX	// usec
    228 	IMULQ	$1000, DX
    229 	MOVQ	BP, SP		// Restore real SP
    230 	MOVQ	AX, sec+0(FP)
    231 	MOVL	DX, nsec+8(FP)
    232 	RET
    233 
    234 TEXT runtimenanotime(SB),NOSPLIT,$0-8
    235 	// Switch to g0 stack. See comment above in runtimewalltime.
    236 
    237 	MOVQ	SP, BP	// Save old SP; BX unchanged by C code.
    238 
    239 	get_tls(CX)
    240 	MOVQ	g(CX), AX
    241 	MOVQ	g_m(AX), CX
    242 	MOVQ	m_curg(CX), DX
    243 
    244 	CMPQ	AX, DX		// Only switch if on curg.
    245 	JNE	noswitch
    246 
    247 	MOVQ	m_g0(CX), DX
    248 	MOVQ	(g_sched+gobuf_sp)(DX), SP	// Set SP to g0 stack
    249 
    250 noswitch:
    251 	SUBQ	$16, SP		// Space for results
    252 	ANDQ	$~15, SP	// Align for C code
    253 
    254 	MOVQ	runtime__vdso_clock_gettime_sym(SB), AX
    255 	CMPQ	AX, $0
    256 	JEQ	fallback
    257 	MOVL	$1, DI // CLOCK_MONOTONIC
    258 	LEAQ	0(SP), SI
    259 	CALL	AX
    260 	MOVQ	0(SP), AX	// sec
    261 	MOVQ	8(SP), DX	// nsec
    262 	MOVQ	BP, SP		// Restore real SP
    263 	// sec is in AX, nsec in DX
    264 	// return nsec in AX
    265 	IMULQ	$1000000000, AX
    266 	ADDQ	DX, AX
    267 	MOVQ	AX, ret+0(FP)
    268 	RET
    269 fallback:
    270 	LEAQ	0(SP), DI
    271 	MOVQ	$0, SI
    272 	MOVQ	runtime__vdso_gettimeofday_sym(SB), AX
    273 	CALL	AX
    274 	MOVQ	0(SP), AX	// sec
    275 	MOVL	8(SP), DX	// usec
    276 	MOVQ	BP, SP		// Restore real SP
    277 	IMULQ	$1000, DX
    278 	// sec is in AX, nsec in DX
    279 	// return nsec in AX
    280 	IMULQ	$1000000000, AX
    281 	ADDQ	DX, AX
    282 	MOVQ	AX, ret+0(FP)
    283 	RET
    284 
    285 TEXT runtimertsigprocmask(SB),NOSPLIT,$0-28
    286 	MOVL	how+0(FP), DI
    287 	MOVQ	new+8(FP), SI
    288 	MOVQ	old+16(FP), DX
    289 	MOVL	size+24(FP), R10
    290 	MOVL	$SYS_rt_sigprocmask, AX
    291 	SYSCALL
    292 	CMPQ	AX, $0xfffffffffffff001
    293 	JLS	2(PC)
    294 	MOVL	$0xf1, 0xf1  // crash
    295 	RET
    296 
    297 TEXT runtimesysSigaction(SB),NOSPLIT,$0-36
    298 	MOVQ	sig+0(FP), DI
    299 	MOVQ	new+8(FP), SI
    300 	MOVQ	old+16(FP), DX
    301 	MOVQ	size+24(FP), R10
    302 	MOVL	$SYS_rt_sigaction, AX
    303 	SYSCALL
    304 	MOVL	AX, ret+32(FP)
    305 	RET
    306 
    307 // Call the function stored in _cgo_sigaction using the GCC calling convention.
    308 TEXT runtimecallCgoSigaction(SB),NOSPLIT,$16
    309 	MOVQ	sig+0(FP), DI
    310 	MOVQ	new+8(FP), SI
    311 	MOVQ	old+16(FP), DX
    312 	MOVQ	_cgo_sigaction(SB), AX
    313 	MOVQ	SP, BX	// callee-saved
    314 	ANDQ	$~15, SP	// alignment as per amd64 psABI
    315 	CALL	AX
    316 	MOVQ	BX, SP
    317 	MOVL	AX, ret+24(FP)
    318 	RET
    319 
    320 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    321 	MOVQ	fn+0(FP),    AX
    322 	MOVL	sig+8(FP),   DI
    323 	MOVQ	info+16(FP), SI
    324 	MOVQ	ctx+24(FP),  DX
    325 	PUSHQ	BP
    326 	MOVQ	SP, BP
    327 	ANDQ	$~15, SP     // alignment for x86_64 ABI
    328 	CALL	AX
    329 	MOVQ	BP, SP
    330 	POPQ	BP
    331 	RET
    332 
    333 TEXT runtimesigtramp(SB),NOSPLIT,$72
    334 	// Save callee-saved C registers, since the caller may be a C signal handler.
    335 	MOVQ	BX,  bx-8(SP)
    336 	MOVQ	BP,  bp-16(SP)  // save in case GOEXPERIMENT=noframepointer is set
    337 	MOVQ	R12, r12-24(SP)
    338 	MOVQ	R13, r13-32(SP)
    339 	MOVQ	R14, r14-40(SP)
    340 	MOVQ	R15, r15-48(SP)
    341 	// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
    342 	// modify them.
    343 
    344 	MOVQ	DX, ctx-56(SP)
    345 	MOVQ	SI, info-64(SP)
    346 	MOVQ	DI, signum-72(SP)
    347 	MOVQ	$runtimesigtrampgo(SB), AX
    348 	CALL AX
    349 
    350 	MOVQ	r15-48(SP), R15
    351 	MOVQ	r14-40(SP), R14
    352 	MOVQ	r13-32(SP), R13
    353 	MOVQ	r12-24(SP), R12
    354 	MOVQ	bp-16(SP),  BP
    355 	MOVQ	bx-8(SP),   BX
    356 	RET
    357 
    358 // Used instead of sigtramp in programs that use cgo.
    359 // Arguments from kernel are in DI, SI, DX.
    360 TEXT runtimecgoSigtramp(SB),NOSPLIT,$0
    361 	// If no traceback function, do usual sigtramp.
    362 	MOVQ	runtimecgoTraceback(SB), AX
    363 	TESTQ	AX, AX
    364 	JZ	sigtramp
    365 
    366 	// If no traceback support function, which means that
    367 	// runtime/cgo was not linked in, do usual sigtramp.
    368 	MOVQ	_cgo_callers(SB), AX
    369 	TESTQ	AX, AX
    370 	JZ	sigtramp
    371 
    372 	// Figure out if we are currently in a cgo call.
    373 	// If not, just do usual sigtramp.
    374 	get_tls(CX)
    375 	MOVQ	g(CX),AX
    376 	TESTQ	AX, AX
    377 	JZ	sigtrampnog     // g == nil
    378 	MOVQ	g_m(AX), AX
    379 	TESTQ	AX, AX
    380 	JZ	sigtramp        // g.m == nil
    381 	MOVL	m_ncgo(AX), CX
    382 	TESTL	CX, CX
    383 	JZ	sigtramp        // g.m.ncgo == 0
    384 	MOVQ	m_curg(AX), CX
    385 	TESTQ	CX, CX
    386 	JZ	sigtramp        // g.m.curg == nil
    387 	MOVQ	g_syscallsp(CX), CX
    388 	TESTQ	CX, CX
    389 	JZ	sigtramp        // g.m.curg.syscallsp == 0
    390 	MOVQ	m_cgoCallers(AX), R8
    391 	TESTQ	R8, R8
    392 	JZ	sigtramp        // g.m.cgoCallers == nil
    393 	MOVL	m_cgoCallersUse(AX), CX
    394 	TESTL	CX, CX
    395 	JNZ	sigtramp	// g.m.cgoCallersUse != 0
    396 
    397 	// Jump to a function in runtime/cgo.
    398 	// That function, written in C, will call the user's traceback
    399 	// function with proper unwind info, and will then call back here.
    400 	// The first three arguments, and the fifth, are already in registers.
    401 	// Set the two remaining arguments now.
    402 	MOVQ	runtimecgoTraceback(SB), CX
    403 	MOVQ	$runtimesigtramp(SB), R9
    404 	MOVQ	_cgo_callers(SB), AX
    405 	JMP	AX
    406 
    407 sigtramp:
    408 	JMP	runtimesigtramp(SB)
    409 
    410 sigtrampnog:
    411 	// Signal arrived on a non-Go thread. If this is SIGPROF, get a
    412 	// stack trace.
    413 	CMPL	DI, $27 // 27 == SIGPROF
    414 	JNZ	sigtramp
    415 
    416 	// Lock sigprofCallersUse.
    417 	MOVL	$0, AX
    418 	MOVL	$1, CX
    419 	MOVQ	$runtimesigprofCallersUse(SB), R11
    420 	LOCK
    421 	CMPXCHGL	CX, 0(R11)
    422 	JNZ	sigtramp  // Skip stack trace if already locked.
    423 
    424 	// Jump to the traceback function in runtime/cgo.
    425 	// It will call back to sigprofNonGo, which will ignore the
    426 	// arguments passed in registers.
    427 	// First three arguments to traceback function are in registers already.
    428 	MOVQ	runtimecgoTraceback(SB), CX
    429 	MOVQ	$runtimesigprofCallers(SB), R8
    430 	MOVQ	$runtimesigprofNonGo(SB), R9
    431 	MOVQ	_cgo_callers(SB), AX
    432 	JMP	AX
    433 
    434 // For cgo unwinding to work, this function must look precisely like
    435 // the one in glibc.  The glibc source code is:
    436 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c
    437 // The code that cares about the precise instructions used is:
    438 // https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup
    439 TEXT runtimesigreturn(SB),NOSPLIT,$0
    440 	MOVQ	$SYS_rt_sigreturn, AX
    441 	SYSCALL
    442 	INT $3	// not reached
    443 
    444 TEXT runtimesysMmap(SB),NOSPLIT,$0
    445 	MOVQ	addr+0(FP), DI
    446 	MOVQ	n+8(FP), SI
    447 	MOVL	prot+16(FP), DX
    448 	MOVL	flags+20(FP), R10
    449 	MOVL	fd+24(FP), R8
    450 	MOVL	off+28(FP), R9
    451 
    452 	MOVL	$SYS_mmap, AX
    453 	SYSCALL
    454 	CMPQ	AX, $0xfffffffffffff001
    455 	JLS	ok
    456 	NOTQ	AX
    457 	INCQ	AX
    458 	MOVQ	$0, p+32(FP)
    459 	MOVQ	AX, err+40(FP)
    460 	RET
    461 ok:
    462 	MOVQ	AX, p+32(FP)
    463 	MOVQ	$0, err+40(FP)
    464 	RET
    465 
    466 // Call the function stored in _cgo_mmap using the GCC calling convention.
    467 // This must be called on the system stack.
    468 TEXT runtimecallCgoMmap(SB),NOSPLIT,$16
    469 	MOVQ	addr+0(FP), DI
    470 	MOVQ	n+8(FP), SI
    471 	MOVL	prot+16(FP), DX
    472 	MOVL	flags+20(FP), CX
    473 	MOVL	fd+24(FP), R8
    474 	MOVL	off+28(FP), R9
    475 	MOVQ	_cgo_mmap(SB), AX
    476 	MOVQ	SP, BX
    477 	ANDQ	$~15, SP	// alignment as per amd64 psABI
    478 	MOVQ	BX, 0(SP)
    479 	CALL	AX
    480 	MOVQ	0(SP), SP
    481 	MOVQ	AX, ret+32(FP)
    482 	RET
    483 
    484 TEXT runtimesysMunmap(SB),NOSPLIT,$0
    485 	MOVQ	addr+0(FP), DI
    486 	MOVQ	n+8(FP), SI
    487 	MOVQ	$SYS_munmap, AX
    488 	SYSCALL
    489 	CMPQ	AX, $0xfffffffffffff001
    490 	JLS	2(PC)
    491 	MOVL	$0xf1, 0xf1  // crash
    492 	RET
    493 
    494 // Call the function stored in _cgo_munmap using the GCC calling convention.
    495 // This must be called on the system stack.
    496 TEXT runtimecallCgoMunmap(SB),NOSPLIT,$16-16
    497 	MOVQ	addr+0(FP), DI
    498 	MOVQ	n+8(FP), SI
    499 	MOVQ	_cgo_munmap(SB), AX
    500 	MOVQ	SP, BX
    501 	ANDQ	$~15, SP	// alignment as per amd64 psABI
    502 	MOVQ	BX, 0(SP)
    503 	CALL	AX
    504 	MOVQ	0(SP), SP
    505 	RET
    506 
    507 TEXT runtimemadvise(SB),NOSPLIT,$0
    508 	MOVQ	addr+0(FP), DI
    509 	MOVQ	n+8(FP), SI
    510 	MOVL	flags+16(FP), DX
    511 	MOVQ	$SYS_madvise, AX
    512 	SYSCALL
    513 	// ignore failure - maybe pages are locked
    514 	RET
    515 
    516 // int64 futex(int32 *uaddr, int32 op, int32 val,
    517 //	struct timespec *timeout, int32 *uaddr2, int32 val2);
    518 TEXT runtimefutex(SB),NOSPLIT,$0
    519 	MOVQ	addr+0(FP), DI
    520 	MOVL	op+8(FP), SI
    521 	MOVL	val+12(FP), DX
    522 	MOVQ	ts+16(FP), R10
    523 	MOVQ	addr2+24(FP), R8
    524 	MOVL	val3+32(FP), R9
    525 	MOVL	$SYS_futex, AX
    526 	SYSCALL
    527 	MOVL	AX, ret+40(FP)
    528 	RET
    529 
    530 // int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
    531 TEXT runtimeclone(SB),NOSPLIT,$0
    532 	MOVL	flags+0(FP), DI
    533 	MOVQ	stk+8(FP), SI
    534 	MOVQ	$0, DX
    535 	MOVQ	$0, R10
    536 
    537 	// Copy mp, gp, fn off parent stack for use by child.
    538 	// Careful: Linux system call clobbers CX and R11.
    539 	MOVQ	mp+16(FP), R8
    540 	MOVQ	gp+24(FP), R9
    541 	MOVQ	fn+32(FP), R12
    542 
    543 	MOVL	$SYS_clone, AX
    544 	SYSCALL
    545 
    546 	// In parent, return.
    547 	CMPQ	AX, $0
    548 	JEQ	3(PC)
    549 	MOVL	AX, ret+40(FP)
    550 	RET
    551 
    552 	// In child, on new stack.
    553 	MOVQ	SI, SP
    554 
    555 	// If g or m are nil, skip Go-related setup.
    556 	CMPQ	R8, $0    // m
    557 	JEQ	nog
    558 	CMPQ	R9, $0    // g
    559 	JEQ	nog
    560 
    561 	// Initialize m->procid to Linux tid
    562 	MOVL	$SYS_gettid, AX
    563 	SYSCALL
    564 	MOVQ	AX, m_procid(R8)
    565 
    566 	// Set FS to point at m->tls.
    567 	LEAQ	m_tls(R8), DI
    568 	CALL	runtimesettls(SB)
    569 
    570 	// In child, set up new stack
    571 	get_tls(CX)
    572 	MOVQ	R8, g_m(R9)
    573 	MOVQ	R9, g(CX)
    574 	CALL	runtimestackcheck(SB)
    575 
    576 nog:
    577 	// Call fn
    578 	CALL	R12
    579 
    580 	// It shouldn't return. If it does, exit that thread.
    581 	MOVL	$111, DI
    582 	MOVL	$SYS_exit, AX
    583 	SYSCALL
    584 	JMP	-3(PC)	// keep exiting
    585 
    586 TEXT runtimesigaltstack(SB),NOSPLIT,$-8
    587 	MOVQ	new+0(FP), DI
    588 	MOVQ	old+8(FP), SI
    589 	MOVQ	$SYS_sigaltstack, AX
    590 	SYSCALL
    591 	CMPQ	AX, $0xfffffffffffff001
    592 	JLS	2(PC)
    593 	MOVL	$0xf1, 0xf1  // crash
    594 	RET
    595 
    596 // set tls base to DI
    597 TEXT runtimesettls(SB),NOSPLIT,$32
    598 #ifdef GOOS_android
    599 	// Same as in sys_darwin_386.s:/ugliness, different constant.
    600 	// DI currently holds m->tls, which must be fs:0x1d0.
    601 	// See cgo/gcc_android_amd64.c for the derivation of the constant.
    602 	SUBQ	$0x1d0, DI  // In android, the tls base
    603 #else
    604 	ADDQ	$8, DI	// ELF wants to use -8(FS)
    605 #endif
    606 	MOVQ	DI, SI
    607 	MOVQ	$0x1002, DI	// ARCH_SET_FS
    608 	MOVQ	$SYS_arch_prctl, AX
    609 	SYSCALL
    610 	CMPQ	AX, $0xfffffffffffff001
    611 	JLS	2(PC)
    612 	MOVL	$0xf1, 0xf1  // crash
    613 	RET
    614 
    615 TEXT runtimeosyield(SB),NOSPLIT,$0
    616 	MOVL	$SYS_sched_yield, AX
    617 	SYSCALL
    618 	RET
    619 
    620 TEXT runtimesched_getaffinity(SB),NOSPLIT,$0
    621 	MOVQ	pid+0(FP), DI
    622 	MOVQ	len+8(FP), SI
    623 	MOVQ	buf+16(FP), DX
    624 	MOVL	$SYS_sched_getaffinity, AX
    625 	SYSCALL
    626 	MOVL	AX, ret+24(FP)
    627 	RET
    628 
    629 // int32 runtimeepollcreate(int32 size);
    630 TEXT runtimeepollcreate(SB),NOSPLIT,$0
    631 	MOVL    size+0(FP), DI
    632 	MOVL    $SYS_epoll_create, AX
    633 	SYSCALL
    634 	MOVL	AX, ret+8(FP)
    635 	RET
    636 
    637 // int32 runtimeepollcreate1(int32 flags);
    638 TEXT runtimeepollcreate1(SB),NOSPLIT,$0
    639 	MOVL	flags+0(FP), DI
    640 	MOVL	$SYS_epoll_create1, AX
    641 	SYSCALL
    642 	MOVL	AX, ret+8(FP)
    643 	RET
    644 
    645 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
    646 TEXT runtimeepollctl(SB),NOSPLIT,$0
    647 	MOVL	epfd+0(FP), DI
    648 	MOVL	op+4(FP), SI
    649 	MOVL	fd+8(FP), DX
    650 	MOVQ	ev+16(FP), R10
    651 	MOVL	$SYS_epoll_ctl, AX
    652 	SYSCALL
    653 	MOVL	AX, ret+24(FP)
    654 	RET
    655 
    656 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
    657 TEXT runtimeepollwait(SB),NOSPLIT,$0
    658 	MOVL	epfd+0(FP), DI
    659 	MOVQ	ev+8(FP), SI
    660 	MOVL	nev+16(FP), DX
    661 	MOVL	timeout+20(FP), R10
    662 	MOVL	$SYS_epoll_wait, AX
    663 	SYSCALL
    664 	MOVL	AX, ret+24(FP)
    665 	RET
    666 
    667 // void runtimecloseonexec(int32 fd);
    668 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    669 	MOVL    fd+0(FP), DI  // fd
    670 	MOVQ    $2, SI  // F_SETFD
    671 	MOVQ    $1, DX  // FD_CLOEXEC
    672 	MOVL	$SYS_fcntl, AX
    673 	SYSCALL
    674 	RET
    675 
    676 
    677 // int access(const char *name, int mode)
    678 TEXT runtimeaccess(SB),NOSPLIT,$0
    679 	MOVQ	name+0(FP), DI
    680 	MOVL	mode+8(FP), SI
    681 	MOVL	$SYS_access, AX
    682 	SYSCALL
    683 	MOVL	AX, ret+16(FP)
    684 	RET
    685 
    686 // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
    687 TEXT runtimeconnect(SB),NOSPLIT,$0-28
    688 	MOVL	fd+0(FP), DI
    689 	MOVQ	addr+8(FP), SI
    690 	MOVL	len+16(FP), DX
    691 	MOVL	$SYS_connect, AX
    692 	SYSCALL
    693 	MOVL	AX, ret+24(FP)
    694 	RET
    695 
    696 // int socket(int domain, int type, int protocol)
    697 TEXT runtimesocket(SB),NOSPLIT,$0-20
    698 	MOVL	domain+0(FP), DI
    699 	MOVL	typ+4(FP), SI
    700 	MOVL	prot+8(FP), DX
    701 	MOVL	$SYS_socket, AX
    702 	SYSCALL
    703 	MOVL	AX, ret+16(FP)
    704 	RET
    705 
    706 // func sbrk0() uintptr
    707 TEXT runtimesbrk0(SB),NOSPLIT,$0-8
    708 	// Implemented as brk(NULL).
    709 	MOVQ	$0, DI
    710 	MOVL	$SYS_brk, AX
    711 	SYSCALL
    712 	MOVQ	AX, ret+0(FP)
    713 	RET
    714