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