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