1 /* $NetBSD: sunos_syscall.c,v 1.2 2002/11/15 20:06:02 manu Exp $ */ 2 3 /*- 4 * Portions Copyright (c) 2000 The NetBSD Foundation, Inc. 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the NetBSD 18 * Foundation, Inc. and its contributors. 19 * 4. Neither the name of The NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* 37 * Copyright (c) 1988 University of Utah. 38 * Copyright (c) 1982, 1986, 1990, 1993 39 * The Regents of the University of California. All rights reserved. 40 * 41 * This code is derived from software contributed to Berkeley by 42 * the Systems Programming Group of the University of Utah Computer 43 * Science Department. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the University of 56 * California, Berkeley and its contributors. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 * 73 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 74 * 75 * @(#)trap.c 8.5 (Berkeley) 1/4/94 76 */ 77 78 #include "opt_syscall_debug.h" 79 #include "opt_execfmt.h" 80 #include "opt_ktrace.h" 81 #include "opt_systrace.h" 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/proc.h> 86 #include <sys/acct.h> 87 #include <sys/kernel.h> 88 #include <sys/syscall.h> 89 #include <sys/syslog.h> 90 #include <sys/user.h> 91 #ifdef KTRACE 92 #include <sys/ktrace.h> 93 #endif 94 #ifdef SYSTRACE 95 #include <sys/systrace.h> 96 #endif 97 98 #include <machine/psl.h> 99 #include <machine/cpu.h> 100 #include <machine/reg.h> 101 102 #include <uvm/uvm_extern.h> 103 104 #include <compat/sunos/sunos_syscall.h> 105 #include <compat/sunos/sunos_exec.h> 106 107 void sunos_syscall_intern(struct proc *); 108 static void sunos_syscall_plain(register_t, struct proc *, struct frame *); 109 static void sunos_syscall_fancy(register_t, struct proc *, struct frame *); 110 111 void 112 sunos_syscall_intern(struct proc *p) 113 { 114 115 #ifdef KTRACE 116 if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) 117 p->p_md.md_syscall = sunos_syscall_fancy; 118 else 119 #endif 120 #ifdef SYSTRACE 121 if (ISSET(p->p_flag, P_SYSTRACE)) 122 p->p_md.md_syscall = sunos_syscall_fancy; 123 else 124 #endif 125 p->p_md.md_syscall = sunos_syscall_plain; 126 } 127 128 static void 129 sunos_syscall_plain(register_t code, struct proc *p, struct frame *frame) 130 { 131 caddr_t params; 132 const struct sysent *callp; 133 int error, nsys; 134 size_t argsize; 135 register_t args[16], rval[2]; 136 137 nsys = p->p_emul->e_nsysent; 138 callp = p->p_emul->e_sysent; 139 140 /* 141 * SunOS passes the syscall-number on the stack, whereas 142 * BSD passes it in D0. So, we have to get the real "code" 143 * from the stack, and clean up the stack, as SunOS glue 144 * code assumes the kernel pops the syscall argument the 145 * glue pushed on the stack. Sigh... 146 */ 147 code = fuword((caddr_t)frame->f_regs[SP]); 148 149 /* 150 * XXX 151 * Don't do this for sunos_sigreturn, as there's no stored pc 152 * on the stack to skip, the argument follows the syscall 153 * number without a gap. 154 */ 155 if (code != SUNOS_SYS_sigreturn) { 156 frame->f_regs[SP] += sizeof (int); 157 /* 158 * remember that we adjusted the SP, 159 * might have to undo this if the system call 160 * returns ERESTART. 161 */ 162 p->p_md.md_flags |= MDP_STACKADJ; 163 } else 164 p->p_md.md_flags &= ~MDP_STACKADJ; 165 166 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 167 168 switch (code) { 169 case SUNOS_SYS_syscall: 170 /* 171 * Code is first argument, followed by actual args. 172 */ 173 code = fuword(params); 174 params += sizeof(int); 175 break; 176 default: 177 break; 178 } 179 180 if (code < 0 || code >= nsys) 181 callp += p->p_emul->e_nosys; /* illegal */ 182 else 183 callp += code; 184 185 argsize = callp->sy_argsize; 186 if (argsize) { 187 error = copyin(params, (caddr_t)args, argsize); 188 if (error) 189 goto bad; 190 } 191 192 #ifdef SYSCALL_DEBUG 193 scdebug_call(p, code, args); 194 #endif 195 196 rval[0] = 0; 197 rval[1] = frame->f_regs[D1]; 198 error = (*callp->sy_call)(p, args, rval); 199 200 switch (error) { 201 case 0: 202 /* 203 * Reinitialize proc pointer `p' as it may be different 204 * if this is a child returning from fork syscall. 205 */ 206 p = curproc; 207 frame->f_regs[D0] = rval[0]; 208 frame->f_regs[D1] = rval[1]; 209 frame->f_sr &= ~PSL_C; /* carry bit */ 210 break; 211 case ERESTART: 212 /* 213 * We always enter through a `trap' instruction, which is 2 214 * bytes, so adjust the pc by that amount. 215 */ 216 frame->f_pc = frame->f_pc - 2; 217 break; 218 case EJUSTRETURN: 219 /* nothing to do */ 220 break; 221 default: 222 bad: 223 frame->f_regs[D0] = error; 224 frame->f_sr |= PSL_C; /* carry bit */ 225 break; 226 } 227 228 /* need new p-value for this */ 229 if (p->p_md.md_flags & MDP_STACKADJ) { 230 p->p_md.md_flags &= ~MDP_STACKADJ; 231 if (error == ERESTART) 232 frame->f_regs[SP] -= sizeof (int); 233 } 234 235 #ifdef SYSCALL_DEBUG 236 scdebug_ret(p, code, error, rval) 237 #endif 238 } 239 240 static void 241 sunos_syscall_fancy(register_t code, struct proc *p, struct frame *frame) 242 { 243 caddr_t params; 244 const struct sysent *callp; 245 int error, nsys; 246 size_t argsize; 247 register_t args[16], rval[2]; 248 249 nsys = p->p_emul->e_nsysent; 250 callp = p->p_emul->e_sysent; 251 252 /* 253 * SunOS passes the syscall-number on the stack, whereas 254 * BSD passes it in D0. So, we have to get the real "code" 255 * from the stack, and clean up the stack, as SunOS glue 256 * code assumes the kernel pops the syscall argument the 257 * glue pushed on the stack. Sigh... 258 */ 259 code = fuword((caddr_t)frame->f_regs[SP]); 260 261 /* 262 * XXX 263 * Don't do this for sunos_sigreturn, as there's no stored pc 264 * on the stack to skip, the argument follows the syscall 265 * number without a gap. 266 */ 267 if (code != SUNOS_SYS_sigreturn) { 268 frame->f_regs[SP] += sizeof (int); 269 /* 270 * remember that we adjusted the SP, 271 * might have to undo this if the system call 272 * returns ERESTART. 273 */ 274 p->p_md.md_flags |= MDP_STACKADJ; 275 } else 276 p->p_md.md_flags &= ~MDP_STACKADJ; 277 278 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 279 280 switch (code) { 281 case SUNOS_SYS_syscall: 282 /* 283 * Code is first argument, followed by actual args. 284 */ 285 code = fuword(params); 286 params += sizeof(int); 287 break; 288 default: 289 break; 290 } 291 292 if (code < 0 || code >= nsys) 293 callp += p->p_emul->e_nosys; /* illegal */ 294 else 295 callp += code; 296 297 argsize = callp->sy_argsize; 298 if (argsize) { 299 error = copyin(params, (caddr_t)args, argsize); 300 if (error) 301 goto bad; 302 } 303 304 if ((error = trace_enter(p, code, code, args, rval)) != 0) 305 goto bad; 306 307 rval[0] = 0; 308 rval[1] = frame->f_regs[D1]; 309 error = (*callp->sy_call)(p, args, rval); 310 311 switch (error) { 312 case 0: 313 /* 314 * Reinitialize proc pointer `p' as it may be different 315 * if this is a child returning from fork syscall. 316 */ 317 p = curproc; 318 frame->f_regs[D0] = rval[0]; 319 frame->f_regs[D1] = rval[1]; 320 frame->f_sr &= ~PSL_C; /* carry bit */ 321 break; 322 case ERESTART: 323 /* 324 * We always enter through a `trap' instruction, which is 2 325 * bytes, so adjust the pc by that amount. 326 */ 327 frame->f_pc = frame->f_pc - 2; 328 break; 329 case EJUSTRETURN: 330 /* nothing to do */ 331 break; 332 default: 333 bad: 334 frame->f_regs[D0] = error; 335 frame->f_sr |= PSL_C; /* carry bit */ 336 break; 337 } 338 339 /* need new p-value for this */ 340 if (p->p_md.md_flags & MDP_STACKADJ) { 341 p->p_md.md_flags &= ~MDP_STACKADJ; 342 if (error == ERESTART) 343 frame->f_regs[SP] -= sizeof (int); 344 } 345 346 trace_exit(p, code, args, rval, error); 347 } 348