1// Copyright 2012 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 ARM, 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
13// for EABI, as we don't support OABI
14#define SYS_BASE 0x0
15
16#define SYS_exit (SYS_BASE + 1)
17#define SYS_read (SYS_BASE + 3)
18#define SYS_write (SYS_BASE + 4)
19#define SYS_open (SYS_BASE + 5)
20#define SYS_close (SYS_BASE + 6)
21#define SYS_getpid (SYS_BASE + 20)
22#define SYS_kill (SYS_BASE + 37)
23#define SYS_sigaltstack (SYS_BASE + 53)
24#define SYS_munmap (SYS_BASE + 73)
25#define SYS_madvise (SYS_BASE + 75)
26#define SYS_setitimer (SYS_BASE + 83)
27#define SYS_fcntl (SYS_BASE + 92)
28#define SYS___sysctl (SYS_BASE + 202)
29#define SYS_nanosleep (SYS_BASE + 240)
30#define SYS_issetugid (SYS_BASE + 253)
31#define SYS_clock_gettime (SYS_BASE + 232)
32#define SYS_sched_yield (SYS_BASE + 331)
33#define SYS_sigprocmask (SYS_BASE + 340)
34#define SYS_kqueue (SYS_BASE + 362)
35#define SYS_sigaction (SYS_BASE + 416)
36#define SYS_thr_exit (SYS_BASE + 431)
37#define SYS_thr_self (SYS_BASE + 432)
38#define SYS_thr_kill (SYS_BASE + 433)
39#define SYS__umtx_op (SYS_BASE + 454)
40#define SYS_thr_new (SYS_BASE + 455)
41#define SYS_mmap (SYS_BASE + 477)
42#define SYS_cpuset_getaffinity (SYS_BASE + 487)
43#define SYS_pipe2 (SYS_BASE + 542)
44#define SYS_kevent (SYS_BASE + 560)
45
46TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
47	MOVW addr+0(FP), R0
48	MOVW mode+4(FP), R1
49	MOVW val+8(FP), R2
50	MOVW uaddr1+12(FP), R3
51	ADD $20, R13 // arg 5 is passed on stack
52	MOVW $SYS__umtx_op, R7
53	SWI $0
54	RSB.CS $0, R0
55	SUB $20, R13
56	// BCS error
57	MOVW	R0, ret+20(FP)
58	RET
59
60TEXT runtime·thr_new(SB),NOSPLIT,$0
61	MOVW param+0(FP), R0
62	MOVW size+4(FP), R1
63	MOVW $SYS_thr_new, R7
64	SWI $0
65	RSB.CS $0, R0
66	MOVW	R0, ret+8(FP)
67	RET
68
69TEXT runtime·thr_start(SB),NOSPLIT,$0
70	// set up g
71	MOVW m_g0(R0), g
72	MOVW R0, g_m(g)
73	BL runtime·emptyfunc(SB) // fault if stack check is wrong
74	BL runtime·mstart(SB)
75
76	MOVW $2, R8  // crash (not reached)
77	MOVW R8, (R8)
78	RET
79
80// Exit the entire program (like C exit)
81TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0
82	MOVW code+0(FP), R0	// arg 1 exit status
83	MOVW $SYS_exit, R7
84	SWI $0
85	MOVW.CS $0, R8 // crash on syscall failure
86	MOVW.CS R8, (R8)
87	RET
88
89// func exitThread(wait *atomic.Uint32)
90TEXT runtime·exitThread(SB),NOSPLIT,$0-4
91	MOVW	wait+0(FP), R0
92	// We're done using the stack.
93	MOVW	$0, R2
94storeloop:
95	LDREX	(R0), R4          // loads R4
96	STREX	R2, (R0), R1      // stores R2
97	CMP	$0, R1
98	BNE	storeloop
99	MOVW	$0, R0		// arg 1 long *state
100	MOVW	$SYS_thr_exit, R7
101	SWI	$0
102	MOVW.CS	$0, R8 // crash on syscall failure
103	MOVW.CS	R8, (R8)
104	JMP	0(PC)
105
106TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0
107	MOVW name+0(FP), R0	// arg 1 name
108	MOVW mode+4(FP), R1	// arg 2 mode
109	MOVW perm+8(FP), R2	// arg 3 perm
110	MOVW $SYS_open, R7
111	SWI $0
112	MOVW.CS	$-1, R0
113	MOVW	R0, ret+12(FP)
114	RET
115
116TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0
117	MOVW fd+0(FP), R0	// arg 1 fd
118	MOVW p+4(FP), R1	// arg 2 buf
119	MOVW n+8(FP), R2	// arg 3 count
120	MOVW $SYS_read, R7
121	SWI $0
122	RSB.CS	$0, R0		// caller expects negative errno
123	MOVW	R0, ret+12(FP)
124	RET
125
126// func pipe2(flags int32) (r, w int32, errno int32)
127TEXT runtime·pipe2(SB),NOSPLIT,$0-16
128	MOVW	$r+4(FP), R0
129	MOVW	flags+0(FP), R1
130	MOVW	$SYS_pipe2, R7
131	SWI	$0
132	RSB.CS $0, R0
133	MOVW	R0, errno+12(FP)
134	RET
135
136TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0
137	MOVW fd+0(FP), R0	// arg 1 fd
138	MOVW p+4(FP), R1	// arg 2 buf
139	MOVW n+8(FP), R2	// arg 3 count
140	MOVW $SYS_write, R7
141	SWI $0
142	RSB.CS	$0, R0		// caller expects negative errno
143	MOVW	R0, ret+12(FP)
144	RET
145
146TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0
147	MOVW fd+0(FP), R0	// arg 1 fd
148	MOVW $SYS_close, R7
149	SWI $0
150	MOVW.CS	$-1, R0
151	MOVW	R0, ret+4(FP)
152	RET
153
154TEXT runtime·thr_self(SB),NOSPLIT,$0-4
155	// thr_self(&0(FP))
156	MOVW $ret+0(FP), R0 // arg 1
157	MOVW $SYS_thr_self, R7
158	SWI $0
159	RET
160
161TEXT runtime·thr_kill(SB),NOSPLIT,$0-8
162	// thr_kill(tid, sig)
163	MOVW tid+0(FP), R0	// arg 1 id
164	MOVW sig+4(FP), R1	// arg 2 signal
165	MOVW $SYS_thr_kill, R7
166	SWI $0
167	RET
168
169TEXT runtime·raiseproc(SB),NOSPLIT,$0
170	// getpid
171	MOVW $SYS_getpid, R7
172	SWI $0
173	// kill(self, sig)
174				// arg 1 - pid, now in R0
175	MOVW sig+0(FP), R1	// arg 2 - signal
176	MOVW $SYS_kill, R7
177	SWI $0
178	RET
179
180TEXT runtime·setitimer(SB), NOSPLIT|NOFRAME, $0
181	MOVW mode+0(FP), R0
182	MOVW new+4(FP), R1
183	MOVW old+8(FP), R2
184	MOVW $SYS_setitimer, R7
185	SWI $0
186	RET
187
188// func fallback_walltime() (sec int64, nsec int32)
189TEXT runtime·fallback_walltime(SB), NOSPLIT, $32-12
190	MOVW $0, R0 // CLOCK_REALTIME
191	MOVW $8(R13), R1
192	MOVW $SYS_clock_gettime, R7
193	SWI $0
194
195	MOVW 8(R13), R0 // sec.low
196	MOVW 12(R13), R1 // sec.high
197	MOVW 16(R13), R2 // nsec
198
199	MOVW R0, sec_lo+0(FP)
200	MOVW R1, sec_hi+4(FP)
201	MOVW R2, nsec+8(FP)
202	RET
203
204// func fallback_nanotime() int64
205TEXT runtime·fallback_nanotime(SB), NOSPLIT, $32
206	MOVW $4, R0 // CLOCK_MONOTONIC
207	MOVW $8(R13), R1
208	MOVW $SYS_clock_gettime, R7
209	SWI $0
210
211	MOVW 8(R13), R0 // sec.low
212	MOVW 12(R13), R4 // sec.high
213	MOVW 16(R13), R2 // nsec
214
215	MOVW $1000000000, R3
216	MULLU R0, R3, (R1, R0)
217	MUL R3, R4
218	ADD.S R2, R0
219	ADC R4, R1
220
221	MOVW R0, ret_lo+0(FP)
222	MOVW R1, ret_hi+4(FP)
223	RET
224
225TEXT runtime·asmSigaction(SB),NOSPLIT|NOFRAME,$0
226	MOVW sig+0(FP), R0		// arg 1 sig
227	MOVW new+4(FP), R1		// arg 2 act
228	MOVW old+8(FP), R2		// arg 3 oact
229	MOVW $SYS_sigaction, R7
230	SWI $0
231	MOVW.CS	$-1, R0
232	MOVW	R0, ret+12(FP)
233	RET
234
235TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$0
236	// Reserve space for callee-save registers and arguments.
237	MOVM.DB.W [R4-R11], (R13)
238	SUB	$16, R13
239
240	// this might be called in external code context,
241	// where g is not set.
242	// first save R0, because runtime·load_g will clobber it
243	MOVW	R0, 4(R13) // signum
244	MOVB	runtime·iscgo(SB), R0
245	CMP 	$0, R0
246	BL.NE	runtime·load_g(SB)
247
248	MOVW	R1, 8(R13)
249	MOVW	R2, 12(R13)
250	BL	runtime·sigtrampgo(SB)
251
252	// Restore callee-save registers.
253	ADD	$16, R13
254	MOVM.IA.W (R13), [R4-R11]
255
256	RET
257
258TEXT runtime·mmap(SB),NOSPLIT,$16
259	MOVW addr+0(FP), R0		// arg 1 addr
260	MOVW n+4(FP), R1		// arg 2 len
261	MOVW prot+8(FP), R2		// arg 3 prot
262	MOVW flags+12(FP), R3		// arg 4 flags
263	// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
264	// note the C runtime only passes the 32-bit offset_lo to us
265	MOVW fd+16(FP), R4		// arg 5
266	MOVW R4, 4(R13)
267	MOVW off+20(FP), R5		// arg 6 lower 32-bit
268	// the word at 8(R13) is skipped due to 64-bit argument alignment.
269	MOVW R5, 12(R13)
270	MOVW $0, R6 		// higher 32-bit for arg 6
271	MOVW R6, 16(R13)
272	ADD $4, R13
273	MOVW $SYS_mmap, R7
274	SWI $0
275	SUB $4, R13
276	MOVW $0, R1
277	MOVW.CS R0, R1		// if failed, put in R1
278	MOVW.CS $0, R0
279	MOVW	R0, p+24(FP)
280	MOVW	R1, err+28(FP)
281	RET
282
283TEXT runtime·munmap(SB),NOSPLIT,$0
284	MOVW addr+0(FP), R0		// arg 1 addr
285	MOVW n+4(FP), R1		// arg 2 len
286	MOVW $SYS_munmap, R7
287	SWI $0
288	MOVW.CS $0, R8 // crash on syscall failure
289	MOVW.CS R8, (R8)
290	RET
291
292TEXT runtime·madvise(SB),NOSPLIT,$0
293	MOVW	addr+0(FP), R0		// arg 1 addr
294	MOVW	n+4(FP), R1		// arg 2 len
295	MOVW	flags+8(FP), R2		// arg 3 flags
296	MOVW	$SYS_madvise, R7
297	SWI	$0
298	MOVW.CS $-1, R0
299	MOVW	R0, ret+12(FP)
300	RET
301
302TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
303	MOVW new+0(FP), R0
304	MOVW old+4(FP), R1
305	MOVW $SYS_sigaltstack, R7
306	SWI $0
307	MOVW.CS $0, R8 // crash on syscall failure
308	MOVW.CS R8, (R8)
309	RET
310
311TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
312	MOVW	sig+4(FP), R0
313	MOVW	info+8(FP), R1
314	MOVW	ctx+12(FP), R2
315	MOVW	fn+0(FP), R11
316	MOVW	R13, R4
317	SUB	$24, R13
318	BIC	$0x7, R13 // alignment for ELF ABI
319	BL	(R11)
320	MOVW	R4, R13
321	RET
322
323TEXT runtime·usleep(SB),NOSPLIT,$16
324	MOVW usec+0(FP), R0
325	CALL runtime·usplitR0(SB)
326	// 0(R13) is the saved LR, don't use it
327	MOVW R0, 4(R13) // tv_sec.low
328	MOVW $0, R0
329	MOVW R0, 8(R13) // tv_sec.high
330	MOVW $1000, R2
331	MUL R1, R2
332	MOVW R2, 12(R13) // tv_nsec
333
334	MOVW $4(R13), R0 // arg 1 - rqtp
335	MOVW $0, R1      // arg 2 - rmtp
336	MOVW $SYS_nanosleep, R7
337	SWI $0
338	RET
339
340TEXT runtime·sysctl(SB),NOSPLIT,$0
341	MOVW mib+0(FP), R0	// arg 1 - name
342	MOVW miblen+4(FP), R1	// arg 2 - namelen
343	MOVW out+8(FP), R2	// arg 3 - old
344	MOVW size+12(FP), R3	// arg 4 - oldlenp
345	// arg 5 (newp) and arg 6 (newlen) are passed on stack
346	ADD $20, R13
347	MOVW $SYS___sysctl, R7
348	SWI $0
349	SUB.CS $0, R0, R0
350	SUB $20, R13
351	MOVW	R0, ret+24(FP)
352	RET
353
354TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
355	MOVW $SYS_sched_yield, R7
356	SWI $0
357	RET
358
359TEXT runtime·sigprocmask(SB),NOSPLIT,$0
360	MOVW how+0(FP), R0	// arg 1 - how
361	MOVW new+4(FP), R1	// arg 2 - set
362	MOVW old+8(FP), R2	// arg 3 - oset
363	MOVW $SYS_sigprocmask, R7
364	SWI $0
365	MOVW.CS $0, R8 // crash on syscall failure
366	MOVW.CS R8, (R8)
367	RET
368
369// int32 runtime·kqueue(void)
370TEXT runtime·kqueue(SB),NOSPLIT,$0
371	MOVW $SYS_kqueue, R7
372	SWI $0
373	RSB.CS $0, R0
374	MOVW	R0, ret+0(FP)
375	RET
376
377// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
378TEXT runtime·kevent(SB),NOSPLIT,$0
379	MOVW kq+0(FP), R0	// kq
380	MOVW ch+4(FP), R1	// changelist
381	MOVW nch+8(FP), R2	// nchanges
382	MOVW ev+12(FP), R3	// eventlist
383	ADD $20, R13	// pass arg 5 and 6 on stack
384	MOVW $SYS_kevent, R7
385	SWI $0
386	RSB.CS $0, R0
387	SUB $20, R13
388	MOVW	R0, ret+24(FP)
389	RET
390
391// func fcntl(fd, cmd, arg int32) (int32, int32)
392TEXT runtime·fcntl(SB),NOSPLIT,$0
393	MOVW fd+0(FP), R0	// fd
394	MOVW cmd+4(FP), R1	// cmd
395	MOVW arg+8(FP), R2	// arg
396	MOVW $SYS_fcntl, R7
397	SWI $0
398	MOVW $0, R1
399	MOVW.CS R0, R1
400	MOVW.CS $-1, R0
401	MOVW R0, ret+12(FP)
402	MOVW R1, errno+16(FP)
403	RET
404
405// TODO: this is only valid for ARMv7+
406TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
407	B	runtime·armPublicationBarrier(SB)
408
409// TODO(minux): this only supports ARMv6K+.
410TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
411	WORD $0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3
412	RET
413
414// func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
415TEXT runtime·cpuset_getaffinity(SB), NOSPLIT, $0-28
416	MOVW	level+0(FP), R0
417	MOVW	which+4(FP), R1
418	MOVW	id_lo+8(FP), R2
419	MOVW	id_hi+12(FP), R3
420	ADD	$20, R13	// Pass size and mask on stack.
421	MOVW	$SYS_cpuset_getaffinity, R7
422	SWI	$0
423	RSB.CS	$0, R0
424	SUB	$20, R13
425	MOVW	R0, ret+24(FP)
426	RET
427
428// func getCntxct(physical bool) uint32
429TEXT runtime·getCntxct(SB),NOSPLIT|NOFRAME,$0-8
430	MOVB	runtime·goarm(SB), R11
431	CMP	$7, R11
432	BLT	2(PC)
433	DMB
434
435	MOVB	physical+0(FP), R0
436	CMP	$1, R0
437	B.NE	3(PC)
438
439	// get CNTPCT (Physical Count Register) into R0(low) R1(high)
440	// mrrc    15, 0, r0, r1, cr14
441	WORD	$0xec510f0e
442	B	2(PC)
443
444	// get CNTVCT (Virtual Count Register) into R0(low) R1(high)
445	// mrrc    15, 1, r0, r1, cr14
446	WORD	$0xec510f1e
447
448	MOVW	R0, ret+4(FP)
449	RET
450
451// func issetugid() int32
452TEXT runtime·issetugid(SB),NOSPLIT,$0
453	MOVW $SYS_issetugid, R7
454	SWI $0
455	MOVW	R0, ret+0(FP)
456	RET
457