Home | History | Annotate | Line # | Download | only in ia64
      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
     84 ia64_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 }
    102 gw_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 }
    115 gw_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 
    130 ENTRY_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 }
    192 END(break_sigtramp)
    193 
    194 ENTRY_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
    231 END(epc_sigtramp)
    232 
    233         .align          PAGE_SIZE
    234 
    235         .text
    236 
    237 ENTRY_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 }
    389 1:
    390 {       .mib
    391         srlz.d
    392         add             out0=16,sp
    393         br.call.sptk    rp=syscall
    394         ;;
    395 }
    396         .global         epc_syscall_return
    397 epc_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 }
    523 epc_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         ;;
    583 END(epc_syscall)
    584