sunos_syscall.c revision 1.4
1/* $NetBSD: sunos_syscall.c,v 1.4 2003/01/17 23:18:29 thorpej 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 107void sunos_syscall_intern(struct proc *); 108static void sunos_syscall_plain(register_t, struct lwp *, struct frame *); 109static void sunos_syscall_fancy(register_t, struct lwp *, struct frame *); 110 111void 112sunos_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 128static void 129sunos_syscall_plain(register_t code, struct lwp *l, struct frame *frame) 130{ 131 struct proc *p = l->l_proc; 132 caddr_t params; 133 const struct sysent *callp; 134 int error, nsys; 135 size_t argsize; 136 register_t args[16], rval[2]; 137 138 nsys = p->p_emul->e_nsysent; 139 callp = p->p_emul->e_sysent; 140 141 /* 142 * SunOS passes the syscall-number on the stack, whereas 143 * BSD passes it in D0. So, we have to get the real "code" 144 * from the stack, and clean up the stack, as SunOS glue 145 * code assumes the kernel pops the syscall argument the 146 * glue pushed on the stack. Sigh... 147 */ 148 code = fuword((caddr_t)frame->f_regs[SP]); 149 150 /* 151 * XXX 152 * Don't do this for sunos_sigreturn, as there's no stored pc 153 * on the stack to skip, the argument follows the syscall 154 * number without a gap. 155 */ 156 if (code != SUNOS_SYS_sigreturn) { 157 frame->f_regs[SP] += sizeof (int); 158 /* 159 * remember that we adjusted the SP, 160 * might have to undo this if the system call 161 * returns ERESTART. 162 */ 163 l->l_md.md_flags |= MDL_STACKADJ; 164 } else 165 l->l_md.md_flags &= ~MDL_STACKADJ; 166 167 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 168 169 switch (code) { 170 case SUNOS_SYS_syscall: 171 /* 172 * Code is first argument, followed by actual args. 173 */ 174 code = fuword(params); 175 params += sizeof(int); 176 break; 177 default: 178 break; 179 } 180 181 if (code < 0 || code >= nsys) 182 callp += p->p_emul->e_nosys; /* illegal */ 183 else 184 callp += code; 185 186 argsize = callp->sy_argsize; 187 if (argsize) { 188 error = copyin(params, (caddr_t)args, argsize); 189 if (error) 190 goto bad; 191 } 192 193#ifdef SYSCALL_DEBUG 194 scdebug_call(l, code, args); 195#endif 196 197 rval[0] = 0; 198 rval[1] = frame->f_regs[D1]; 199 error = (*callp->sy_call)(l, args, rval); 200 201 switch (error) { 202 case 0: 203 /* 204 * Reinitialize proc pointer `p' as it may be different 205 * if this is a child returning from fork syscall. 206 */ 207 p = curproc; 208 frame->f_regs[D0] = rval[0]; 209 frame->f_regs[D1] = rval[1]; 210 frame->f_sr &= ~PSL_C; /* carry bit */ 211 break; 212 case ERESTART: 213 /* 214 * We always enter through a `trap' instruction, which is 2 215 * bytes, so adjust the pc by that amount. 216 */ 217 frame->f_pc = frame->f_pc - 2; 218 break; 219 case EJUSTRETURN: 220 /* nothing to do */ 221 break; 222 default: 223 bad: 224 frame->f_regs[D0] = error; 225 frame->f_sr |= PSL_C; /* carry bit */ 226 break; 227 } 228 229 /* need new p-value for this */ 230 if (l->l_md.md_flags & MDL_STACKADJ) { 231 l->l_md.md_flags &= ~MDL_STACKADJ; 232 if (error == ERESTART) 233 frame->f_regs[SP] -= sizeof (int); 234 } 235 236#ifdef SYSCALL_DEBUG 237 scdebug_ret(p, code, error, rval) 238#endif 239} 240 241static void 242sunos_syscall_fancy(register_t code, struct lwp *l, struct frame *frame) 243{ 244 struct proc *p = l->l_proc; 245 caddr_t params; 246 const struct sysent *callp; 247 int error, nsys; 248 size_t argsize; 249 register_t args[16], rval[2]; 250 251 nsys = p->p_emul->e_nsysent; 252 callp = p->p_emul->e_sysent; 253 254 /* 255 * SunOS passes the syscall-number on the stack, whereas 256 * BSD passes it in D0. So, we have to get the real "code" 257 * from the stack, and clean up the stack, as SunOS glue 258 * code assumes the kernel pops the syscall argument the 259 * glue pushed on the stack. Sigh... 260 */ 261 code = fuword((caddr_t)frame->f_regs[SP]); 262 263 /* 264 * XXX 265 * Don't do this for sunos_sigreturn, as there's no stored pc 266 * on the stack to skip, the argument follows the syscall 267 * number without a gap. 268 */ 269 if (code != SUNOS_SYS_sigreturn) { 270 frame->f_regs[SP] += sizeof (int); 271 /* 272 * remember that we adjusted the SP, 273 * might have to undo this if the system call 274 * returns ERESTART. 275 */ 276 l->l_md.md_flags |= MDL_STACKADJ; 277 } else 278 l->l_md.md_flags &= ~MDL_STACKADJ; 279 280 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 281 282 switch (code) { 283 case SUNOS_SYS_syscall: 284 /* 285 * Code is first argument, followed by actual args. 286 */ 287 code = fuword(params); 288 params += sizeof(int); 289 break; 290 default: 291 break; 292 } 293 294 if (code < 0 || code >= nsys) 295 callp += p->p_emul->e_nosys; /* illegal */ 296 else 297 callp += code; 298 299 argsize = callp->sy_argsize; 300 if (argsize) { 301 error = copyin(params, (caddr_t)args, argsize); 302 if (error) 303 goto bad; 304 } 305 306 if ((error = trace_enter(l, code, code, NULL, args, rval)) != 0) 307 goto bad; 308 309 rval[0] = 0; 310 rval[1] = frame->f_regs[D1]; 311 error = (*callp->sy_call)(l, args, rval); 312 313 switch (error) { 314 case 0: 315 /* 316 * Reinitialize proc pointer `p' as it may be different 317 * if this is a child returning from fork syscall. 318 */ 319 p = curproc; 320 frame->f_regs[D0] = rval[0]; 321 frame->f_regs[D1] = rval[1]; 322 frame->f_sr &= ~PSL_C; /* carry bit */ 323 break; 324 case ERESTART: 325 /* 326 * We always enter through a `trap' instruction, which is 2 327 * bytes, so adjust the pc by that amount. 328 */ 329 frame->f_pc = frame->f_pc - 2; 330 break; 331 case EJUSTRETURN: 332 /* nothing to do */ 333 break; 334 default: 335 bad: 336 frame->f_regs[D0] = error; 337 frame->f_sr |= PSL_C; /* carry bit */ 338 break; 339 } 340 341 /* need new p-value for this */ 342 if (l->l_md.md_flags & MDL_STACKADJ) { 343 l->l_md.md_flags &= ~MDL_STACKADJ; 344 if (error == ERESTART) 345 frame->f_regs[SP] -= sizeof (int); 346 } 347 348 trace_exit(l, code, args, rval, error); 349} 350