1/* 2 * Linux/PARISC Project (http://www.parisc-linux.org/) 3 * 4 * HP-UX System Call Wrapper routines and System Call Return Path 5 * 6 * Copyright (C) 2000 Hewlett-Packard (John Marvin) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23#ifdef CONFIG_64BIT 24#warning PA64 support needs more work...did first cut 25#endif 26 27#include <asm/asm-offsets.h> 28#include <asm/assembly.h> 29#include <asm/signal.h> 30#include <linux/linkage.h> 31 32 .level LEVEL 33 .text 34 35 /* These should probably go in a header file somewhere. 36 * They are duplicated in kernel/wrappers.S 37 * Possibly we should consider consolidating these 38 * register save/restore macros. 39 */ 40 .macro reg_save regs 41#ifdef CONFIG_64BIT 42#warning NEEDS WORK for 64-bit 43#endif 44 STREG %r3, PT_GR3(\regs) 45 STREG %r4, PT_GR4(\regs) 46 STREG %r5, PT_GR5(\regs) 47 STREG %r6, PT_GR6(\regs) 48 STREG %r7, PT_GR7(\regs) 49 STREG %r8, PT_GR8(\regs) 50 STREG %r9, PT_GR9(\regs) 51 STREG %r10,PT_GR10(\regs) 52 STREG %r11,PT_GR11(\regs) 53 STREG %r12,PT_GR12(\regs) 54 STREG %r13,PT_GR13(\regs) 55 STREG %r14,PT_GR14(\regs) 56 STREG %r15,PT_GR15(\regs) 57 STREG %r16,PT_GR16(\regs) 58 STREG %r17,PT_GR17(\regs) 59 STREG %r18,PT_GR18(\regs) 60 .endm 61 62 .macro reg_restore regs 63 LDREG PT_GR3(\regs), %r3 64 LDREG PT_GR4(\regs), %r4 65 LDREG PT_GR5(\regs), %r5 66 LDREG PT_GR6(\regs), %r6 67 LDREG PT_GR7(\regs), %r7 68 LDREG PT_GR8(\regs), %r8 69 LDREG PT_GR9(\regs), %r9 70 LDREG PT_GR10(\regs),%r10 71 LDREG PT_GR11(\regs),%r11 72 LDREG PT_GR12(\regs),%r12 73 LDREG PT_GR13(\regs),%r13 74 LDREG PT_GR14(\regs),%r14 75 LDREG PT_GR15(\regs),%r15 76 LDREG PT_GR16(\regs),%r16 77 LDREG PT_GR17(\regs),%r17 78 LDREG PT_GR18(\regs),%r18 79 .endm 80 81 82 .import sys_fork 83 84ENTRY(hpux_fork_wrapper) 85 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs 86 ;! pointer in task 87 reg_save %r1 88 89 STREG %r2,-20(%r30) 90 ldo 64(%r30),%r30 91 STREG %r2,PT_GR19(%r1) ;! save for child 92 STREG %r30,PT_GR21(%r1) ;! save for child 93 94 LDREG PT_GR30(%r1),%r25 95 mtctl %r25,%cr29 96 copy %r1,%r24 97 bl sys_clone,%r2 98 ldi SIGCHLD,%r26 99 100 LDREG -84(%r30),%r2 101fork_return: 102 ldo -64(%r30),%r30 103 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs 104 105 reg_restore %r1 106 107 /* 108 * HP-UX wants pid (child gets parent pid, parent gets child pid) 109 * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent). 110 * Linux fork returns 0 for child, pid for parent. Since HP-UX 111 * libc stub throws away parent pid and returns 0 for child, 112 * we'll just return 0 for parent pid now. Only applications 113 * that jump directly to the gateway page (not supported) will 114 * know the difference. We can fix this later if necessary. 115 */ 116 117 ldo -1024(%r0),%r1 118 comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */ 119 or,= %r28,%r0,%r0 120 or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ 121 ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ 122 123fork_exit: 124 bv %r0(%r2) 125 nop 126ENDPROC(hpux_fork_wrapper) 127 128 /* Set the return value for the child */ 129 130ENTRY(hpux_child_return) 131#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) 132 bl,n schedule_tail, %r2 133#endif 134 135 LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 136 b fork_return 137 copy %r0,%r28 138ENDPROC(hpux_child_return) 139 140 .import hpux_execve 141 142ENTRY(hpux_execv_wrapper) 143 copy %r0,%r24 /* NULL environment */ 144 145ENTRY(hpux_execve_wrapper) 146 147 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs 148 149 /* 150 * Do we need to save/restore r3-r18 here? 151 * I don't think so. why would new thread need old 152 * threads registers? 153 */ 154 155 /* Store arg0, arg1 and arg2 so that hpux_execve will find them */ 156 157 STREG %r26,PT_GR26(%r1) 158 STREG %r25,PT_GR25(%r1) 159 STREG %r24,PT_GR24(%r1) 160 161 STREG %r2,-20(%r30) 162 ldo 64(%r30),%r30 163 bl hpux_execve,%r2 164 copy %r1,%arg0 165 166 ldo -64(%r30),%r30 167 LDREG -20(%r30),%r2 168 169 /* If exec succeeded we need to load the args */ 170 171 ldo -1024(%r0),%r1 172 comb,>>= %r28,%r1,exec_error 173 copy %r2,%r19 174 ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr 175 LDREG TASK_PT_GR26(%r1),%r26 176 LDREG TASK_PT_GR25(%r1),%r25 177 LDREG TASK_PT_GR24(%r1),%r24 178 LDREG TASK_PT_GR23(%r1),%r23 179 copy %r0,%r2 /* Flag to syscall_exit not to clear args */ 180 181exec_error: 182 bv %r0(%r19) 183 nop 184ENDPROC(hpux_execv_wrapper) 185 186 .import hpux_pipe 187 188 /* HP-UX expects pipefd's returned in r28 & r29 */ 189 190ENTRY(hpux_pipe_wrapper) 191 STREG %r2,-20(%r30) 192 ldo 64(%r30),%r30 193 bl hpux_pipe,%r2 194 ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ 195 196 197 ldo -1024(%r0),%r1 198 comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ 199 LDREG -84(%r30),%r2 200 201 /* if success, load fd's from stack array */ 202 203 LDREG -56(%r30),%r28 204 LDREG -52(%r30),%r29 205 206pipe_exit: 207 bv %r0(%r2) 208 ldo -64(%r30),%r30 209ENDPROC(hpux_pipe_wrapper) 210 211 .import syscall_exit 212 213ENTRY(hpux_syscall_exit) 214 /* 215 * 216 * HP-UX call return conventions: 217 * 218 * if error: 219 * r22 = 1 220 * r28 = errno value 221 * r29 = secondary return value 222 * else 223 * r22 = 0 224 * r28 = return value 225 * r29 = secondary return value 226 * 227 * For now, we'll just check to see if r28 is < (unsigned long)-1024 228 * (to handle addresses > 2 Gb) and if so set r22 to zero. If not, 229 * we'll complement r28 and set r22 to 1. Wrappers will be 230 * needed for syscalls that care about the secondary return value. 231 * The wrapper may also need a way of avoiding the following code, 232 * but we'll deal with that when it becomes necessary. 233 */ 234 235 ldo -1024(%r0),%r1 236 comb,<< %r28,%r1,no_error 237 copy %r0,%r22 238 subi 0,%r28,%r28 239 ldo 1(%r0),%r22 240 241no_error: 242 b,n syscall_exit 243ENDPROC(hpux_syscall_exit) 244 245 .import hpux_unimplemented 246 247ENTRY(hpux_unimplemented_wrapper) 248 b hpux_unimplemented 249 STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */ 250ENDPROC(hpux_unimplemented_wrapper) 251