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, NetBSD
7//
8
9#include "go_asm.h"
10#include "go_tls.h"
11#include "textflag.h"
12#include "cgo/abi_arm64.h"
13
14#define CLOCK_REALTIME		0
15#define CLOCK_MONOTONIC		3
16
17#define SYS_exit			1
18#define SYS_read			3
19#define SYS_write			4
20#define SYS_open			5
21#define SYS_close			6
22#define SYS_getpid			20
23#define SYS_kill			37
24#define SYS_munmap			73
25#define SYS_madvise			75
26#define SYS_fcntl			92
27#define SYS_mmap			197
28#define SYS___sysctl			202
29#define SYS___sigaltstack14		281
30#define SYS___sigprocmask14		293
31#define SYS_issetugid			305
32#define SYS_getcontext			307
33#define SYS_setcontext			308
34#define SYS__lwp_create			309
35#define SYS__lwp_exit			310
36#define SYS__lwp_self			311
37#define SYS__lwp_kill			318
38#define SYS__lwp_unpark			321
39#define SYS___sigaction_sigtramp	340
40#define SYS_kqueue			344
41#define SYS_sched_yield			350
42#define SYS___setitimer50		425
43#define SYS___clock_gettime50		427
44#define SYS___nanosleep50		430
45#define SYS___kevent50			435
46#define SYS_pipe2			453
47#define SYS_openat			468
48#define SYS____lwp_park60		478
49
50// int32 lwp_create(void *context, uintptr flags, void *lwpid)
51TEXT runtime·lwp_create(SB),NOSPLIT,$0
52	MOVD	ctxt+0(FP), R0
53	MOVD	flags+8(FP), R1
54	MOVD	lwpid+16(FP), R2
55	SVC	$SYS__lwp_create
56	BCC	ok
57	NEG	R0, R0
58ok:
59	MOVW	R0, ret+24(FP)
60	RET
61
62TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
63	CMP	$0, R1
64	BEQ	nog
65	CMP	$0, R2
66	BEQ	nog
67
68	MOVD	R0, g_m(R1)
69	MOVD	R1, g
70nog:
71	CALL	(R2)
72
73	MOVD	$0, R0  // crash (not reached)
74	MOVD	R0, (R8)
75
76TEXT ·netbsdMstart(SB),NOSPLIT|TOPFRAME,$0
77	CALL	·netbsdMstart0(SB)
78	RET // not reached
79
80TEXT runtime·osyield(SB),NOSPLIT,$0
81	SVC	$SYS_sched_yield
82	RET
83
84TEXT runtime·lwp_park(SB),NOSPLIT,$0
85	MOVW	clockid+0(FP), R0	// arg 1 - clockid
86	MOVW	flags+4(FP), R1		// arg 2 - flags
87	MOVD	ts+8(FP), R2		// arg 3 - ts
88	MOVW	unpark+16(FP), R3	// arg 4 - unpark
89	MOVD	hint+24(FP), R4		// arg 5 - hint
90	MOVD	unparkhint+32(FP), R5	// arg 6 - unparkhint
91	SVC	$SYS____lwp_park60
92	MOVW	R0, ret+40(FP)
93	RET
94
95TEXT runtime·lwp_unpark(SB),NOSPLIT,$0
96	MOVW	lwp+0(FP), R0		// arg 1 - lwp
97	MOVD	hint+8(FP), R1		// arg 2 - hint
98	SVC	$SYS__lwp_unpark
99	MOVW	R0, ret+16(FP)
100	RET
101
102TEXT runtime·lwp_self(SB),NOSPLIT,$0
103	SVC	$SYS__lwp_self
104	MOVW	R0, ret+0(FP)
105	RET
106
107// Exit the entire program (like C exit)
108TEXT runtime·exit(SB),NOSPLIT,$-8
109	MOVW	code+0(FP), R0		// arg 1 - exit status
110	SVC	$SYS_exit
111	MOVD	$0, R0			// If we're still running,
112	MOVD	R0, (R0)		// crash
113
114// func exitThread(wait *atomic.Uint32)
115TEXT runtime·exitThread(SB),NOSPLIT,$0-8
116	MOVD	wait+0(FP), R0
117	// We're done using the stack.
118	MOVW	$0, R1
119	STLRW	R1, (R0)
120	SVC	$SYS__lwp_exit
121	JMP	0(PC)
122
123TEXT runtime·open(SB),NOSPLIT|NOFRAME,$-8
124	MOVD	name+0(FP), R0		// arg 1 - pathname
125	MOVW	mode+8(FP), R1		// arg 2 - flags
126	MOVW	perm+12(FP), R2		// arg 3 - mode
127	SVC	$SYS_open
128	BCC	ok
129	MOVW	$-1, R0
130ok:
131	MOVW	R0, ret+16(FP)
132	RET
133
134TEXT runtime·closefd(SB),NOSPLIT,$-8
135	MOVW	fd+0(FP), R0		// arg 1 - fd
136	SVC	$SYS_close
137	BCC	ok
138	MOVW	$-1, R0
139ok:
140	MOVW	R0, ret+8(FP)
141	RET
142
143TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0
144	MOVW	fd+0(FP), R0		// arg 1 - fd
145	MOVD	p+8(FP), R1		// arg 2 - buf
146	MOVW	n+16(FP), R2		// arg 3 - count
147	SVC	$SYS_read
148	BCC	ok
149	NEG	R0, R0
150ok:
151	MOVW	R0, ret+24(FP)
152	RET
153
154// func pipe2(flags int32) (r, w int32, errno int32)
155TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
156	ADD	$16, RSP, R0
157	MOVW	flags+0(FP), R1
158	SVC	$SYS_pipe2
159	BCC	pipe2ok
160	NEG	R0, R0
161pipe2ok:
162	MOVW	R0, errno+16(FP)
163	RET
164
165TEXT runtime·write1(SB),NOSPLIT,$-8
166	MOVD	fd+0(FP), R0		// arg 1 - fd
167	MOVD	p+8(FP), R1		// arg 2 - buf
168	MOVW	n+16(FP), R2		// arg 3 - nbyte
169	SVC	$SYS_write
170	BCC	ok
171	NEG	R0, R0
172ok:
173	MOVW	R0, ret+24(FP)
174	RET
175
176TEXT runtime·usleep(SB),NOSPLIT,$24-4
177	MOVWU	usec+0(FP), R3
178	MOVD	R3, R5
179	MOVW	$1000000, R4
180	UDIV	R4, R3
181	MOVD	R3, 8(RSP)		// sec
182	MUL	R3, R4
183	SUB	R4, R5
184	MOVW	$1000, R4
185	MUL	R4, R5
186	MOVD	R5, 16(RSP)		// nsec
187
188	MOVD	$8(RSP), R0		// arg 1 - rqtp
189	MOVD	$0, R1			// arg 2 - rmtp
190	SVC	$SYS___nanosleep50
191	RET
192
193TEXT runtime·lwp_kill(SB),NOSPLIT,$0-16
194	MOVW	tid+0(FP), R0		// arg 1 - target
195	MOVD	sig+8(FP), R1		// arg 2 - signo
196	SVC	$SYS__lwp_kill
197	RET
198
199TEXT runtime·raiseproc(SB),NOSPLIT,$16
200	SVC	$SYS_getpid
201					// arg 1 - pid (from getpid)
202	MOVD	sig+0(FP), R1		// arg 2 - signo
203	SVC	$SYS_kill
204	RET
205
206TEXT runtime·setitimer(SB),NOSPLIT,$-8
207	MOVW	mode+0(FP), R0		// arg 1 - which
208	MOVD	new+8(FP), R1		// arg 2 - itv
209	MOVD	old+16(FP), R2		// arg 3 - oitv
210	SVC	$SYS___setitimer50
211	RET
212
213// func walltime() (sec int64, nsec int32)
214TEXT runtime·walltime(SB), NOSPLIT, $32
215	MOVW	$CLOCK_REALTIME, R0	// arg 1 - clock_id
216	MOVD	$8(RSP), R1		// arg 2 - tp
217	SVC	$SYS___clock_gettime50
218
219	MOVD	8(RSP), R0		// sec
220	MOVD	16(RSP), R1		// nsec
221
222	// sec is in R0, nsec in R1
223	MOVD	R0, sec+0(FP)
224	MOVW	R1, nsec+8(FP)
225	RET
226
227// int64 nanotime1(void) so really
228// void nanotime1(int64 *nsec)
229TEXT runtime·nanotime1(SB), NOSPLIT, $32
230	MOVD	$CLOCK_MONOTONIC, R0	// arg 1 - clock_id
231	MOVD	$8(RSP), R1		// arg 2 - tp
232	SVC	$SYS___clock_gettime50
233	MOVD	8(RSP), R0		// sec
234	MOVD	16(RSP), R2		// nsec
235
236	// sec is in R0, nsec in R2
237	// return nsec in R2
238	MOVD	$1000000000, R3
239	MUL	R3, R0
240	ADD	R2, R0
241
242	MOVD	R0, ret+0(FP)
243	RET
244
245TEXT runtime·getcontext(SB),NOSPLIT,$-8
246	MOVD	ctxt+0(FP), R0		// arg 1 - context
247	SVC	$SYS_getcontext
248	BCS	fail
249	RET
250fail:
251	MOVD	$0, R0
252	MOVD	R0, (R0)		// crash
253
254TEXT runtime·sigprocmask(SB),NOSPLIT,$0
255	MOVW	how+0(FP), R0		// arg 1 - how
256	MOVD	new+8(FP), R1		// arg 2 - set
257	MOVD	old+16(FP), R2		// arg 3 - oset
258	SVC	$SYS___sigprocmask14
259	BCS	fail
260	RET
261fail:
262	MOVD	$0, R0
263	MOVD	R0, (R0)		// crash
264
265TEXT sigreturn_tramp<>(SB),NOSPLIT,$-8
266	MOVD	g, R0
267	SVC	$SYS_setcontext
268	MOVD	$0, R0
269	MOVD	R0, (R0)		// crash
270
271TEXT runtime·sigaction(SB),NOSPLIT,$-8
272	MOVW	sig+0(FP), R0		// arg 1 - signum
273	MOVD	new+8(FP), R1		// arg 2 - nsa
274	MOVD	old+16(FP), R2		// arg 3 - osa
275					// arg 4 - tramp
276	MOVD	$sigreturn_tramp<>(SB), R3
277	MOVW	$2, R4			// arg 5 - vers
278	SVC	$SYS___sigaction_sigtramp
279	BCS	fail
280	RET
281fail:
282	MOVD	$0, R0
283	MOVD	R0, (R0)		// crash
284
285// XXX ???
286TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
287	MOVW	sig+8(FP), R0
288	MOVD	info+16(FP), R1
289	MOVD	ctx+24(FP), R2
290	MOVD	fn+0(FP), R11
291	BL	(R11)
292	RET
293
294TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$176
295	// Save callee-save registers in the case of signal forwarding.
296	// Please refer to https://golang.org/issue/31827 .
297	SAVE_R19_TO_R28(8*4)
298	SAVE_F8_TO_F15(8*14)
299	// Unclobber g for now (kernel uses it as ucontext ptr)
300	// See https://github.com/golang/go/issues/30824#issuecomment-492772426
301	// This is only correct in the non-cgo case.
302	// XXX should use lwp_getprivate as suggested.
303	// 8*36 is ucontext.uc_mcontext.__gregs[_REG_X28]
304	MOVD	8*36(g), g
305
306	// this might be called in external code context,
307	// where g is not set.
308	// first save R0, because runtime·load_g will clobber it
309	MOVD	R0, 8(RSP)		// signum
310	MOVB	runtime·iscgo(SB), R0
311	CMP 	$0, R0
312	// XXX branch destination
313	BEQ	2(PC)
314	BL	runtime·load_g(SB)
315
316	// Restore signum to R0.
317	MOVW	8(RSP), R0
318	// R1 and R2 already contain info and ctx, respectively.
319	BL	runtime·sigtrampgo<ABIInternal>(SB)
320
321	// Restore callee-save registers.
322	RESTORE_R19_TO_R28(8*4)
323	RESTORE_F8_TO_F15(8*14)
324
325	RET
326
327TEXT runtime·mmap(SB),NOSPLIT,$0
328	MOVD	addr+0(FP), R0		// arg 1 - addr
329	MOVD	n+8(FP), R1		// arg 2 - len
330	MOVW	prot+16(FP), R2		// arg 3 - prot
331	MOVW	flags+20(FP), R3	// arg 4 - flags
332	MOVW	fd+24(FP), R4		// arg 5 - fd
333	MOVW	$0, R5			// arg 6 - pad
334	MOVD	off+28(FP), R6		// arg 7 - offset
335	SVC	$SYS_mmap
336	BCS	fail
337	MOVD	R0, p+32(FP)
338	MOVD	$0, err+40(FP)
339	RET
340fail:
341	MOVD	$0, p+32(FP)
342	MOVD	R0, err+40(FP)
343	RET
344
345TEXT runtime·munmap(SB),NOSPLIT,$0
346	MOVD	addr+0(FP), R0	// arg 1 - addr
347	MOVD	n+8(FP), R1	// arg 2 - len
348	SVC	$SYS_munmap
349	BCS	fail
350	RET
351fail:
352	MOVD	$0, R0
353	MOVD	R0, (R0)	// crash
354
355TEXT runtime·madvise(SB),NOSPLIT,$0
356	MOVD	addr+0(FP), R0		// arg 1 - addr
357	MOVD	n+8(FP), R1		// arg 2 - len
358	MOVW	flags+16(FP), R2	// arg 3 - behav
359	SVC	$SYS_madvise
360	BCC	ok
361	MOVD	$-1, R0
362ok:
363	MOVD	R0, ret+24(FP)
364	RET
365
366TEXT runtime·sigaltstack(SB),NOSPLIT,$0
367	MOVD	new+0(FP), R0		// arg 1 - nss
368	MOVD	old+8(FP), R1		// arg 2 - oss
369	SVC	$SYS___sigaltstack14
370	BCS	fail
371	RET
372fail:
373	MOVD	$0, R0
374	MOVD	R0, (R0)		// crash
375
376TEXT runtime·sysctl(SB),NOSPLIT,$0
377	MOVD	mib+0(FP), R0		// arg 1 - name
378	MOVW	miblen+8(FP), R1	// arg 2 - namelen
379	MOVD	out+16(FP), R2		// arg 3 - oldp
380	MOVD	size+24(FP), R3		// arg 4 - oldlenp
381	MOVD	dst+32(FP), R4		// arg 5 - newp
382	MOVD	ndst+40(FP), R5		// arg 6 - newlen
383	SVC	$SYS___sysctl
384	BCC	ok
385	NEG	R0, R0
386ok:
387	MOVW	R0, ret+48(FP)
388	RET
389
390// int32 runtime·kqueue(void)
391TEXT runtime·kqueue(SB),NOSPLIT,$0
392	MOVD	$0, R0
393	SVC	$SYS_kqueue
394	BCC	ok
395	NEG	R0, R0
396ok:
397	MOVW	R0, ret+0(FP)
398	RET
399
400// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
401TEXT runtime·kevent(SB),NOSPLIT,$0
402	MOVW	kq+0(FP), R0	// arg 1 - kq
403	MOVD	ch+8(FP), R1	// arg 2 - changelist
404	MOVW	nch+16(FP), R2	// arg 3 - nchanges
405	MOVD	ev+24(FP), R3	// arg 4 - eventlist
406	MOVW	nev+32(FP), R4	// arg 5 - nevents
407	MOVD	ts+40(FP), R5	// arg 6 - timeout
408	SVC	$SYS___kevent50
409	BCC	ok
410	NEG	R0, R0
411ok:
412	MOVW	R0, ret+48(FP)
413	RET
414
415// func fcntl(fd, cmd, arg int32) (int32, int32)
416TEXT runtime·fcntl(SB),NOSPLIT,$0
417	MOVW	fd+0(FP), R0	// fd
418	MOVW	cmd+4(FP), R1	// cmd
419	MOVW	arg+8(FP), R2	// arg
420	SVC	$SYS_fcntl
421	BCC	noerr
422	MOVW	$-1, R1
423	MOVW	R1, ret+16(FP)
424	MOVW	R0, errno+20(FP)
425	RET
426noerr:
427	MOVW	R0, ret+16(FP)
428	MOVW	$0, errno+20(FP)
429	RET
430
431// func issetugid() int32
432TEXT runtime·issetugid(SB),NOSPLIT|NOFRAME,$0
433	SVC $SYS_issetugid
434	MOVW	R0, ret+0(FP)
435	RET
436