1*be8b2353Sthorpej /* $NetBSD: linux_syscall.c,v 1.18 2006/03/07 03:32:04 thorpej Exp $ */ 23c073877Smycroft 33c073877Smycroft /*- 43c073877Smycroft * Copyright (c) 2000 The NetBSD Foundation, Inc. 53c073877Smycroft * All rights reserved. 63c073877Smycroft * 73c073877Smycroft * This code is derived from software contributed to The NetBSD Foundation 83c073877Smycroft * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 93c073877Smycroft * NASA Ames Research Center, and by Charles M. Hannum. 103c073877Smycroft * 113c073877Smycroft * Redistribution and use in source and binary forms, with or without 123c073877Smycroft * modification, are permitted provided that the following conditions 133c073877Smycroft * are met: 143c073877Smycroft * 1. Redistributions of source code must retain the above copyright 153c073877Smycroft * notice, this list of conditions and the following disclaimer. 163c073877Smycroft * 2. Redistributions in binary form must reproduce the above copyright 173c073877Smycroft * notice, this list of conditions and the following disclaimer in the 183c073877Smycroft * documentation and/or other materials provided with the distribution. 193c073877Smycroft * 3. All advertising materials mentioning features or use of this software 203c073877Smycroft * must display the following acknowledgement: 213c073877Smycroft * This product includes software developed by the NetBSD 223c073877Smycroft * Foundation, Inc. and its contributors. 233c073877Smycroft * 4. Neither the name of The NetBSD Foundation nor the names of its 243c073877Smycroft * contributors may be used to endorse or promote products derived 253c073877Smycroft * from this software without specific prior written permission. 263c073877Smycroft * 273c073877Smycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 283c073877Smycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 293c073877Smycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 303c073877Smycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 313c073877Smycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 323c073877Smycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 333c073877Smycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 343c073877Smycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 353c073877Smycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 363c073877Smycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 373c073877Smycroft * POSSIBILITY OF SUCH DAMAGE. 383c073877Smycroft */ 393c073877Smycroft 403c073877Smycroft /* 413c073877Smycroft * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. 423c073877Smycroft * 433c073877Smycroft * Redistribution and use in source and binary forms, with or without 443c073877Smycroft * modification, are permitted provided that the following conditions 453c073877Smycroft * are met: 463c073877Smycroft * 1. Redistributions of source code must retain the above copyright 473c073877Smycroft * notice, this list of conditions and the following disclaimer. 483c073877Smycroft * 2. Redistributions in binary form must reproduce the above copyright 493c073877Smycroft * notice, this list of conditions and the following disclaimer in the 503c073877Smycroft * documentation and/or other materials provided with the distribution. 513c073877Smycroft * 3. All advertising materials mentioning features or use of this software 523c073877Smycroft * must display the following acknowledgement: 533c073877Smycroft * This product includes software developed by Christopher G. Demetriou 543c073877Smycroft * for the NetBSD Project. 553c073877Smycroft * 4. The name of the author may not be used to endorse or promote products 563c073877Smycroft * derived from this software without specific prior written permission 573c073877Smycroft * 583c073877Smycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 593c073877Smycroft * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 603c073877Smycroft * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 613c073877Smycroft * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 623c073877Smycroft * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 633c073877Smycroft * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 643c073877Smycroft * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 653c073877Smycroft * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 663c073877Smycroft * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 673c073877Smycroft * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 683c073877Smycroft */ 693c073877Smycroft 703c073877Smycroft /* 713c073877Smycroft * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 723c073877Smycroft * All rights reserved. 733c073877Smycroft * 743c073877Smycroft * Author: Chris G. Demetriou 753c073877Smycroft * 763c073877Smycroft * Permission to use, copy, modify and distribute this software and 773c073877Smycroft * its documentation is hereby granted, provided that both the copyright 783c073877Smycroft * notice and this permission notice appear in all copies of the 793c073877Smycroft * software, derivative works or modified versions, and any portions 803c073877Smycroft * thereof, and that both notices appear in supporting documentation. 813c073877Smycroft * 823c073877Smycroft * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 833c073877Smycroft * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 843c073877Smycroft * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 853c073877Smycroft * 863c073877Smycroft * Carnegie Mellon requests users of this software to return to 873c073877Smycroft * 883c073877Smycroft * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 893c073877Smycroft * School of Computer Science 903c073877Smycroft * Carnegie Mellon University 913c073877Smycroft * Pittsburgh PA 15213-3890 923c073877Smycroft * 933c073877Smycroft * any improvements or extensions that they make and grant Carnegie the 943c073877Smycroft * rights to redistribute these changes. 953c073877Smycroft */ 963c073877Smycroft 9767afbd62Smrg #if defined(_KERNEL_OPT) 983c073877Smycroft #include "opt_syscall_debug.h" 99c0d0ffefSmycroft #endif 1003c073877Smycroft 1013c073877Smycroft #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 1023c073877Smycroft 103*be8b2353Sthorpej __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.18 2006/03/07 03:32:04 thorpej Exp $"); 1043c073877Smycroft 1053c073877Smycroft #include <sys/param.h> 1063c073877Smycroft #include <sys/systm.h> 1073c073877Smycroft #include <sys/proc.h> 10823bc2503Sthorpej #include <sys/sa.h> 10923bc2503Sthorpej #include <sys/savar.h> 1103c073877Smycroft #include <sys/user.h> 1113c073877Smycroft #include <sys/signal.h> 1123c073877Smycroft #include <sys/syscall.h> 1133c073877Smycroft 1143c073877Smycroft #include <uvm/uvm_extern.h> 1153c073877Smycroft 1163c073877Smycroft #include <machine/cpu.h> 1173c073877Smycroft #include <machine/reg.h> 1183c073877Smycroft #include <machine/alpha.h> 11933338b63Sthorpej #include <machine/userret.h> 1203c073877Smycroft 12133d5c07cSmycroft #include <compat/linux/common/linux_types.h> 12233d5c07cSmycroft #include <compat/linux/common/linux_errno.h> 1233c073877Smycroft #include <compat/linux/linux_syscall.h> 12433d5c07cSmycroft #include <compat/linux/common/linux_signal.h> 12533d5c07cSmycroft #include <compat/linux/common/linux_siginfo.h> 1263c073877Smycroft #include <compat/linux/arch/alpha/linux_machdep.h> 1273c073877Smycroft 12833338b63Sthorpej void linux_syscall_intern(struct proc *); 12923bc2503Sthorpej void linux_syscall_plain(struct lwp *, u_int64_t, struct trapframe *); 13023bc2503Sthorpej void linux_syscall_fancy(struct lwp *, u_int64_t, struct trapframe *); 1313c073877Smycroft 1323c073877Smycroft void 13333338b63Sthorpej linux_syscall_intern(struct proc *p) 1343c073877Smycroft { 135*be8b2353Sthorpej 136*be8b2353Sthorpej if (trace_is_enabled(p)) 137a4495f4cSchristos p->p_md.md_syscall = linux_syscall_fancy; 138a4495f4cSchristos else 139ae0f07ddSthorpej p->p_md.md_syscall = linux_syscall_plain; 1403c073877Smycroft } 1413c073877Smycroft 1423c073877Smycroft /* 1433c073877Smycroft * Process a system call. 1443c073877Smycroft * 1453c073877Smycroft * System calls are strange beasts. They are passed the syscall number 1463c073877Smycroft * in v0, and the arguments in the registers (as normal). They return 1473c073877Smycroft * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 1483c073877Smycroft * and the return value (if any) in v0. 1493c073877Smycroft * 1503c073877Smycroft * The assembly stub takes care of moving the call number into a register 1513c073877Smycroft * we can get to, and moves all of the argument registers into their places 1523c073877Smycroft * in the trap frame. On return, it restores the callee-saved registers, 1533c073877Smycroft * a3, and v0 from the frame before returning to the user process. 1543c073877Smycroft */ 1553c073877Smycroft void 15623bc2503Sthorpej linux_syscall_plain(struct lwp *l, u_int64_t code, struct trapframe *framep) 1573c073877Smycroft { 1583c073877Smycroft const struct sysent *callp; 1593c073877Smycroft int error; 1603c073877Smycroft u_int64_t rval[2]; 1613c073877Smycroft u_int64_t *args, copyargs[10]; /* XXX */ 1623c073877Smycroft u_int hidden, nargs; 16323bc2503Sthorpej struct proc *p = l->l_proc; 1643c073877Smycroft 16523bc2503Sthorpej KERNEL_PROC_LOCK(l); 1663c073877Smycroft 1673c073877Smycroft uvmexp.syscalls++; 16823bc2503Sthorpej l->l_md.md_tf = framep; 1693c073877Smycroft 1703c073877Smycroft callp = p->p_emul->e_sysent; 1713c073877Smycroft 1723c073877Smycroft switch (code) { 1733c073877Smycroft case LINUX_SYS_syscall: 1743c073877Smycroft /* OSF/1 syscall() */ 1753c073877Smycroft code = framep->tf_regs[FRAME_A0]; 1763c073877Smycroft hidden = 1; 1773c073877Smycroft break; 1783c073877Smycroft default: 1793c073877Smycroft hidden = 0; 1803c073877Smycroft break; 1813c073877Smycroft } 1823c073877Smycroft 1833c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 1843c073877Smycroft callp += code; 1853c073877Smycroft 1863c073877Smycroft nargs = callp->sy_narg + hidden; 1873c073877Smycroft switch (nargs) { 1883c073877Smycroft default: 1893c073877Smycroft error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 1903c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 1913c073877Smycroft if (error) 1923c073877Smycroft goto bad; 1933c073877Smycroft case 6: 1943c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 1953c073877Smycroft case 5: 1963c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 1973c073877Smycroft case 4: 1983c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 1993c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 2003c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 2013c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 2023c073877Smycroft args = copyargs; 2033c073877Smycroft break; 2043c073877Smycroft case 3: 2053c073877Smycroft case 2: 2063c073877Smycroft case 1: 2073c073877Smycroft case 0: 2083c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 2093c073877Smycroft break; 2103c073877Smycroft } 2113c073877Smycroft args += hidden; 2123c073877Smycroft 2133c073877Smycroft #ifdef SYSCALL_DEBUG 21423bc2503Sthorpej scdebug_call(l, code, args); 2153c073877Smycroft #endif 2163c073877Smycroft 2173c073877Smycroft rval[0] = 0; 2183c073877Smycroft rval[1] = 0; 21923bc2503Sthorpej error = (*callp->sy_call)(l, args, rval); 2203c073877Smycroft 2213c073877Smycroft switch (error) { 2223c073877Smycroft case 0: 2233c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 2243c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 2253c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 2263c073877Smycroft break; 2273c073877Smycroft case ERESTART: 2283c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 2293c073877Smycroft break; 2303c073877Smycroft case EJUSTRETURN: 2313c073877Smycroft break; 2323c073877Smycroft default: 2333c073877Smycroft bad: 23433d5c07cSmycroft error = native_to_linux_errno[error]; 2353c073877Smycroft framep->tf_regs[FRAME_V0] = error; 2363c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 2373c073877Smycroft break; 2383c073877Smycroft } 2393c073877Smycroft 2403c073877Smycroft #ifdef SYSCALL_DEBUG 24123bc2503Sthorpej scdebug_ret(l, code, error, rval); 2423c073877Smycroft #endif 24323bc2503Sthorpej KERNEL_PROC_UNLOCK(l); 24423bc2503Sthorpej userret(l); 2453c073877Smycroft } 2463c073877Smycroft 2473c073877Smycroft void 24823bc2503Sthorpej linux_syscall_fancy(struct lwp *l, u_int64_t code, struct trapframe *framep) 2493c073877Smycroft { 2503c073877Smycroft const struct sysent *callp; 2513c073877Smycroft int error; 2523c073877Smycroft u_int64_t rval[2]; 25301ffeba8Smycroft u_int64_t *args, copyargs[10]; 2543c073877Smycroft u_int hidden, nargs; 25523bc2503Sthorpej struct proc *p = l->l_proc; 2563c073877Smycroft 25723bc2503Sthorpej KERNEL_PROC_LOCK(l); 2583c073877Smycroft 2593c073877Smycroft uvmexp.syscalls++; 26023bc2503Sthorpej l->l_md.md_tf = framep; 2613c073877Smycroft 2623c073877Smycroft callp = p->p_emul->e_sysent; 2633c073877Smycroft 2643c073877Smycroft switch (code) { 2653c073877Smycroft case LINUX_SYS_syscall: 2663c073877Smycroft /* OSF/1 syscall() */ 2673c073877Smycroft code = framep->tf_regs[FRAME_A0]; 2683c073877Smycroft hidden = 1; 2693c073877Smycroft break; 2703c073877Smycroft default: 2713c073877Smycroft hidden = 0; 2723c073877Smycroft break; 2733c073877Smycroft } 2743c073877Smycroft 2753c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 2763c073877Smycroft callp += code; 2773c073877Smycroft 2783c073877Smycroft nargs = callp->sy_narg + hidden; 2793c073877Smycroft switch (nargs) { 2803c073877Smycroft default: 2813c073877Smycroft error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 2823c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 28301ffeba8Smycroft if (error) { 28401ffeba8Smycroft args = copyargs; 2853c073877Smycroft goto bad; 28601ffeba8Smycroft } 2873c073877Smycroft case 6: 2883c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 2893c073877Smycroft case 5: 2903c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 2913c073877Smycroft case 4: 2923c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 2933c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 2943c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 2953c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 2963c073877Smycroft args = copyargs; 2973c073877Smycroft break; 2983c073877Smycroft case 3: 2993c073877Smycroft case 2: 3003c073877Smycroft case 1: 3013c073877Smycroft case 0: 3023c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 3033c073877Smycroft break; 3043c073877Smycroft } 3053c073877Smycroft args += hidden; 3063c073877Smycroft 3073b50728cSchristos 3086d85c5e0Ssimonb if ((error = trace_enter(l, code, code, NULL, args)) != 0) 3096d30dceeSchristos goto out; 3103c073877Smycroft 3113c073877Smycroft rval[0] = 0; 3123c073877Smycroft rval[1] = 0; 31323bc2503Sthorpej error = (*callp->sy_call)(l, args, rval); 3146d30dceeSchristos out: 3153c073877Smycroft switch (error) { 3163c073877Smycroft case 0: 3173c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 3183c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 3193c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 3203c073877Smycroft break; 3213c073877Smycroft case ERESTART: 3223c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 3233c073877Smycroft break; 3243c073877Smycroft case EJUSTRETURN: 3253c073877Smycroft break; 3263c073877Smycroft default: 3273c073877Smycroft bad: 32833d5c07cSmycroft error = native_to_linux_errno[error]; 3293c073877Smycroft framep->tf_regs[FRAME_V0] = error; 3303c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 3313c073877Smycroft break; 3323c073877Smycroft } 3333c073877Smycroft 33423bc2503Sthorpej KERNEL_PROC_UNLOCK(l); 3353b50728cSchristos 33623bc2503Sthorpej trace_exit(l, code, args, rval, error); 3373b50728cSchristos 33823bc2503Sthorpej userret(l); 3393c073877Smycroft } 340