1// Copyright 2016 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 system stuff for Linux s390x; see
6// /usr/include/asm/unistd.h for the syscall number definitions.
7
8#include "go_asm.h"
9#include "go_tls.h"
10#include "textflag.h"
11
12#define SYS_exit                  1
13#define SYS_read                  3
14#define SYS_write                 4
15#define SYS_open                  5
16#define SYS_close                 6
17#define SYS_getpid               20
18#define SYS_kill                 37
19#define SYS_fcntl                55
20#define SYS_gettimeofday         78
21#define SYS_mmap                 90
22#define SYS_munmap               91
23#define SYS_setitimer           104
24#define SYS_clone               120
25#define SYS_select              142
26#define SYS_sched_yield         158
27#define SYS_rt_sigreturn        173
28#define SYS_rt_sigaction        174
29#define SYS_rt_sigprocmask      175
30#define SYS_sigaltstack         186
31#define SYS_ugetrlimit          191
32#define SYS_madvise             219
33#define SYS_mincore             218
34#define SYS_gettid              236
35#define SYS_tkill               237
36#define SYS_futex               238
37#define SYS_sched_getaffinity   240
38#define SYS_exit_group          248
39#define SYS_epoll_create        249
40#define SYS_epoll_ctl           250
41#define SYS_epoll_wait          251
42#define SYS_clock_gettime       260
43#define SYS_epoll_create1       327
44
45TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
46	MOVW	code+0(FP), R2
47	MOVW	$SYS_exit_group, R1
48	SYSCALL
49	RET
50
51TEXT runtime·exit1(SB),NOSPLIT|NOFRAME,$0-4
52	MOVW	code+0(FP), R2
53	MOVW	$SYS_exit, R1
54	SYSCALL
55	RET
56
57TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
58	MOVD	name+0(FP), R2
59	MOVW	mode+8(FP), R3
60	MOVW	perm+12(FP), R4
61	MOVW	$SYS_open, R1
62	SYSCALL
63	MOVD	$-4095, R3
64	CMPUBLT	R2, R3, 2(PC)
65	MOVW	$-1, R2
66	MOVW	R2, ret+16(FP)
67	RET
68
69TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
70	MOVW	fd+0(FP), R2
71	MOVW	$SYS_close, R1
72	SYSCALL
73	MOVD	$-4095, R3
74	CMPUBLT	R2, R3, 2(PC)
75	MOVW	$-1, R2
76	MOVW	R2, ret+8(FP)
77	RET
78
79TEXT runtime·write(SB),NOSPLIT|NOFRAME,$0-28
80	MOVD	fd+0(FP), R2
81	MOVD	p+8(FP), R3
82	MOVW	n+16(FP), R4
83	MOVW	$SYS_write, R1
84	SYSCALL
85	MOVD	$-4095, R3
86	CMPUBLT	R2, R3, 2(PC)
87	MOVW	$-1, R2
88	MOVW	R2, ret+24(FP)
89	RET
90
91TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
92	MOVW	fd+0(FP), R2
93	MOVD	p+8(FP), R3
94	MOVW	n+16(FP), R4
95	MOVW	$SYS_read, R1
96	SYSCALL
97	MOVD	$-4095, R3
98	CMPUBLT	R2, R3, 2(PC)
99	MOVW	$-1, R2
100	MOVW	R2, ret+24(FP)
101	RET
102
103TEXT runtime·getrlimit(SB),NOSPLIT|NOFRAME,$0-20
104	MOVW	kind+0(FP), R2
105	MOVD	limit+8(FP), R3
106	MOVW	$SYS_ugetrlimit, R1
107	SYSCALL
108	MOVW	R2, ret+16(FP)
109	RET
110
111TEXT runtime·usleep(SB),NOSPLIT,$16-4
112	MOVW	usec+0(FP), R2
113	MOVD	R2, R4
114	MOVW	$1000000, R3
115	DIVD	R3, R2
116	MOVD	R2, 8(R15)
117	MULLD	R2, R3
118	SUB	R3, R4
119	MOVD	R4, 16(R15)
120
121	// select(0, 0, 0, 0, &tv)
122	MOVW	$0, R2
123	MOVW	$0, R3
124	MOVW	$0, R4
125	MOVW	$0, R5
126	ADD	$8, R15, R6
127	MOVW	$SYS_select, R1
128	SYSCALL
129	RET
130
131TEXT runtime·gettid(SB),NOSPLIT,$0-4
132	MOVW	$SYS_gettid, R1
133	SYSCALL
134	MOVW	R2, ret+0(FP)
135	RET
136
137TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
138	MOVW	$SYS_gettid, R1
139	SYSCALL
140	MOVW	R2, R2	// arg 1 tid
141	MOVW	sig+0(FP), R3	// arg 2
142	MOVW	$SYS_tkill, R1
143	SYSCALL
144	RET
145
146TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
147	MOVW	$SYS_getpid, R1
148	SYSCALL
149	MOVW	R2, R2	// arg 1 pid
150	MOVW	sig+0(FP), R3	// arg 2
151	MOVW	$SYS_kill, R1
152	SYSCALL
153	RET
154
155TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
156	MOVW	mode+0(FP), R2
157	MOVD	new+8(FP), R3
158	MOVD	old+16(FP), R4
159	MOVW	$SYS_setitimer, R1
160	SYSCALL
161	RET
162
163TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
164	MOVD	addr+0(FP), R2
165	MOVD	n+8(FP), R3
166	MOVD	dst+16(FP), R4
167	MOVW	$SYS_mincore, R1
168	SYSCALL
169	MOVW	R2, ret+24(FP)
170	RET
171
172// func now() (sec int64, nsec int32)
173TEXT time·now(SB),NOSPLIT,$16
174	MOVW	$0, R2 // CLOCK_REALTIME
175	MOVD	$tp-16(SP), R3
176	MOVW	$SYS_clock_gettime, R1
177	SYSCALL
178	LMG	tp-16(SP), R2, R3
179	// sec is in R2, nsec in R3
180	MOVD	R2, sec+0(FP)
181	MOVW	R3, nsec+8(FP)
182	RET
183
184TEXT runtime·nanotime(SB),NOSPLIT,$16
185	MOVW	$1, R2 // CLOCK_MONOTONIC
186	MOVD	$tp-16(SP), R3
187	MOVW	$SYS_clock_gettime, R1
188	SYSCALL
189	LMG	tp-16(SP), R2, R3
190	// sec is in R2, nsec in R3
191	// return nsec in R2
192	MULLD	$1000000000, R2
193	ADD	R3, R2
194	MOVD	R2, ret+0(FP)
195	RET
196
197TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
198	MOVW	how+0(FP), R2
199	MOVD	new+8(FP), R3
200	MOVD	old+16(FP), R4
201	MOVW	size+24(FP), R5
202	MOVW	$SYS_rt_sigprocmask, R1
203	SYSCALL
204	MOVD	$-4095, R3
205	CMPUBLT	R2, R3, 2(PC)
206	MOVD	R0, 0(R0) // crash
207	RET
208
209TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
210	MOVD	sig+0(FP), R2
211	MOVD	new+8(FP), R3
212	MOVD	old+16(FP), R4
213	MOVD	size+24(FP), R5
214	MOVW	$SYS_rt_sigaction, R1
215	SYSCALL
216	MOVW	R2, ret+32(FP)
217	RET
218
219TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
220	MOVW	sig+8(FP), R2
221	MOVD	info+16(FP), R3
222	MOVD	ctx+24(FP), R4
223	MOVD	fn+0(FP), R5
224	BL	R5
225	RET
226
227TEXT runtime·sigtramp(SB),NOSPLIT,$64
228	// initialize essential registers (just in case)
229	XOR	R0, R0
230
231	// this might be called in external code context,
232	// where g is not set.
233	MOVB	runtime·iscgo(SB), R6
234	CMPBEQ	R6, $0, 2(PC)
235	BL	runtime·load_g(SB)
236
237	MOVW	R2, 8(R15)
238	MOVD	R3, 16(R15)
239	MOVD	R4, 24(R15)
240	MOVD	$runtime·sigtrampgo(SB), R5
241	BL	R5
242	RET
243
244TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
245	BR	runtime·sigtramp(SB)
246
247// func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
248TEXT runtime·mmap(SB),NOSPLIT,$48-40
249	MOVD	addr+0(FP), R2
250	MOVD	n+8(FP), R3
251	MOVW	prot+16(FP), R4
252	MOVW	flags+20(FP), R5
253	MOVW	fd+24(FP), R6
254	MOVWZ	off+28(FP), R7
255
256	// s390x uses old_mmap, so the arguments need to be placed into
257	// a struct and a pointer to the struct passed to mmap.
258	MOVD	R2, addr-48(SP)
259	MOVD	R3, n-40(SP)
260	MOVD	R4, prot-32(SP)
261	MOVD	R5, flags-24(SP)
262	MOVD	R6, fd-16(SP)
263	MOVD	R7, off-8(SP)
264
265	MOVD	$addr-48(SP), R2
266	MOVW	$SYS_mmap, R1
267	SYSCALL
268	MOVD	$-4095, R3
269	CMPUBLT	R2, R3, 2(PC)
270	NEG	R2
271	MOVD	R2, ret+32(FP)
272	RET
273
274TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
275	MOVD	addr+0(FP), R2
276	MOVD	n+8(FP), R3
277	MOVW	$SYS_munmap, R1
278	SYSCALL
279	MOVD	$-4095, R3
280	CMPUBLT	R2, R3, 2(PC)
281	MOVD	R0, 0(R0) // crash
282	RET
283
284TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
285	MOVD	addr+0(FP), R2
286	MOVD	n+8(FP), R3
287	MOVW	flags+16(FP), R4
288	MOVW	$SYS_madvise, R1
289	SYSCALL
290	// ignore failure - maybe pages are locked
291	RET
292
293// int64 futex(int32 *uaddr, int32 op, int32 val,
294//	struct timespec *timeout, int32 *uaddr2, int32 val2);
295TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
296	MOVD	addr+0(FP), R2
297	MOVW	op+8(FP), R3
298	MOVW	val+12(FP), R4
299	MOVD	ts+16(FP), R5
300	MOVD	addr2+24(FP), R6
301	MOVW	val3+32(FP),  R7
302	MOVW	$SYS_futex, R1
303	SYSCALL
304	MOVW	R2, ret+40(FP)
305	RET
306
307// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
308TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
309	MOVW	flags+0(FP), R3
310	MOVD	stk+8(FP), R2
311
312	// Copy mp, gp, fn off parent stack for use by child.
313	// Careful: Linux system call clobbers ???.
314	MOVD	mp+16(FP), R7
315	MOVD	gp+24(FP), R8
316	MOVD	fn+32(FP), R9
317
318	MOVD	R7, -8(R2)
319	MOVD	R8, -16(R2)
320	MOVD	R9, -24(R2)
321	MOVD	$1234, R7
322	MOVD	R7, -32(R2)
323
324	SYSCALL $SYS_clone
325
326	// In parent, return.
327	CMPBEQ	R2, $0, 3(PC)
328	MOVW	R2, ret+40(FP)
329	RET
330
331	// In child, on new stack.
332	// initialize essential registers
333	XOR	R0, R0
334	MOVD	-32(R15), R7
335	CMP	R7, $1234
336	BEQ	2(PC)
337	MOVD	R0, 0(R0)
338
339	// Initialize m->procid to Linux tid
340	SYSCALL $SYS_gettid
341
342	MOVD	-24(R15), R9        // fn
343	MOVD	-16(R15), R8        // g
344	MOVD	-8(R15), R7         // m
345
346	CMPBEQ	R7, $0, nog
347	CMP	R8, $0
348	BEQ	nog
349
350	MOVD	R2, m_procid(R7)
351
352	// In child, set up new stack
353	MOVD	R7, g_m(R8)
354	MOVD	R8, g
355	//CALL	runtime·stackcheck(SB)
356
357nog:
358	// Call fn
359	BL	R9
360
361	// It shouldn't return.	 If it does, exit that thread.
362	MOVW	$111, R2
363	MOVW	$SYS_exit, R1
364	SYSCALL
365	BR	-2(PC)	// keep exiting
366
367TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
368	MOVD	new+0(FP), R2
369	MOVD	old+8(FP), R3
370	MOVW	$SYS_sigaltstack, R1
371	SYSCALL
372	MOVD	$-4095, R3
373	CMPUBLT	R2, R3, 2(PC)
374	MOVD	R0, 0(R0) // crash
375	RET
376
377TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
378	MOVW	$SYS_sched_yield, R1
379	SYSCALL
380	RET
381
382TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
383	MOVD	pid+0(FP), R2
384	MOVD	len+8(FP), R3
385	MOVD	buf+16(FP), R4
386	MOVW	$SYS_sched_getaffinity, R1
387	SYSCALL
388	MOVW	R2, ret+24(FP)
389	RET
390
391// int32 runtime·epollcreate(int32 size);
392TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0
393	MOVW    size+0(FP), R2
394	MOVW	$SYS_epoll_create, R1
395	SYSCALL
396	MOVW	R2, ret+8(FP)
397	RET
398
399// int32 runtime·epollcreate1(int32 flags);
400TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0
401	MOVW	flags+0(FP), R2
402	MOVW	$SYS_epoll_create1, R1
403	SYSCALL
404	MOVW	R2, ret+8(FP)
405	RET
406
407// func epollctl(epfd, op, fd int32, ev *epollEvent) int
408TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0
409	MOVW	epfd+0(FP), R2
410	MOVW	op+4(FP), R3
411	MOVW	fd+8(FP), R4
412	MOVD	ev+16(FP), R5
413	MOVW	$SYS_epoll_ctl, R1
414	SYSCALL
415	MOVW	R2, ret+24(FP)
416	RET
417
418// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
419TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0
420	MOVW	epfd+0(FP), R2
421	MOVD	ev+8(FP), R3
422	MOVW	nev+16(FP), R4
423	MOVW	timeout+20(FP), R5
424	MOVW	$SYS_epoll_wait, R1
425	SYSCALL
426	MOVW	R2, ret+24(FP)
427	RET
428
429// void runtime·closeonexec(int32 fd);
430TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0
431	MOVW    fd+0(FP), R2  // fd
432	MOVD    $2, R3  // F_SETFD
433	MOVD    $1, R4  // FD_CLOEXEC
434	MOVW	$SYS_fcntl, R1
435	SYSCALL
436	RET
437