1// Copyright 2019 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 arm64, FreeBSD
7// /usr/src/sys/kern/syscalls.master for syscall numbers.
8//
9
10#include "go_asm.h"
11#include "go_tls.h"
12#include "textflag.h"
13#include "cgo/abi_arm64.h"
14
15#define CLOCK_REALTIME		0
16#define CLOCK_MONOTONIC		4
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___sysctl		202
31#define SYS_nanosleep		240
32#define SYS_issetugid		253
33#define SYS_clock_gettime	232
34#define SYS_sched_yield		331
35#define SYS_sigprocmask		340
36#define SYS_kqueue		362
37#define SYS_sigaction		416
38#define SYS_thr_exit		431
39#define SYS_thr_self		432
40#define SYS_thr_kill		433
41#define SYS__umtx_op		454
42#define SYS_thr_new		455
43#define SYS_mmap		477
44#define SYS_cpuset_getaffinity	487
45#define SYS_pipe2 		542
46#define SYS_kevent		560
47
48TEXT emptyfunc<>(SB),0,$0-0
49	RET
50
51// func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
52TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
53	MOVD	addr+0(FP), R0
54	MOVW	mode+8(FP), R1
55	MOVW	val+12(FP), R2
56	MOVD	uaddr1+16(FP), R3
57	MOVD	ut+24(FP), R4
58	MOVD	$SYS__umtx_op, R8
59	SVC
60	BCC	ok
61	NEG	R0, R0
62ok:
63	MOVW	R0, ret+32(FP)
64	RET
65
66// func thr_new(param *thrparam, size int32) int32
67TEXT runtime·thr_new(SB),NOSPLIT,$0
68	MOVD	param+0(FP), R0
69	MOVW	size+8(FP), R1
70	MOVD	$SYS_thr_new, R8
71	SVC
72	BCC	ok
73	NEG	R0, R0
74ok:
75	MOVW	R0, ret+16(FP)
76	RET
77
78// func thr_start()
79TEXT runtime·thr_start(SB),NOSPLIT,$0
80	// set up g
81	MOVD	m_g0(R0), g
82	MOVD	R0, g_m(g)
83	BL	emptyfunc<>(SB)	 // fault if stack check is wrong
84	BL	runtime·mstart(SB)
85
86	MOVD	$2, R8	// crash (not reached)
87	MOVD	R8, (R8)
88	RET
89
90// func exit(code int32)
91TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
92	MOVW	code+0(FP), R0
93	MOVD	$SYS_exit, R8
94	SVC
95	MOVD	$0, R0
96	MOVD	R0, (R0)
97
98// func exitThread(wait *atomic.Uint32)
99TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
100	MOVD	wait+0(FP), R0
101	// We're done using the stack.
102	MOVW	$0, R1
103	STLRW	R1, (R0)
104	MOVW	$0, R0
105	MOVD	$SYS_thr_exit, R8
106	SVC
107	JMP	0(PC)
108
109// func open(name *byte, mode, perm int32) int32
110TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
111	MOVD	name+0(FP), R0
112	MOVW	mode+8(FP), R1
113	MOVW	perm+12(FP), R2
114	MOVD	$SYS_open, R8
115	SVC
116	BCC	ok
117	MOVW	$-1, R0
118ok:
119	MOVW	R0, ret+16(FP)
120	RET
121
122// func closefd(fd int32) int32
123TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
124	MOVW	fd+0(FP), R0
125	MOVD	$SYS_close, R8
126	SVC
127	BCC	ok
128	MOVW	$-1, R0
129ok:
130	MOVW	R0, ret+8(FP)
131	RET
132
133// func pipe2(flags int32) (r, w int32, errno int32)
134TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
135	MOVD	$r+8(FP), R0
136	MOVW	flags+0(FP), R1
137	MOVD	$SYS_pipe2, R8
138	SVC
139	BCC	ok
140	NEG	R0, R0
141ok:
142	MOVW	R0, errno+16(FP)
143	RET
144
145// func write1(fd uintptr, p unsafe.Pointer, n int32) int32
146TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
147	MOVD	fd+0(FP), R0
148	MOVD	p+8(FP), R1
149	MOVW	n+16(FP), R2
150	MOVD	$SYS_write, R8
151	SVC
152	BCC	ok
153	NEG	R0, R0		// caller expects negative errno
154ok:
155	MOVW	R0, ret+24(FP)
156	RET
157
158// func read(fd int32, p unsafe.Pointer, n int32) int32
159TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
160	MOVW	fd+0(FP), R0
161	MOVD	p+8(FP), R1
162	MOVW	n+16(FP), R2
163	MOVD	$SYS_read, R8
164	SVC
165	BCC	ok
166	NEG	R0, R0		// caller expects negative errno
167ok:
168	MOVW	R0, ret+24(FP)
169	RET
170
171// func usleep(usec uint32)
172TEXT runtime·usleep(SB),NOSPLIT,$24-4
173	MOVWU	usec+0(FP), R3
174	MOVD	R3, R5
175	MOVW	$1000000, R4
176	UDIV	R4, R3
177	MOVD	R3, 8(RSP)
178	MUL	R3, R4
179	SUB	R4, R5
180	MOVW	$1000, R4
181	MUL	R4, R5
182	MOVD	R5, 16(RSP)
183
184	// nanosleep(&ts, 0)
185	ADD	$8, RSP, R0
186	MOVD	$0, R1
187	MOVD	$SYS_nanosleep, R8
188	SVC
189	RET
190
191// func thr_self() thread
192TEXT runtime·thr_self(SB),NOSPLIT,$8-8
193	MOVD	$ptr-8(SP), R0	// arg 1 &8(SP)
194	MOVD	$SYS_thr_self, R8
195	SVC
196	MOVD	ptr-8(SP), R0
197	MOVD	R0, ret+0(FP)
198	RET
199
200// func thr_kill(t thread, sig int)
201TEXT runtime·thr_kill(SB),NOSPLIT,$0-16
202	MOVD	tid+0(FP), R0	// arg 1 pid
203	MOVD	sig+8(FP), R1	// arg 2 sig
204	MOVD	$SYS_thr_kill, R8
205	SVC
206	RET
207
208// func raiseproc(sig uint32)
209TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
210	MOVD	$SYS_getpid, R8
211	SVC
212	MOVW	sig+0(FP), R1
213	MOVD	$SYS_kill, R8
214	SVC
215	RET
216
217// func setitimer(mode int32, new, old *itimerval)
218TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
219	MOVW	mode+0(FP), R0
220	MOVD	new+8(FP), R1
221	MOVD	old+16(FP), R2
222	MOVD	$SYS_setitimer, R8
223	SVC
224	RET
225
226// func fallback_walltime() (sec int64, nsec int32)
227TEXT runtime·fallback_walltime(SB),NOSPLIT,$24-12
228	MOVW	$CLOCK_REALTIME, R0
229	MOVD	$8(RSP), R1
230	MOVD	$SYS_clock_gettime, R8
231	SVC
232	MOVD	8(RSP), R0	// sec
233	MOVW	16(RSP), R1	// nsec
234	MOVD	R0, sec+0(FP)
235	MOVW	R1, nsec+8(FP)
236	RET
237
238// func fallback_nanotime() int64
239TEXT runtime·fallback_nanotime(SB),NOSPLIT,$24-8
240	MOVD	$CLOCK_MONOTONIC, R0
241	MOVD	$8(RSP), R1
242	MOVD	$SYS_clock_gettime, R8
243	SVC
244	MOVD	8(RSP), R0	// sec
245	MOVW	16(RSP), R2	// nsec
246
247	// sec is in R0, nsec in R2
248	// return nsec in R2
249	MOVD	$1000000000, R3
250	MUL	R3, R0
251	ADD	R2, R0
252
253	MOVD	R0, ret+0(FP)
254	RET
255
256// func asmSigaction(sig uintptr, new, old *sigactiont) int32
257TEXT runtime·asmSigaction(SB),NOSPLIT|NOFRAME,$0
258	MOVD	sig+0(FP), R0		// arg 1 sig
259	MOVD	new+8(FP), R1		// arg 2 act
260	MOVD	old+16(FP), R2		// arg 3 oact
261	MOVD	$SYS_sigaction, R8
262	SVC
263	BCC	ok
264	MOVW	$-1, R0
265ok:
266	MOVW	R0, ret+24(FP)
267	RET
268
269// func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
270TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
271	MOVW	sig+8(FP), R0
272	MOVD	info+16(FP), R1
273	MOVD	ctx+24(FP), R2
274	MOVD	fn+0(FP), R11
275	BL	(R11)
276	RET
277
278// func sigtramp()
279TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$176
280	// Save callee-save registers in the case of signal forwarding.
281	// Please refer to https://golang.org/issue/31827 .
282	SAVE_R19_TO_R28(8*4)
283	SAVE_F8_TO_F15(8*14)
284
285	// this might be called in external code context,
286	// where g is not set.
287	// first save R0, because runtime·load_g will clobber it
288	MOVW	R0, 8(RSP)
289	MOVBU	runtime·iscgo(SB), R0
290	CMP	$0, R0
291	BEQ	2(PC)
292	BL	runtime·load_g(SB)
293
294	// Restore signum to R0.
295	MOVW	8(RSP), R0
296	// R1 and R2 already contain info and ctx, respectively.
297	MOVD	$runtime·sigtrampgo<ABIInternal>(SB), R3
298	BL	(R3)
299
300	// Restore callee-save registers.
301	RESTORE_R19_TO_R28(8*4)
302	RESTORE_F8_TO_F15(8*14)
303
304	RET
305
306// func mmap(addr uintptr, n uintptr, prot int, flags int, fd int, off int64) (ret uintptr, err error)
307TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
308	MOVD	addr+0(FP), R0
309	MOVD	n+8(FP), R1
310	MOVW	prot+16(FP), R2
311	MOVW	flags+20(FP), R3
312	MOVW	fd+24(FP), R4
313	MOVW	off+28(FP), R5
314	MOVD	$SYS_mmap, R8
315	SVC
316	BCS	fail
317	MOVD	R0, p+32(FP)
318	MOVD	$0, err+40(FP)
319	RET
320fail:
321	MOVD	$0, p+32(FP)
322	MOVD	R0, err+40(FP)
323	RET
324
325// func munmap(addr uintptr, n uintptr) (err error)
326TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
327	MOVD	addr+0(FP), R0
328	MOVD	n+8(FP), R1
329	MOVD	$SYS_munmap, R8
330	SVC
331	BCS	fail
332	RET
333fail:
334	MOVD	$0, R0
335	MOVD	R0, (R0)	// crash
336
337// func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32
338TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
339	MOVD	addr+0(FP), R0
340	MOVD	n+8(FP), R1
341	MOVW	flags+16(FP), R2
342	MOVD	$SYS_madvise, R8
343	SVC
344	BCC	ok
345	MOVW	$-1, R0
346ok:
347	MOVW	R0, ret+24(FP)
348	RET
349
350// func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
351TEXT runtime·sysctl(SB),NOSPLIT,$0
352	MOVD	mib+0(FP), R0
353	MOVD	miblen+8(FP), R1
354	MOVD	out+16(FP), R2
355	MOVD	size+24(FP), R3
356	MOVD	dst+32(FP), R4
357	MOVD	ndst+40(FP), R5
358	MOVD	$SYS___sysctl, R8
359	SVC
360	BCC	ok
361	NEG	R0, R0
362ok:
363	MOVW	R0, ret+48(FP)
364	RET
365
366// func sigaltstack(new, old *stackt)
367TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
368	MOVD	new+0(FP), R0
369	MOVD	old+8(FP), R1
370	MOVD	$SYS_sigaltstack, R8
371	SVC
372	BCS	fail
373	RET
374fail:
375	MOVD	$0, R0
376	MOVD	R0, (R0)	// crash
377
378// func osyield()
379TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
380	MOVD	$SYS_sched_yield, R8
381	SVC
382	RET
383
384// func sigprocmask(how int32, new, old *sigset)
385TEXT runtime·sigprocmask(SB),NOSPLIT|NOFRAME,$0-24
386	MOVW	how+0(FP), R0
387	MOVD	new+8(FP), R1
388	MOVD	old+16(FP), R2
389	MOVD	$SYS_sigprocmask, R8
390	SVC
391	BCS	fail
392	RET
393fail:
394	MOVD	$0, R0
395	MOVD	R0, (R0)	// crash
396
397// func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
398TEXT runtime·cpuset_getaffinity(SB),NOSPLIT|NOFRAME,$0-44
399	MOVD	level+0(FP), R0
400	MOVD	which+8(FP), R1
401	MOVD	id+16(FP), R2
402	MOVD	size+24(FP), R3
403	MOVD	mask+32(FP), R4
404	MOVD	$SYS_cpuset_getaffinity, R8
405	SVC
406	BCC	ok
407	MOVW	$-1, R0
408ok:
409	MOVW	R0, ret+40(FP)
410	RET
411
412// func kqueue() int32
413TEXT runtime·kqueue(SB),NOSPLIT|NOFRAME,$0
414	MOVD $SYS_kqueue, R8
415	SVC
416	BCC	ok
417	MOVW	$-1, R0
418ok:
419	MOVW	R0, ret+0(FP)
420	RET
421
422// func kevent(kq int, ch unsafe.Pointer, nch int, ev unsafe.Pointer, nev int, ts *Timespec) (n int, err error)
423TEXT runtime·kevent(SB),NOSPLIT,$0
424	MOVW	kq+0(FP), R0
425	MOVD	ch+8(FP), R1
426	MOVW	nch+16(FP), R2
427	MOVD	ev+24(FP), R3
428	MOVW	nev+32(FP), R4
429	MOVD	ts+40(FP), R5
430	MOVD	$SYS_kevent, R8
431	SVC
432	BCC	ok
433	NEG	R0, R0
434ok:
435	MOVW	R0, ret+48(FP)
436	RET
437
438// func fcntl(fd, cmd, arg int32) (int32, int32)
439TEXT runtime·fcntl(SB),NOSPLIT,$0
440	MOVW	fd+0(FP), R0
441	MOVW	cmd+4(FP), R1
442	MOVW	arg+8(FP), R2
443	MOVD	$SYS_fcntl, R8
444	SVC
445	BCC	noerr
446	MOVW	$-1, R1
447	MOVW	R1, ret+16(FP)
448	MOVW	R0, errno+20(FP)
449	RET
450noerr:
451	MOVW	R0, ret+16(FP)
452	MOVW	$0, errno+20(FP)
453	RET
454
455// func getCntxct(physical bool) uint32
456TEXT runtime·getCntxct(SB),NOSPLIT,$0
457	MOVB	physical+0(FP), R0
458	CMP	$0, R0
459	BEQ	3(PC)
460
461	// get CNTPCT (Physical Count Register) into R0
462	MRS	CNTPCT_EL0, R0
463	B	2(PC)
464
465	// get CNTVCT (Virtual Count Register) into R0
466	MRS	CNTVCT_EL0, R0
467
468	MOVW	R0, ret+8(FP)
469	RET
470
471// func issetugid() int32
472TEXT runtime·issetugid(SB),NOSPLIT|NOFRAME,$0
473	MOVD $SYS_issetugid, R8
474	SVC
475	MOVW	R0, ret+0(FP)
476	RET
477