/* $OpenBSD: syscall.c,v 1.10 2008/06/26 05:42:09 ray Exp $ */ /* $NetBSD: syscall.c,v 1.24 2003/11/14 19:03:17 scw Exp $ */ /*- * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1994-1998 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. * * This code is derived from software written for Brini by Mark Brinicombe * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Mark Brinicombe * for the NetBSD Project. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * syscall entry handling * * Created : 09/11/94 */ #include #include #include #include #include #include #include #include #include #ifdef KTRACE #include #endif #include #include #include #include #include #ifdef acorn26 #include #endif #define MAXARGS 8 void swi_handler(trapframe_t *frame) { struct proc *p = curproc; const struct sysent *callp; int code, error, orig_error; u_int nap = 4, nargs; register_t *ap, *args, copyargs[MAXARGS], rval[2]; uvmexp.syscalls++; /* Re-enable interrupts if they were enabled previously */ if (__predict_true((frame->tf_spsr & I32_bit) == 0)) enable_interrupts(I32_bit); p->p_addr->u_pcb.pcb_tf = frame; code = frame->tf_r12; ap = &frame->tf_r0; callp = p->p_emul->e_sysent; switch (code) { case SYS_syscall: code = *ap++; nap--; break; case SYS___syscall: code = ap[_QUAD_LOWWORD]; ap += 2; nap -= 2; break; } if (code < 0 || code >= p->p_emul->e_nsysent) { callp += p->p_emul->e_nosys; } else { callp += code; } nargs = callp->sy_argsize / sizeof(register_t); if (nargs <= nap) { args = ap; error = 0; } else { KASSERT(nargs <= MAXARGS); memcpy(copyargs, ap, nap * sizeof(register_t)); error = copyin((void *)frame->tf_usr_sp, copyargs + nap, (nargs - nap) * sizeof(register_t)); args = copyargs; } orig_error = error; #ifdef SYSCALL_DEBUG scdebug_call(p, code, args); #endif #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p, code, callp->sy_argsize, args); #endif if (error) goto bad; rval[0] = 0; rval[1] = frame->tf_r1; orig_error = error = (*callp->sy_call)(p, args, rval); switch (error) { case 0: frame->tf_r0 = rval[0]; frame->tf_r1 = rval[1]; frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ break; case ERESTART: /* * Reconstruct the pc to point at the swi. */ frame->tf_pc -= INSN_SIZE; break; case EJUSTRETURN: /* nothing to do */ break; default: bad: frame->tf_r0 = error; frame->tf_spsr |= PSR_C_bit; /* carry bit */ break; } #ifdef SYSCALL_DEBUG scdebug_ret(p, code, orig_error, rval); #endif userret(p); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p, code, orig_error, rval[0]); #endif } void child_return(arg) void *arg; { struct proc *p = arg; struct trapframe *frame = p->p_addr->u_pcb.pcb_tf; frame->tf_r0 = 0; frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ userret(p); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) { ktrsysret(p, (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0); } #endif }