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