Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame^] | 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 | */ |
| 10 | |
| 11 | #include <asm/assembly.h> |
| 12 | #include <asm/offsets.h> |
| 13 | #include <asm/unistd.h> |
| 14 | #include <asm/errno.h> |
| 15 | |
| 16 | #ifdef __LP64__ |
| 17 | .level 2.0w |
| 18 | #else |
| 19 | .level 1.1 |
| 20 | #endif |
| 21 | .text |
| 22 | |
| 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 |
| 31 | |
| 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 */ |
| 48 | |
| 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 */ |
| 55 | |
| 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 | */ |
| 61 | |
| 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 */ |
| 65 | |
| 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 */ |
| 89 | |
| 90 | mfctl %cr11, %r27 /* i.e. SAR */ |
| 91 | STREG %r27, TASK_PT_SAR(%r1) |
| 92 | |
| 93 | loadgp |
| 94 | |
| 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 |
| 99 | |
| 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 |
| 108 | |
| 109 | syscall_nosys: |
| 110 | ldil L%hpux_syscall_exit,%r1 |
| 111 | be R%hpux_syscall_exit(%sr7,%r1) |
| 112 | ldo -ENOSYS(%r0),%r28 |
| 113 | |
| 114 | .align 4096 |
| 115 | .export end_hpux_gateway_page |
| 116 | end_hpux_gateway_page: |