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