1// Copyright 2015 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//go:build linux && (mips64 || mips64le)
6
7//
8// System calls and other sys.stuff for mips64, Linux
9//
10
11#include "go_asm.h"
12#include "go_tls.h"
13#include "textflag.h"
14
15#define AT_FDCWD -100
16
17#define SYS_exit		5058
18#define SYS_read		5000
19#define SYS_write		5001
20#define SYS_close		5003
21#define SYS_getpid		5038
22#define SYS_kill		5060
23#define SYS_mmap		5009
24#define SYS_munmap		5011
25#define SYS_setitimer		5036
26#define SYS_clone		5055
27#define SYS_nanosleep		5034
28#define SYS_sched_yield		5023
29#define SYS_rt_sigreturn	5211
30#define SYS_rt_sigaction	5013
31#define SYS_rt_sigprocmask	5014
32#define SYS_sigaltstack		5129
33#define SYS_madvise		5027
34#define SYS_mincore		5026
35#define SYS_gettid		5178
36#define SYS_futex		5194
37#define SYS_sched_getaffinity	5196
38#define SYS_exit_group		5205
39#define SYS_timer_create	5216
40#define SYS_timer_settime	5217
41#define SYS_timer_delete	5220
42#define SYS_tgkill		5225
43#define SYS_openat		5247
44#define SYS_clock_gettime	5222
45#define SYS_brk			5012
46#define SYS_pipe2		5287
47
48TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
49	MOVW	code+0(FP), R4
50	MOVV	$SYS_exit_group, R2
51	SYSCALL
52	RET
53
54// func exitThread(wait *atomic.Uint32)
55TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
56	MOVV	wait+0(FP), R1
57	// We're done using the stack.
58	MOVW	$0, R2
59	SYNC
60	MOVW	R2, (R1)
61	SYNC
62	MOVW	$0, R4	// exit code
63	MOVV	$SYS_exit, R2
64	SYSCALL
65	JMP	0(PC)
66
67TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
68	// This uses openat instead of open, because Android O blocks open.
69	MOVW	$AT_FDCWD, R4 // AT_FDCWD, so this acts like open
70	MOVV	name+0(FP), R5
71	MOVW	mode+8(FP), R6
72	MOVW	perm+12(FP), R7
73	MOVV	$SYS_openat, R2
74	SYSCALL
75	BEQ	R7, 2(PC)
76	MOVW	$-1, R2
77	MOVW	R2, ret+16(FP)
78	RET
79
80TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
81	MOVW	fd+0(FP), R4
82	MOVV	$SYS_close, R2
83	SYSCALL
84	BEQ	R7, 2(PC)
85	MOVW	$-1, R2
86	MOVW	R2, ret+8(FP)
87	RET
88
89TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
90	MOVV	fd+0(FP), R4
91	MOVV	p+8(FP), R5
92	MOVW	n+16(FP), R6
93	MOVV	$SYS_write, R2
94	SYSCALL
95	BEQ	R7, 2(PC)
96	SUBVU	R2, R0, R2	// caller expects negative errno
97	MOVW	R2, ret+24(FP)
98	RET
99
100TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
101	MOVW	fd+0(FP), R4
102	MOVV	p+8(FP), R5
103	MOVW	n+16(FP), R6
104	MOVV	$SYS_read, R2
105	SYSCALL
106	BEQ	R7, 2(PC)
107	SUBVU	R2, R0, R2	// caller expects negative errno
108	MOVW	R2, ret+24(FP)
109	RET
110
111// func pipe2(flags int32) (r, w int32, errno int32)
112TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
113	MOVV	$r+8(FP), R4
114	MOVW	flags+0(FP), R5
115	MOVV	$SYS_pipe2, R2
116	SYSCALL
117	BEQ	R7, 2(PC)
118	SUBVU	R2, R0, R2	// caller expects negative errno
119	MOVW	R2, errno+16(FP)
120	RET
121
122TEXT runtime·usleep(SB),NOSPLIT,$16-4
123	MOVWU	usec+0(FP), R3
124	MOVV	R3, R5
125	MOVW	$1000000, R4
126	DIVVU	R4, R3
127	MOVV	LO, R3
128	MOVV	R3, 8(R29)
129	MOVW	$1000, R4
130	MULVU	R3, R4
131	MOVV	LO, R4
132	SUBVU	R4, R5
133	MOVV	R5, 16(R29)
134
135	// nanosleep(&ts, 0)
136	ADDV	$8, R29, R4
137	MOVW	$0, R5
138	MOVV	$SYS_nanosleep, R2
139	SYSCALL
140	RET
141
142TEXT runtime·gettid(SB),NOSPLIT,$0-4
143	MOVV	$SYS_gettid, R2
144	SYSCALL
145	MOVW	R2, ret+0(FP)
146	RET
147
148TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
149	MOVV	$SYS_getpid, R2
150	SYSCALL
151	MOVW	R2, R16
152	MOVV	$SYS_gettid, R2
153	SYSCALL
154	MOVW	R2, R5	// arg 2 tid
155	MOVW	R16, R4	// arg 1 pid
156	MOVW	sig+0(FP), R6	// arg 3
157	MOVV	$SYS_tgkill, R2
158	SYSCALL
159	RET
160
161TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
162	MOVV	$SYS_getpid, R2
163	SYSCALL
164	MOVW	R2, R4	// arg 1 pid
165	MOVW	sig+0(FP), R5	// arg 2
166	MOVV	$SYS_kill, R2
167	SYSCALL
168	RET
169
170TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
171	MOVV	$SYS_getpid, R2
172	SYSCALL
173	MOVV	R2, ret+0(FP)
174	RET
175
176TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
177	MOVV	tgid+0(FP), R4
178	MOVV	tid+8(FP), R5
179	MOVV	sig+16(FP), R6
180	MOVV	$SYS_tgkill, R2
181	SYSCALL
182	RET
183
184TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
185	MOVW	mode+0(FP), R4
186	MOVV	new+8(FP), R5
187	MOVV	old+16(FP), R6
188	MOVV	$SYS_setitimer, R2
189	SYSCALL
190	RET
191
192TEXT runtime·timer_create(SB),NOSPLIT,$0-28
193	MOVW	clockid+0(FP), R4
194	MOVV	sevp+8(FP), R5
195	MOVV	timerid+16(FP), R6
196	MOVV	$SYS_timer_create, R2
197	SYSCALL
198	MOVW	R2, ret+24(FP)
199	RET
200
201TEXT runtime·timer_settime(SB),NOSPLIT,$0-28
202	MOVW	timerid+0(FP), R4
203	MOVW	flags+4(FP), R5
204	MOVV	new+8(FP), R6
205	MOVV	old+16(FP), R7
206	MOVV	$SYS_timer_settime, R2
207	SYSCALL
208	MOVW	R2, ret+24(FP)
209	RET
210
211TEXT runtime·timer_delete(SB),NOSPLIT,$0-12
212	MOVW	timerid+0(FP), R4
213	MOVV	$SYS_timer_delete, R2
214	SYSCALL
215	MOVW	R2, ret+8(FP)
216	RET
217
218TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
219	MOVV	addr+0(FP), R4
220	MOVV	n+8(FP), R5
221	MOVV	dst+16(FP), R6
222	MOVV	$SYS_mincore, R2
223	SYSCALL
224	SUBVU	R2, R0, R2	// caller expects negative errno
225	MOVW	R2, ret+24(FP)
226	RET
227
228// func walltime() (sec int64, nsec int32)
229TEXT runtime·walltime(SB),NOSPLIT,$16-12
230	MOVV	R29, R16	// R16 is unchanged by C code
231	MOVV	R29, R1
232
233	MOVV	g_m(g), R17	// R17 = m
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	MOVV	m_vdsoPC(R17), R2
239	MOVV	m_vdsoSP(R17), R3
240	MOVV	R2, 8(R29)
241	MOVV	R3, 16(R29)
242
243	MOVV	$ret-8(FP), R2 // caller's SP
244	MOVV	R31, m_vdsoPC(R17)
245	MOVV	R2, m_vdsoSP(R17)
246
247	MOVV	m_curg(R17), R4
248	MOVV	g, R5
249	BNE	R4, R5, noswitch
250
251	MOVV	m_g0(R17), R4
252	MOVV	(g_sched+gobuf_sp)(R4), R1	// Set SP to g0 stack
253
254noswitch:
255	SUBV	$16, R1
256	AND	$~15, R1	// Align for C code
257	MOVV	R1, R29
258
259	MOVW	$0, R4 // CLOCK_REALTIME
260	MOVV	$0(R29), R5
261
262	MOVV	runtime·vdsoClockgettimeSym(SB), R25
263	BEQ	R25, fallback
264
265	JAL	(R25)
266	// check on vdso call return for kernel compatibility
267	// see https://golang.org/issues/39046
268	// if we get any error make fallback permanent.
269	BEQ	R2, R0, finish
270	MOVV	R0, runtime·vdsoClockgettimeSym(SB)
271	MOVW	$0, R4 // CLOCK_REALTIME
272	MOVV	$0(R29), R5
273	JMP	fallback
274
275finish:
276	MOVV	0(R29), R3	// sec
277	MOVV	8(R29), R5	// nsec
278
279	MOVV	R16, R29	// restore SP
280	// Restore vdsoPC, vdsoSP
281	// We don't worry about being signaled between the two stores.
282	// If we are not in a signal handler, we'll restore vdsoSP to 0,
283	// and no one will care about vdsoPC. If we are in a signal handler,
284	// we cannot receive another signal.
285	MOVV	16(R29), R1
286	MOVV	R1, m_vdsoSP(R17)
287	MOVV	8(R29), R1
288	MOVV	R1, m_vdsoPC(R17)
289
290	MOVV	R3, sec+0(FP)
291	MOVW	R5, nsec+8(FP)
292	RET
293
294fallback:
295	MOVV	$SYS_clock_gettime, R2
296	SYSCALL
297	JMP finish
298
299TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
300	MOVV	R29, R16	// R16 is unchanged by C code
301	MOVV	R29, R1
302
303	MOVV	g_m(g), R17	// R17 = m
304
305	// Set vdsoPC and vdsoSP for SIGPROF traceback.
306	// Save the old values on stack and restore them on exit,
307	// so this function is reentrant.
308	MOVV	m_vdsoPC(R17), R2
309	MOVV	m_vdsoSP(R17), R3
310	MOVV	R2, 8(R29)
311	MOVV	R3, 16(R29)
312
313	MOVV	$ret-8(FP), R2 // caller's SP
314	MOVV	R31, m_vdsoPC(R17)
315	MOVV	R2, m_vdsoSP(R17)
316
317	MOVV	m_curg(R17), R4
318	MOVV	g, R5
319	BNE	R4, R5, noswitch
320
321	MOVV	m_g0(R17), R4
322	MOVV	(g_sched+gobuf_sp)(R4), R1	// Set SP to g0 stack
323
324noswitch:
325	SUBV	$16, R1
326	AND	$~15, R1	// Align for C code
327	MOVV	R1, R29
328
329	MOVW	$1, R4 // CLOCK_MONOTONIC
330	MOVV	$0(R29), R5
331
332	MOVV	runtime·vdsoClockgettimeSym(SB), R25
333	BEQ	R25, fallback
334
335	JAL	(R25)
336	// see walltime for detail
337	BEQ	R2, R0, finish
338	MOVV	R0, runtime·vdsoClockgettimeSym(SB)
339	MOVW	$1, R4 // CLOCK_MONOTONIC
340	MOVV	$0(R29), R5
341	JMP	fallback
342
343finish:
344	MOVV	0(R29), R3	// sec
345	MOVV	8(R29), R5	// nsec
346
347	MOVV	R16, R29	// restore SP
348	// Restore vdsoPC, vdsoSP
349	// We don't worry about being signaled between the two stores.
350	// If we are not in a signal handler, we'll restore vdsoSP to 0,
351	// and no one will care about vdsoPC. If we are in a signal handler,
352	// we cannot receive another signal.
353	MOVV	16(R29), R1
354	MOVV	R1, m_vdsoSP(R17)
355	MOVV	8(R29), R1
356	MOVV	R1, m_vdsoPC(R17)
357
358	// sec is in R3, nsec in R5
359	// return nsec in R3
360	MOVV	$1000000000, R4
361	MULVU	R4, R3
362	MOVV	LO, R3
363	ADDVU	R5, R3
364	MOVV	R3, ret+0(FP)
365	RET
366
367fallback:
368	MOVV	$SYS_clock_gettime, R2
369	SYSCALL
370	JMP	finish
371
372TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
373	MOVW	how+0(FP), R4
374	MOVV	new+8(FP), R5
375	MOVV	old+16(FP), R6
376	MOVW	size+24(FP), R7
377	MOVV	$SYS_rt_sigprocmask, R2
378	SYSCALL
379	BEQ	R7, 2(PC)
380	MOVV	R0, 0xf1(R0)	// crash
381	RET
382
383TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
384	MOVV	sig+0(FP), R4
385	MOVV	new+8(FP), R5
386	MOVV	old+16(FP), R6
387	MOVV	size+24(FP), R7
388	MOVV	$SYS_rt_sigaction, R2
389	SYSCALL
390	BEQ	R7, 2(PC)
391	SUBVU	R2, R0, R2	// caller expects negative errno
392	MOVW	R2, ret+32(FP)
393	RET
394
395TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
396	MOVW	sig+8(FP), R4
397	MOVV	info+16(FP), R5
398	MOVV	ctx+24(FP), R6
399	MOVV	fn+0(FP), R25
400	JAL	(R25)
401	RET
402
403TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$64
404	// initialize REGSB = PC&0xffffffff00000000
405	BGEZAL	R0, 1(PC)
406	SRLV	$32, R31, RSB
407	SLLV	$32, RSB
408
409	// this might be called in external code context,
410	// where g is not set.
411	MOVB	runtime·iscgo(SB), R1
412	BEQ	R1, 2(PC)
413	JAL	runtime·load_g(SB)
414
415	MOVW	R4, 8(R29)
416	MOVV	R5, 16(R29)
417	MOVV	R6, 24(R29)
418	MOVV	$runtime·sigtrampgo(SB), R1
419	JAL	(R1)
420	RET
421
422TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
423	JMP	runtime·sigtramp(SB)
424
425TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
426	MOVV	addr+0(FP), R4
427	MOVV	n+8(FP), R5
428	MOVW	prot+16(FP), R6
429	MOVW	flags+20(FP), R7
430	MOVW	fd+24(FP), R8
431	MOVW	off+28(FP), R9
432
433	MOVV	$SYS_mmap, R2
434	SYSCALL
435	BEQ	R7, ok
436	MOVV	$0, p+32(FP)
437	MOVV	R2, err+40(FP)
438	RET
439ok:
440	MOVV	R2, p+32(FP)
441	MOVV	$0, err+40(FP)
442	RET
443
444TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
445	MOVV	addr+0(FP), R4
446	MOVV	n+8(FP), R5
447	MOVV	$SYS_munmap, R2
448	SYSCALL
449	BEQ	R7, 2(PC)
450	MOVV	R0, 0xf3(R0)	// crash
451	RET
452
453TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
454	MOVV	addr+0(FP), R4
455	MOVV	n+8(FP), R5
456	MOVW	flags+16(FP), R6
457	MOVV	$SYS_madvise, R2
458	SYSCALL
459	MOVW	R2, ret+24(FP)
460	RET
461
462// int64 futex(int32 *uaddr, int32 op, int32 val,
463//	struct timespec *timeout, int32 *uaddr2, int32 val2);
464TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
465	MOVV	addr+0(FP), R4
466	MOVW	op+8(FP), R5
467	MOVW	val+12(FP), R6
468	MOVV	ts+16(FP), R7
469	MOVV	addr2+24(FP), R8
470	MOVW	val3+32(FP), R9
471	MOVV	$SYS_futex, R2
472	SYSCALL
473	BEQ	R7, 2(PC)
474	SUBVU	R2, R0, R2	// caller expects negative errno
475	MOVW	R2, ret+40(FP)
476	RET
477
478// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
479TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
480	MOVW	flags+0(FP), R4
481	MOVV	stk+8(FP), R5
482
483	// Copy mp, gp, fn off parent stack for use by child.
484	// Careful: Linux system call clobbers ???.
485	MOVV	mp+16(FP), R16
486	MOVV	gp+24(FP), R17
487	MOVV	fn+32(FP), R18
488
489	MOVV	R16, -8(R5)
490	MOVV	R17, -16(R5)
491	MOVV	R18, -24(R5)
492	MOVV	$1234, R16
493	MOVV	R16, -32(R5)
494
495	MOVV	$SYS_clone, R2
496	SYSCALL
497	BEQ	R7, 2(PC)
498	SUBVU	R2, R0, R2	// caller expects negative errno
499
500	// In parent, return.
501	BEQ	R2, 3(PC)
502	MOVW	R2, ret+40(FP)
503	RET
504
505	// In child, on new stack.
506	MOVV	-32(R29), R16
507	MOVV	$1234, R1
508	BEQ	R16, R1, 2(PC)
509	MOVV	R0, 0(R0)
510
511	// Initialize m->procid to Linux tid
512	MOVV	$SYS_gettid, R2
513	SYSCALL
514
515	MOVV	-24(R29), R18		// fn
516	MOVV	-16(R29), R17		// g
517	MOVV	-8(R29), R16		// m
518
519	BEQ	R16, nog
520	BEQ	R17, nog
521
522	MOVV	R2, m_procid(R16)
523
524	// TODO: setup TLS.
525
526	// In child, set up new stack
527	MOVV	R16, g_m(R17)
528	MOVV	R17, g
529	//CALL	runtime·stackcheck(SB)
530
531nog:
532	// Call fn
533	JAL	(R18)
534
535	// It shouldn't return.	 If it does, exit that thread.
536	MOVW	$111, R4
537	MOVV	$SYS_exit, R2
538	SYSCALL
539	JMP	-3(PC)	// keep exiting
540
541TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
542	MOVV	new+0(FP), R4
543	MOVV	old+8(FP), R5
544	MOVV	$SYS_sigaltstack, R2
545	SYSCALL
546	BEQ	R7, 2(PC)
547	MOVV	R0, 0xf1(R0)	// crash
548	RET
549
550TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
551	MOVV	$SYS_sched_yield, R2
552	SYSCALL
553	RET
554
555TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
556	MOVV	pid+0(FP), R4
557	MOVV	len+8(FP), R5
558	MOVV	buf+16(FP), R6
559	MOVV	$SYS_sched_getaffinity, R2
560	SYSCALL
561	BEQ	R7, 2(PC)
562	SUBVU	R2, R0, R2	// caller expects negative errno
563	MOVW	R2, ret+24(FP)
564	RET
565
566// func sbrk0() uintptr
567TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0-8
568	// Implemented as brk(NULL).
569	MOVV	$0, R4
570	MOVV	$SYS_brk, R2
571	SYSCALL
572	MOVV	R2, ret+0(FP)
573	RET
574
575TEXT runtime·access(SB),$0-20
576	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
577	MOVW	R0, ret+16(FP) // for vet
578	RET
579
580TEXT runtime·connect(SB),$0-28
581	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
582	MOVW	R0, ret+24(FP) // for vet
583	RET
584
585TEXT runtime·socket(SB),$0-20
586	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
587	MOVW	R0, ret+16(FP) // for vet
588	RET
589