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// System calls and other sys.stuff for AMD64, FreeBSD
6// /usr/src/sys/kern/syscalls.master for syscall numbers.
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 CLOCK_REALTIME		0
15#define CLOCK_MONOTONIC		4
16#define AMD64_SET_FSBASE	129
17
18#define SYS_exit		1
19#define SYS_read		3
20#define SYS_write		4
21#define SYS_open		5
22#define SYS_close		6
23#define SYS_getpid		20
24#define SYS_kill		37
25#define SYS_sigaltstack		53
26#define SYS_munmap		73
27#define SYS_madvise		75
28#define SYS_setitimer		83
29#define SYS_fcntl		92
30#define SYS_sysarch		165
31#define SYS___sysctl		202
32#define SYS_clock_gettime	232
33#define SYS_nanosleep		240
34#define SYS_issetugid		253
35#define SYS_sched_yield		331
36#define SYS_sigprocmask		340
37#define SYS_kqueue		362
38#define SYS_sigaction		416
39#define SYS_thr_exit		431
40#define SYS_thr_self		432
41#define SYS_thr_kill		433
42#define SYS__umtx_op		454
43#define SYS_thr_new		455
44#define SYS_mmap		477
45#define SYS_cpuset_getaffinity	487
46#define SYS_pipe2 		542
47#define SYS_kevent		560
48
49TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
50	MOVQ addr+0(FP), DI
51	MOVL mode+8(FP), SI
52	MOVL val+12(FP), DX
53	MOVQ uaddr1+16(FP), R10
54	MOVQ ut+24(FP), R8
55	MOVL $SYS__umtx_op, AX
56	SYSCALL
57	JCC	2(PC)
58	NEGQ	AX
59	MOVL	AX, ret+32(FP)
60	RET
61
62TEXT runtime·thr_new(SB),NOSPLIT,$0
63	MOVQ param+0(FP), DI
64	MOVL size+8(FP), SI
65	MOVL $SYS_thr_new, AX
66	SYSCALL
67	JCC	2(PC)
68	NEGQ	AX
69	MOVL	AX, ret+16(FP)
70	RET
71
72TEXT runtime·thr_start(SB),NOSPLIT,$0
73	MOVQ	DI, R13 // m
74
75	// set up FS to point at m->tls
76	LEAQ	m_tls(R13), DI
77	CALL	runtime·settls(SB)	// smashes DI
78
79	// set up m, g
80	get_tls(CX)
81	MOVQ	m_g0(R13), DI
82	MOVQ	R13, g_m(DI)
83	MOVQ	DI, g(CX)
84
85	CALL	runtime·stackcheck(SB)
86	CALL	runtime·mstart(SB)
87
88	MOVQ 0, AX			// crash (not reached)
89
90// Exit the entire program (like C exit)
91TEXT runtime·exit(SB),NOSPLIT,$-8
92	MOVL	code+0(FP), DI		// arg 1 exit status
93	MOVL	$SYS_exit, AX
94	SYSCALL
95	MOVL	$0xf1, 0xf1  // crash
96	RET
97
98// func exitThread(wait *atomic.uint32)
99TEXT runtime·exitThread(SB),NOSPLIT,$0-8
100	MOVQ	wait+0(FP), AX
101	// We're done using the stack.
102	MOVL	$0, (AX)
103	MOVL	$0, DI		// arg 1 long *state
104	MOVL	$SYS_thr_exit, AX
105	SYSCALL
106	MOVL	$0xf1, 0xf1  // crash
107	JMP	0(PC)
108
109TEXT runtime·open(SB),NOSPLIT,$-8
110	MOVQ	name+0(FP), DI		// arg 1 pathname
111	MOVL	mode+8(FP), SI		// arg 2 flags
112	MOVL	perm+12(FP), DX		// arg 3 mode
113	MOVL	$SYS_open, AX
114	SYSCALL
115	JCC	2(PC)
116	MOVL	$-1, AX
117	MOVL	AX, ret+16(FP)
118	RET
119
120TEXT runtime·closefd(SB),NOSPLIT,$-8
121	MOVL	fd+0(FP), DI		// arg 1 fd
122	MOVL	$SYS_close, AX
123	SYSCALL
124	JCC	2(PC)
125	MOVL	$-1, AX
126	MOVL	AX, ret+8(FP)
127	RET
128
129TEXT runtime·read(SB),NOSPLIT,$-8
130	MOVL	fd+0(FP), DI		// arg 1 fd
131	MOVQ	p+8(FP), SI		// arg 2 buf
132	MOVL	n+16(FP), DX		// arg 3 count
133	MOVL	$SYS_read, AX
134	SYSCALL
135	JCC	2(PC)
136	NEGQ	AX			// caller expects negative errno
137	MOVL	AX, ret+24(FP)
138	RET
139
140// func pipe2(flags int32) (r, w int32, errno int32)
141TEXT runtime·pipe2(SB),NOSPLIT,$0-20
142	LEAQ	r+8(FP), DI
143	MOVL	flags+0(FP), SI
144	MOVL	$SYS_pipe2, AX
145	SYSCALL
146	JCC	2(PC)
147	NEGQ	AX
148	MOVL	AX, errno+16(FP)
149	RET
150
151TEXT runtime·write1(SB),NOSPLIT,$-8
152	MOVQ	fd+0(FP), DI		// arg 1 fd
153	MOVQ	p+8(FP), SI		// arg 2 buf
154	MOVL	n+16(FP), DX		// arg 3 count
155	MOVL	$SYS_write, AX
156	SYSCALL
157	JCC	2(PC)
158	NEGQ	AX			// caller expects negative errno
159	MOVL	AX, ret+24(FP)
160	RET
161
162TEXT runtime·thr_self(SB),NOSPLIT,$0-8
163	// thr_self(&0(FP))
164	LEAQ	ret+0(FP), DI	// arg 1
165	MOVL	$SYS_thr_self, AX
166	SYSCALL
167	RET
168
169TEXT runtime·thr_kill(SB),NOSPLIT,$0-16
170	// thr_kill(tid, sig)
171	MOVQ	tid+0(FP), DI	// arg 1 id
172	MOVQ	sig+8(FP), SI	// arg 2 sig
173	MOVL	$SYS_thr_kill, AX
174	SYSCALL
175	RET
176
177TEXT runtime·raiseproc(SB),NOSPLIT,$0
178	// getpid
179	MOVL	$SYS_getpid, AX
180	SYSCALL
181	// kill(self, sig)
182	MOVQ	AX, DI		// arg 1 pid
183	MOVL	sig+0(FP), SI	// arg 2 sig
184	MOVL	$SYS_kill, AX
185	SYSCALL
186	RET
187
188TEXT runtime·setitimer(SB), NOSPLIT, $-8
189	MOVL	mode+0(FP), DI
190	MOVQ	new+8(FP), SI
191	MOVQ	old+16(FP), DX
192	MOVL	$SYS_setitimer, AX
193	SYSCALL
194	RET
195
196// func fallback_walltime() (sec int64, nsec int32)
197TEXT runtime·fallback_walltime(SB), NOSPLIT, $32-12
198	MOVL	$SYS_clock_gettime, AX
199	MOVQ	$CLOCK_REALTIME, DI
200	LEAQ	8(SP), SI
201	SYSCALL
202	MOVQ	8(SP), AX	// sec
203	MOVQ	16(SP), DX	// nsec
204
205	// sec is in AX, nsec in DX
206	MOVQ	AX, sec+0(FP)
207	MOVL	DX, nsec+8(FP)
208	RET
209
210TEXT runtime·fallback_nanotime(SB), NOSPLIT, $32-8
211	MOVL	$SYS_clock_gettime, AX
212	MOVQ	$CLOCK_MONOTONIC, DI
213	LEAQ	8(SP), SI
214	SYSCALL
215	MOVQ	8(SP), AX	// sec
216	MOVQ	16(SP), DX	// nsec
217
218	// sec is in AX, nsec in DX
219	// return nsec in AX
220	IMULQ	$1000000000, AX
221	ADDQ	DX, AX
222	MOVQ	AX, ret+0(FP)
223	RET
224
225TEXT runtime·asmSigaction(SB),NOSPLIT,$0
226	MOVQ	sig+0(FP), DI		// arg 1 sig
227	MOVQ	new+8(FP), SI		// arg 2 act
228	MOVQ	old+16(FP), DX		// arg 3 oact
229	MOVL	$SYS_sigaction, AX
230	SYSCALL
231	JCC	2(PC)
232	MOVL	$-1, AX
233	MOVL	AX, ret+24(FP)
234	RET
235
236TEXT runtime·callCgoSigaction(SB),NOSPLIT,$16
237	MOVQ	sig+0(FP), DI		// arg 1 sig
238	MOVQ	new+8(FP), SI		// arg 2 act
239	MOVQ	old+16(FP), DX		// arg 3 oact
240	MOVQ	_cgo_sigaction(SB), AX
241	MOVQ	SP, BX			// callee-saved
242	ANDQ	$~15, SP		// alignment as per amd64 psABI
243	CALL	AX
244	MOVQ	BX, SP
245	MOVL	AX, ret+24(FP)
246	RET
247
248TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
249	MOVQ	fn+0(FP),    AX
250	MOVL	sig+8(FP),   DI
251	MOVQ	info+16(FP), SI
252	MOVQ	ctx+24(FP),  DX
253	MOVQ	SP, BX		// callee-saved
254	ANDQ	$~15, SP	// alignment for x86_64 ABI
255	CALL	AX
256	MOVQ	BX, SP
257	RET
258
259// Called using C ABI.
260TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME|NOFRAME,$0
261	// Transition from C ABI to Go ABI.
262	PUSH_REGS_HOST_TO_ABI0()
263
264	// Set up ABIInternal environment: g in R14, cleared X15.
265	get_tls(R12)
266	MOVQ	g(R12), R14
267	PXOR	X15, X15
268
269	// Reserve space for spill slots.
270	NOP	SP		// disable vet stack checking
271	ADJSP   $24
272
273	// Call into the Go signal handler
274	MOVQ	DI, AX	// sig
275	MOVQ	SI, BX	// info
276	MOVQ	DX, CX	// ctx
277	CALL	·sigtrampgo<ABIInternal>(SB)
278
279	ADJSP	$-24
280
281	POP_REGS_HOST_TO_ABI0()
282	RET
283
284// Called using C ABI.
285TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT|NOFRAME,$0
286	// Transition from C ABI to Go ABI.
287	PUSH_REGS_HOST_TO_ABI0()
288
289	// Set up ABIInternal environment: g in R14, cleared X15.
290	get_tls(R12)
291	MOVQ	g(R12), R14
292	PXOR	X15, X15
293
294	// Reserve space for spill slots.
295	NOP	SP		// disable vet stack checking
296	ADJSP   $24
297
298	// Call into the Go signal handler
299	MOVQ	DI, AX	// sig
300	MOVQ	SI, BX	// info
301	MOVQ	DX, CX	// ctx
302	CALL	·sigprofNonGo<ABIInternal>(SB)
303
304	ADJSP	$-24
305
306	POP_REGS_HOST_TO_ABI0()
307	RET
308
309// Used instead of sigtramp in programs that use cgo.
310// Arguments from kernel are in DI, SI, DX.
311TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
312	// If no traceback function, do usual sigtramp.
313	MOVQ	runtime·cgoTraceback(SB), AX
314	TESTQ	AX, AX
315	JZ	sigtramp
316
317	// If no traceback support function, which means that
318	// runtime/cgo was not linked in, do usual sigtramp.
319	MOVQ	_cgo_callers(SB), AX
320	TESTQ	AX, AX
321	JZ	sigtramp
322
323	// Figure out if we are currently in a cgo call.
324	// If not, just do usual sigtramp.
325	get_tls(CX)
326	MOVQ	g(CX),AX
327	TESTQ	AX, AX
328	JZ	sigtrampnog     // g == nil
329	MOVQ	g_m(AX), AX
330	TESTQ	AX, AX
331	JZ	sigtramp        // g.m == nil
332	MOVL	m_ncgo(AX), CX
333	TESTL	CX, CX
334	JZ	sigtramp        // g.m.ncgo == 0
335	MOVQ	m_curg(AX), CX
336	TESTQ	CX, CX
337	JZ	sigtramp        // g.m.curg == nil
338	MOVQ	g_syscallsp(CX), CX
339	TESTQ	CX, CX
340	JZ	sigtramp        // g.m.curg.syscallsp == 0
341	MOVQ	m_cgoCallers(AX), R8
342	TESTQ	R8, R8
343	JZ	sigtramp        // g.m.cgoCallers == nil
344	MOVL	m_cgoCallersUse(AX), CX
345	TESTL	CX, CX
346	JNZ	sigtramp	// g.m.cgoCallersUse != 0
347
348	// Jump to a function in runtime/cgo.
349	// That function, written in C, will call the user's traceback
350	// function with proper unwind info, and will then call back here.
351	// The first three arguments, and the fifth, are already in registers.
352	// Set the two remaining arguments now.
353	MOVQ	runtime·cgoTraceback(SB), CX
354	MOVQ	$runtime·sigtramp(SB), R9
355	MOVQ	_cgo_callers(SB), AX
356	JMP	AX
357
358sigtramp:
359	JMP	runtime·sigtramp(SB)
360
361sigtrampnog:
362	// Signal arrived on a non-Go thread. If this is SIGPROF, get a
363	// stack trace.
364	CMPL	DI, $27 // 27 == SIGPROF
365	JNZ	sigtramp
366
367	// Lock sigprofCallersUse.
368	MOVL	$0, AX
369	MOVL	$1, CX
370	MOVQ	$runtime·sigprofCallersUse(SB), R11
371	LOCK
372	CMPXCHGL	CX, 0(R11)
373	JNZ	sigtramp  // Skip stack trace if already locked.
374
375	// Jump to the traceback function in runtime/cgo.
376	// It will call back to sigprofNonGo, via sigprofNonGoWrapper, to convert
377	// the arguments to the Go calling convention.
378	// First three arguments to traceback function are in registers already.
379	MOVQ	runtime·cgoTraceback(SB), CX
380	MOVQ	$runtime·sigprofCallers(SB), R8
381	MOVQ	$runtime·sigprofNonGoWrapper<>(SB), R9
382	MOVQ	_cgo_callers(SB), AX
383	JMP	AX
384
385TEXT runtime·sysMmap(SB),NOSPLIT,$0
386	MOVQ	addr+0(FP), DI		// arg 1 addr
387	MOVQ	n+8(FP), SI		// arg 2 len
388	MOVL	prot+16(FP), DX		// arg 3 prot
389	MOVL	flags+20(FP), R10		// arg 4 flags
390	MOVL	fd+24(FP), R8		// arg 5 fid
391	MOVL	off+28(FP), R9		// arg 6 offset
392	MOVL	$SYS_mmap, AX
393	SYSCALL
394	JCC	ok
395	MOVQ	$0, p+32(FP)
396	MOVQ	AX, err+40(FP)
397	RET
398ok:
399	MOVQ	AX, p+32(FP)
400	MOVQ	$0, err+40(FP)
401	RET
402
403// Call the function stored in _cgo_mmap using the GCC calling convention.
404// This must be called on the system stack.
405TEXT runtime·callCgoMmap(SB),NOSPLIT,$16
406	MOVQ	addr+0(FP), DI
407	MOVQ	n+8(FP), SI
408	MOVL	prot+16(FP), DX
409	MOVL	flags+20(FP), CX
410	MOVL	fd+24(FP), R8
411	MOVL	off+28(FP), R9
412	MOVQ	_cgo_mmap(SB), AX
413	MOVQ	SP, BX
414	ANDQ	$~15, SP	// alignment as per amd64 psABI
415	MOVQ	BX, 0(SP)
416	CALL	AX
417	MOVQ	0(SP), SP
418	MOVQ	AX, ret+32(FP)
419	RET
420
421TEXT runtime·sysMunmap(SB),NOSPLIT,$0
422	MOVQ	addr+0(FP), DI		// arg 1 addr
423	MOVQ	n+8(FP), SI		// arg 2 len
424	MOVL	$SYS_munmap, AX
425	SYSCALL
426	JCC	2(PC)
427	MOVL	$0xf1, 0xf1  // crash
428	RET
429
430// Call the function stored in _cgo_munmap using the GCC calling convention.
431// This must be called on the system stack.
432TEXT runtime·callCgoMunmap(SB),NOSPLIT,$16-16
433	MOVQ	addr+0(FP), DI
434	MOVQ	n+8(FP), SI
435	MOVQ	_cgo_munmap(SB), AX
436	MOVQ	SP, BX
437	ANDQ	$~15, SP	// alignment as per amd64 psABI
438	MOVQ	BX, 0(SP)
439	CALL	AX
440	MOVQ	0(SP), SP
441	RET
442
443TEXT runtime·madvise(SB),NOSPLIT,$0
444	MOVQ	addr+0(FP), DI
445	MOVQ	n+8(FP), SI
446	MOVL	flags+16(FP), DX
447	MOVQ	$SYS_madvise, AX
448	SYSCALL
449	JCC	2(PC)
450	MOVL	$-1, AX
451	MOVL	AX, ret+24(FP)
452	RET
453
454TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
455	MOVQ	new+0(FP), DI
456	MOVQ	old+8(FP), SI
457	MOVQ	$SYS_sigaltstack, AX
458	SYSCALL
459	JCC	2(PC)
460	MOVL	$0xf1, 0xf1  // crash
461	RET
462
463TEXT runtime·usleep(SB),NOSPLIT,$16
464	MOVL	$0, DX
465	MOVL	usec+0(FP), AX
466	MOVL	$1000000, CX
467	DIVL	CX
468	MOVQ	AX, 0(SP)		// tv_sec
469	MOVL	$1000, AX
470	MULL	DX
471	MOVQ	AX, 8(SP)		// tv_nsec
472
473	MOVQ	SP, DI			// arg 1 - rqtp
474	MOVQ	$0, SI			// arg 2 - rmtp
475	MOVL	$SYS_nanosleep, AX
476	SYSCALL
477	RET
478
479// set tls base to DI
480TEXT runtime·settls(SB),NOSPLIT,$8
481	ADDQ	$8, DI	// adjust for ELF: wants to use -8(FS) for g and m
482	MOVQ	DI, 0(SP)
483	MOVQ	SP, SI
484	MOVQ	$AMD64_SET_FSBASE, DI
485	MOVQ	$SYS_sysarch, AX
486	SYSCALL
487	JCC	2(PC)
488	MOVL	$0xf1, 0xf1  // crash
489	RET
490
491TEXT runtime·sysctl(SB),NOSPLIT,$0
492	MOVQ	mib+0(FP), DI		// arg 1 - name
493	MOVL	miblen+8(FP), SI		// arg 2 - namelen
494	MOVQ	out+16(FP), DX		// arg 3 - oldp
495	MOVQ	size+24(FP), R10		// arg 4 - oldlenp
496	MOVQ	dst+32(FP), R8		// arg 5 - newp
497	MOVQ	ndst+40(FP), R9		// arg 6 - newlen
498	MOVQ	$SYS___sysctl, AX
499	SYSCALL
500	JCC 4(PC)
501	NEGQ	AX
502	MOVL	AX, ret+48(FP)
503	RET
504	MOVL	$0, AX
505	MOVL	AX, ret+48(FP)
506	RET
507
508TEXT runtime·osyield(SB),NOSPLIT,$-4
509	MOVL	$SYS_sched_yield, AX
510	SYSCALL
511	RET
512
513TEXT runtime·sigprocmask(SB),NOSPLIT,$0
514	MOVL	how+0(FP), DI		// arg 1 - how
515	MOVQ	new+8(FP), SI		// arg 2 - set
516	MOVQ	old+16(FP), DX		// arg 3 - oset
517	MOVL	$SYS_sigprocmask, AX
518	SYSCALL
519	JAE	2(PC)
520	MOVL	$0xf1, 0xf1  // crash
521	RET
522
523// int32 runtime·kqueue(void);
524TEXT runtime·kqueue(SB),NOSPLIT,$0
525	MOVQ	$0, DI
526	MOVQ	$0, SI
527	MOVQ	$0, DX
528	MOVL	$SYS_kqueue, AX
529	SYSCALL
530	JCC	2(PC)
531	NEGQ	AX
532	MOVL	AX, ret+0(FP)
533	RET
534
535// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
536TEXT runtime·kevent(SB),NOSPLIT,$0
537	MOVL	kq+0(FP), DI
538	MOVQ	ch+8(FP), SI
539	MOVL	nch+16(FP), DX
540	MOVQ	ev+24(FP), R10
541	MOVL	nev+32(FP), R8
542	MOVQ	ts+40(FP), R9
543	MOVL	$SYS_kevent, AX
544	SYSCALL
545	JCC	2(PC)
546	NEGQ	AX
547	MOVL	AX, ret+48(FP)
548	RET
549
550// func fcntl(fd, cmd, arg int32) (int32, int32)
551TEXT runtime·fcntl(SB),NOSPLIT,$0
552	MOVL	fd+0(FP), DI	// fd
553	MOVL	cmd+4(FP), SI	// cmd
554	MOVL	arg+8(FP), DX	// arg
555	MOVL	$SYS_fcntl, AX
556	SYSCALL
557	JCC	noerr
558	MOVL	$-1, ret+16(FP)
559	MOVL	AX, errno+20(FP)
560	RET
561noerr:
562	MOVL	AX, ret+16(FP)
563	MOVL	$0, errno+20(FP)
564	RET
565
566// func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
567TEXT runtime·cpuset_getaffinity(SB), NOSPLIT, $0-44
568	MOVQ	level+0(FP), DI
569	MOVQ	which+8(FP), SI
570	MOVQ	id+16(FP), DX
571	MOVQ	size+24(FP), R10
572	MOVQ	mask+32(FP), R8
573	MOVL	$SYS_cpuset_getaffinity, AX
574	SYSCALL
575	JCC	2(PC)
576	NEGQ	AX
577	MOVL	AX, ret+40(FP)
578	RET
579
580// func issetugid() int32
581TEXT runtime·issetugid(SB),NOSPLIT,$0
582	MOVQ	$0, DI
583	MOVQ	$0, SI
584	MOVQ	$0, DX
585	MOVL	$SYS_issetugid, AX
586	SYSCALL
587	MOVL	AX, ret+0(FP)
588	RET
589