Linux 2.6.13-rc4
[linux-2.6/next.git] / arch / parisc / hpux / gate.S
blob2680a1c0fa7742dd0b23652bdf09fc58e7e710a5
1 /*
2  *
3  * Linux/PARISC Project (http://www.parisc-linux.org/)
4  *
5  * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
6  * Licensed under the GNU GPL.
7  * thanks to Philipp Rumpf, Mike Shaver and various others
8  * sorry about the wall, puffin..
9  */
11 #include <asm/assembly.h>
12 #include <asm/offsets.h>
13 #include <asm/unistd.h>
14 #include <asm/errno.h>
16 #ifdef __LP64__
17         .level          2.0w
18 #else
19         .level          1.1
20 #endif
21         .text
23 #ifdef __LP64__
24 #define FRAME_SIZE      128
25 #else
26 #define FRAME_SIZE      64
27 #endif
28         .import hpux_call_table
29         .import hpux_syscall_exit,code
30         .export hpux_gateway_page
32         .align 4096
33 hpux_gateway_page:
34         nop
35 #ifdef __LP64__
36 #warning NEEDS WORK for 64-bit
37 #endif
38         ldw     -64(%r30), %r29                 ;! 8th argument
39         ldw     -60(%r30), %r19                 ;! 7th argument
40         ldw     -56(%r30), %r20                 ;! 6th argument
41         ldw     -52(%r30), %r21                 ;! 5th argument
42         gate    .+8, %r0                        /* become privileged */
43         mtsp    %r0,%sr4                        /* get kernel space into sr4 */
44         mtsp    %r0,%sr5                        /* get kernel space into sr5 */
45         mtsp    %r0,%sr6                        /* get kernel space into sr6 */
46         mfsp    %sr7,%r1                        /* save user sr7 */
47         mtsp    %r1,%sr3                        /* and store it in sr3 */
49         mtctl   %r30,%cr28
50         mfctl   %cr30,%r1
51         xor     %r1,%r30,%r30                   /* ye olde xor trick */
52         xor     %r1,%r30,%r1
53         xor     %r1,%r30,%r30
54         ldo     TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30  /* set up kernel stack */
56         /* N.B.: It is critical that we don't set sr7 to 0 until r30
57          *       contains a valid kernel stack pointer. It is also
58          *       critical that we don't start using the kernel stack
59          *       until after sr7 has been set to 0.
60          */
62         mtsp    %r0,%sr7                        /* get kernel space into sr7 */
63         STREG   %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */
64         ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1   /* get task ptr in %r1 */
66         /* Save some registers for sigcontext and potential task
67            switch (see entry.S for the details of which ones are
68            saved/restored).  TASK_PT_PSW is zeroed so we can see whether
69            a process is on a syscall or not.  For an interrupt the real
70            PSW value is stored.  This is needed for gdb and sys_ptrace. */
71         STREG   %r0,  TASK_PT_PSW(%r1)
72         STREG   %r2,  TASK_PT_GR2(%r1)          /* preserve rp */
73         STREG   %r19, TASK_PT_GR19(%r1)         /* 7th argument */
74         STREG   %r20, TASK_PT_GR20(%r1)         /* 6th argument */
75         STREG   %r21, TASK_PT_GR21(%r1)         /* 5th argument */
76         STREG   %r22, TASK_PT_GR22(%r1)         /* syscall # */
77         STREG   %r23, TASK_PT_GR23(%r1)         /* 4th argument */
78         STREG   %r24, TASK_PT_GR24(%r1)         /* 3rd argument */
79         STREG   %r25, TASK_PT_GR25(%r1)         /* 2nd argument */
80         STREG   %r26, TASK_PT_GR26(%r1)         /* 1st argument */
81         STREG   %r27, TASK_PT_GR27(%r1)         /* user dp */
82         STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
83         STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
84         STREG   %r29, TASK_PT_GR29(%r1)         /* 8th argument */
85         STREG   %r31, TASK_PT_GR31(%r1)         /* preserve syscall return ptr */
86         
87         ldo     TASK_PT_FR0(%r1), %r27          /* save fpregs from the kernel */
88         save_fp %r27                            /* or potential task switch  */
90         mfctl   %cr11, %r27                     /* i.e. SAR */
91         STREG   %r27, TASK_PT_SAR(%r1)
93         loadgp
95         stw     %r21, -52(%r30)                 ;! 5th argument
96         stw     %r20, -56(%r30)                 ;! 6th argument
97         stw     %r19, -60(%r30)                 ;! 7th argument
98         stw     %r29, -64(%r30)                 ;! 8th argument
100         ldil    L%hpux_call_table, %r21
101         ldo     R%hpux_call_table(%r21), %r21
102         comiclr,>>=     __NR_HPUX_syscalls, %r22, %r0
103         b,n     syscall_nosys
104         ldwx,s  %r22(%r21), %r21
105         ldil    L%hpux_syscall_exit,%r2
106         be      0(%sr7,%r21)
107         ldo     R%hpux_syscall_exit(%r2),%r2
109 syscall_nosys:
110         ldil    L%hpux_syscall_exit,%r1
111         be      R%hpux_syscall_exit(%sr7,%r1)
112         ldo     -ENOSYS(%r0),%r28
114         .align 4096
115         .export end_hpux_gateway_page
116 end_hpux_gateway_page: