syscall.S revision 270573
1/*-
2 * Copyright (c) 2002, 2003 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: stable/10/sys/ia64/ia64/syscall.S 270573 2014-08-25 15:15:59Z marcel $
27 */
28
29#include <sys/syscall.h>
30#include <machine/asm.h>
31#include <assym.s>
32
33/*
34 * A process performs a syscall by performing an indirect call to the
35 * address stored in ar.k5. The contents of ar.pfs and rp should be
36 * saved prior to the syscall in r9 and r10 respectively. The kernel
37 * will restore these values on return. The value of gp is preserved
38 * across the call. This allows for small enough syscall stubs without
39 * getting too weird.
40 * The address in ar.k5 is the start of the EPC gateway page and also
41 * the syscall entry point. The syscall code in the gateway page is
42 * primarily responsible for increasing the privilege level, but will
43 * also make sure we have a reliable psr.
44 *
45 * A process defines:
46 *	r8		-	syscall number
47 *	r9		-	copy of ar.pfs
48 *	r10		-	copy of rp
49 *	in0-in7		-	syscall arguments
50 *
51 * A syscall returns:
52 *	r8+r9		-	syscall return value(s)
53 *	r10		-	syscall error flag
54 *	ar.pfs		-	restored from r9
55 *	rp		-	restored from r10
56 *	gp		-	preserved
57 *
58 * The EPC syscall code defines:
59 *	r11		-	copy of psr.l
60 *	r14		-	Kernel memory stack
61 *	r15		-	Kernel register stack
62 *
63 * Also in the gateway page are the signal trampolines. As such, stacks
64 * don't have to be made executable per se. Since debuggers have a need
65 * to know about trampolines, we probably need to define a table of
66 * vectors or something along those lines so that debuggers can get the
67 * information they need and we have the freedom to move code around.
68 */
69
70	.section	.text.gateway, "ax"
71	.align		PAGE_SIZE
72	.global		ia64_gateway_page
73ia64_gateway_page:
74{	.mmb
75	mov		r14=ar.k7		// Memory stack
76	mov		r15=ar.k6		// Register stack
77	epc
78	;;
79}
80{	.mlx
81	mov		r11=psr
82	movl		r31=epc_syscall
83	;;
84}
85{	.mib
86	rum		psr.be
87	mov		b7=r31
88	br		b7
89	;;
90}
91gw_ret:
92{	.mmi
93	mov		ar.rnat=r22
94	;;
95	mov		ar.rsc=r24
96	mov		ar.pfs=r20
97}
98{	.mib
99	mov		ar.fpsr=r25
100	mov		b0=r18
101	br.sptk		b6
102	;;
103}
104gw_ret_ia32:
105{	.mmi
106	flushrs
107	nop		0
108	nop		0
109	;;
110}
111{	.mib
112	nop		0
113	nop		0
114	br.ia.sptk	b6
115	;;
116}
117
118
119ENTRY_NOPROFILE(break_sigtramp, 0)
120{	.mib
121	mov		ar.rsc=0
122	cmp.ne		p15,p0=0,gp
123	cover
124	;;
125}
126{	.mmi
127	flushrs
128(p15)	invala
129	add		r16=16+UC_MCONTEXT+MC_SPECIAL,sp
130	;;
131}
132{	.mmi
133	mov		r17=ar.bsp
134	mov		r18=ar.rnat
135	add		r14=40,r16
136	;;
137}
138{	.mmi
139	st8		[r14]=r17,64		// bspstore
140(p15)	mov		ar.bspstore=gp
141	add		r15=48,r16
142	;;
143}
144{	.mmi
145	st8		[r15]=r18		// rnat
146	st8		[r14]=r0		// ndirty
147	nop		0
148	;;
149}
150{	.mmi
151	alloc		r14=ar.pfs, 0, 0, 3, 0
152	mov		ar.rsc=15
153	mov		out0=r8
154	;;
155}
156{	.mmi
157	ld8		r16=[r10],8		// function address
158	;;
159	ld8		gp=[r10]		// function's gp value
160	mov		b7=r16
161	;;
162}
163{	.mib
164	mov		out1=r9
165	add		out2=16,sp
166	br.call.sptk	rp=b7
167	;;
168}
169{	.mmi
170	mov		r15=SYS_sigreturn
171	add		out0=16,sp
172	break		0x100000
173	;;
174}
175{	.mmi
176	mov		r15=SYS_exit
177	mov		out0=ret0
178	break		0x100000
179	;;
180}
181END(break_sigtramp)
182
183ENTRY_NOPROFILE(epc_sigtramp, 0)
184{	.mmi
185	ld8		r16=[r10],8		// function address
186	mov		ar.rsc=0
187	cmp.ne		p15,p0=0,gp
188	;;
189}
190{	.mmi
191(p15)	invala
192(p15)	mov		ar.bspstore=gp
193	mov		b7=r16
194	;;
195}
196{	.mmi
197	alloc		r14=ar.pfs, 0, 0, 3, 0
198	mov		ar.rsc=15
199	nop		0
200	;;
201}
202{	.mii
203	ld8		gp=[r10]		// function's gp value
204	mov		out0=r8
205	mov		out1=r9
206}
207{	.mib
208	add		out2=16,sp
209	nop		0
210	br.call.sptk	rp=b7
211	;;
212}
213	add		out0=16,sp
214	CALLSYS_NOERROR(sigreturn)
215	mov		out0=ret0
216	CALLSYS_NOERROR(exit)
217END(epc_sigtramp)
218
219	.align		PAGE_SIZE
220
221	.text
222
223ENTRY_NOPROFILE(epc_syscall, 8)
224	.prologue
225	.unwabi		@svr4, 'E'
226	.save		rp, r0
227	.body
228{	.mmi
229	mov		r16=ar.rsc
230	mov		ar.rsc=0
231	nop		0
232	;;
233}
234{	.mmi
235	mov		r18=ar.bspstore
236	;;
237	mov		r19=ar.rnat
238	dep		r15=r18,r15,0,9
239	;;
240}
241{	.mmi
242	mov		r21=ar.unat
243	add		r30=-SIZEOF_TRAPFRAME,r14
244	mov		r20=sp
245	;;
246}
247{	.mii
248	mov		r17=r13
249	dep		r30=0,r30,0,10
250	;;
251	add		sp=-16,r30
252	;;
253}
254{	.mmi
255	mov		ar.bspstore=r15
256	;;
257	mov		ar.rnat=r19
258	add		r31=8,r30
259	;;
260}
261{	.mmi
262	mov		r13=ar.k4
263	mov		r22=ar.fpsr
264	sub		r29=r14,r30
265}
266{	.mmi
267	mov		r23=ar.bsp
268	mov		ar.rsc=3
269	add		r28=FRAME_SYSCALL,r0
270	;;
271}
272{	.mmi
273	st8		[r30]=r29,16		// tf_length
274	st8		[r31]=r28,16		// tf_flags
275	mov		r24=rp
276	;;
277}
278{	.mmi
279	st8		[r30]=r20,16		// sp
280	st8		[r31]=r21,16		// unat
281	mov		r25=pr
282	;;
283}
284{	.mmi
285	st8		[r30]=r10,16		// rp (syscall caller)
286	st8		[r31]=r25,16		// pr
287	mov		r26=ar.pfs
288	;;
289}
290{	.mmi
291	st8		[r30]=r9,16		// pfs (syscall caller)
292	st8		[r31]=r18,16		// bspstore
293	sub		r27=r23,r15
294	;;
295}
296{	.mmi
297	st8		[r30]=r19,16		// rnat
298	st8		[r31]=r0,16		// __spare
299	dep		r11=-1,r11,44,1		// Set psr.bn=1
300	;;
301}
302{	.mmi
303	st8		[r30]=r17,16		// tp
304	st8		[r31]=r16,16		// rsc
305	dep		r11=-1,r11,32,2		// Set psr.cpl=3
306	;;
307}
308{	.mmi
309	st8		[r30]=r22,16		// fpsr
310	st8		[r31]=r11,16		// psr
311	nop		0
312	;;
313}
314{	.mmi
315	st8		[r30]=r1,16		// gp
316	st8		[r31]=r27,16		// ndirty
317	nop		0
318	;;
319}
320{	.mmi
321	st8		[r30]=r26,16		// pfs (syscall stub)
322	st8		[r31]=r24,16		// rp (syscall stub)
323	nop		0
324	;;
325}
326{	.mmi
327	st8		[r30]=r0,80		// ifa
328	st8		[r31]=r0,80		// isr
329	nop		0
330	;;
331}
332{	.mmi
333	alloc		r14=ar.pfs,0,0,8,0
334	st8		[r30]=r8,16		// syscall number (=r15)
335	nop		0
336	;;
337}
338{	.mmi
339	.mem.offset	0,0
340	st8.spill	[r31]=r32,16		// arg0 (=r16)
341	.mem.offset	8,0
342	st8.spill	[r30]=r33,16		// arg1 (=r17)
343	nop		0
344	;;
345}
346{	.mmi
347	.mem.offset	16,0
348	st8.spill	[r31]=r34,16		// arg2 (=r18)
349	.mem.offset	24,0
350	st8.spill	[r30]=r35,16		// arg3 (=r19)
351	nop		0
352	;;
353}
354{	.mmi
355	.mem.offset	32,0
356	st8.spill	[r31]=r36,16		// arg4 (=r20)
357	.mem.offset	40,0
358	st8.spill	[r30]=r37,16		// arg5 (=r21)
359	nop		0
360	;;
361}
362{	.mmi
363	.mem.offset	48,0
364	st8.spill	[r31]=r38		// arg6 (=r22)
365	.mem.offset	56,0
366	st8.spill	[r30]=r39		// arg7 (=r23)
367	nop		0
368	;;
369}
370{	.mlx
371	ssm		psr.dfh|psr.ac
372	movl		gp=__gp
373	;;
374}
3751:
376{	.mib
377	srlz.d
378	add		out0=16,sp
379	br.call.sptk	rp=syscall
380	;;
381}
382	.global		epc_syscall_return
383epc_syscall_return:
384{	.mib
385	add		out0=16,sp
386	nop		0
387	br.call.sptk	rp=do_ast
388	;;
389}
390{	.mib
391	cmp4.eq		p15,p0=ERESTART,r8
392	add		r14=24,sp
393(p15)	br.spnt		1b			// restart syscall
394	;;
395}
396{	.mmi
397	ld8		r14=[r14]		// tf_flags
398	nop		0
399	nop		0
400	;;
401}
402{	.mib
403	nop		0
404	tbit.z		p15,p0=r14,0
405(p15)	br.spnt		exception_restore
406	;;
407}
408{	.mmi
409	alloc		r31=ar.pfs,0,0,0,0
410	add		r14=32,sp
411	add		r15=16,sp
412	;;
413}
414{	.mmi
415	ld8		r31=[r15],24		// tf_length
416	ld8		r16=[r14],16		// sp
417	add		sp=16,sp
418	;;
419}
420{	.mmi
421	ld8		r17=[r15],16		// unat (before)
422	ld8		r18=[r14],16		// rp (syscall caller)
423	add		r31=r31,sp
424	;;
425}
426{	.mmi
427	ld8		r19=[r15],16		// pr
428	ld8		r20=[r14],16		// pfs (syscall caller)
429	nop		0
430	;;
431}
432{	.mmi
433	ld8		r21=[r15],24		// bspstore
434	ld8		r22=[r14],24		// rnat
435	mov		pr=r19,0x1fffe
436	;;
437}
438{	.mmi
439	ld8		r23=[r15],16		// tp
440	ld8		r24=[r14],16		// rsc
441	nop		0
442	;;
443}
444{	.mmi
445	ld8		r25=[r15],16		// fpsr
446	ld8		r26=[r14],16		// psr
447	nop		0
448	;;
449}
450{	.mmi
451	ld8		gp=[r15],16		// gp
452	ld8		r27=[r14],16		// ndirty
453	tbit.z		p14,p15=r26,34		// p14=ia64, p15=ia32
454	;;
455}
456{	.mmi
457	ld8		r28=[r15],56		// pfs (syscall stub)
458	ld8		r29=[r14],56		// rp (syscall stub)
459	shl		r27=r27,16
460	;;
461}
462{	.mmi
463	ld8		r8=[r15],16		// r8
464	mov		ar.rsc=r27
465	mov		b6=r29
466	;;
467}
468{	.mmb
469	ld8		r9=[r14],40		// r9
470	ld8		r10=[r15],40		// r10
471(p15)	br.spnt		epc_syscall_setup_ia32
472	;;
473}
474{	.mmi
475	loadrs
476	mov		ar.k7=r31
477	mov		sp=r16
478	;;
479}
480{	.mmi
481	mov		r30=ar.bspstore
482	mov		r14=ar.k5
483	mov		ar.pfs=r28
484	;;
485}
486{	.mmi
487	mov		ar.bspstore=r21
488	add		r14=gw_ret-ia64_gateway_page,r14
489	dep		r30=0,r30,0,13		// 8KB aligned.
490	;;
491}
492{	.mii
493	mov		ar.k6=r30
494	mov		r13=r23
495	nop		0
496}
497{	.mmi
498	mov		psr.l=r26
499	mov		ar.unat=r17
500	nop		0
501	;;
502}
503{	.mib
504	srlz.d
505	mov		b7=r14
506	br.ret.sptk	b7
507	;;
508}
509epc_syscall_setup_ia32:
510{	.mmi
511	loadrs
512	mov		ar.k7=r31
513	mov		sp=r16
514	;;
515}
516{	.mmi
517	mov		r30=ar.bspstore
518	;;
519	mov		ar.unat=r17
520	dep		r30=0,r30,0,13		// 8KB aligned
521	;;
522}
523{	.mmi
524	mov		ar.k6=r30
525	mov		ar.bspstore=r21
526	mov		r11=r0
527	;;
528}
529{	.mmi
530	ld8		r16=[r14],64
531	ld8		r17=[r15],80
532	mov		r13=r0
533	;;
534}
535
536	ld8		r24=[r14],32
537	ld8		r27=[r15],16
538	;;
539	ld8		r28=[r14],16
540	ld8		r29=[r15],16
541	;;
542	ld8		r30=[r14],40
543	ld8		r31=[r15],40
544	;;
545
546{	.mmi
547	ld8		r2=[r14]
548	ld8		r3=[r15]
549	mov		r14=r0
550	;;
551}
552{	.mmi
553	mov		ar.csd=r2
554	mov		ar.ssd=r3
555	mov		r15=r0
556	;;
557}
558
559	mov		r2=ar.k5
560	mov		psr.l=r26
561	;;
562	srlz.d
563	add		r2=gw_ret_ia32-ia64_gateway_page,r2
564	;;
565	mov		ar.rsc=0
566	mov		b7=r2
567	br.ret.sptk	b7
568	;;
569END(epc_syscall)
570