1*c2a8c787Sdsl /* $NetBSD: linux_syscall.c,v 1.24 2008/02/06 22:12:39 dsl 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 973c073877Smycroft #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 983c073877Smycroft 99*c2a8c787Sdsl __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.24 2008/02/06 22:12:39 dsl Exp $"); 1003c073877Smycroft 1013c073877Smycroft #include <sys/param.h> 1023c073877Smycroft #include <sys/systm.h> 1033c073877Smycroft #include <sys/proc.h> 1043c073877Smycroft #include <sys/user.h> 1053c073877Smycroft #include <sys/signal.h> 1063c073877Smycroft #include <sys/syscall.h> 1073c073877Smycroft 1083c073877Smycroft #include <uvm/uvm_extern.h> 1093c073877Smycroft 1103c073877Smycroft #include <machine/cpu.h> 1113c073877Smycroft #include <machine/reg.h> 1123c073877Smycroft #include <machine/alpha.h> 11333338b63Sthorpej #include <machine/userret.h> 1143c073877Smycroft 11533d5c07cSmycroft #include <compat/linux/common/linux_types.h> 11633d5c07cSmycroft #include <compat/linux/common/linux_errno.h> 1173c073877Smycroft #include <compat/linux/linux_syscall.h> 11833d5c07cSmycroft #include <compat/linux/common/linux_signal.h> 11933d5c07cSmycroft #include <compat/linux/common/linux_siginfo.h> 1203c073877Smycroft #include <compat/linux/arch/alpha/linux_machdep.h> 1213c073877Smycroft 12233338b63Sthorpej void linux_syscall_intern(struct proc *); 12323bc2503Sthorpej void linux_syscall_plain(struct lwp *, u_int64_t, struct trapframe *); 12423bc2503Sthorpej void linux_syscall_fancy(struct lwp *, u_int64_t, struct trapframe *); 1253c073877Smycroft 1263c073877Smycroft void 12733338b63Sthorpej linux_syscall_intern(struct proc *p) 1283c073877Smycroft { 129be8b2353Sthorpej 130be8b2353Sthorpej if (trace_is_enabled(p)) 131a4495f4cSchristos p->p_md.md_syscall = linux_syscall_fancy; 132a4495f4cSchristos else 133ae0f07ddSthorpej p->p_md.md_syscall = linux_syscall_plain; 1343c073877Smycroft } 1353c073877Smycroft 1363c073877Smycroft /* 1373c073877Smycroft * Process a system call. 1383c073877Smycroft * 1393c073877Smycroft * System calls are strange beasts. They are passed the syscall number 1403c073877Smycroft * in v0, and the arguments in the registers (as normal). They return 1413c073877Smycroft * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 1423c073877Smycroft * and the return value (if any) in v0. 1433c073877Smycroft * 1443c073877Smycroft * The assembly stub takes care of moving the call number into a register 1453c073877Smycroft * we can get to, and moves all of the argument registers into their places 1463c073877Smycroft * in the trap frame. On return, it restores the callee-saved registers, 1473c073877Smycroft * a3, and v0 from the frame before returning to the user process. 1483c073877Smycroft */ 1493c073877Smycroft void 15023bc2503Sthorpej linux_syscall_plain(struct lwp *l, u_int64_t code, struct trapframe *framep) 1513c073877Smycroft { 1523c073877Smycroft const struct sysent *callp; 1533c073877Smycroft int error; 1543c073877Smycroft u_int64_t rval[2]; 1553c073877Smycroft u_int64_t *args, copyargs[10]; /* XXX */ 1563c073877Smycroft u_int hidden, nargs; 15723bc2503Sthorpej struct proc *p = l->l_proc; 1583c073877Smycroft 1592b79369cSad LWP_CACHE_CREDS(l, p); 1602b79369cSad 161b07ec3fcSad KERNEL_LOCK(1, l); 1623c073877Smycroft 1633c073877Smycroft uvmexp.syscalls++; 16423bc2503Sthorpej l->l_md.md_tf = framep; 1653c073877Smycroft 1663c073877Smycroft callp = p->p_emul->e_sysent; 1673c073877Smycroft 1683c073877Smycroft switch (code) { 1693c073877Smycroft case LINUX_SYS_syscall: 1703c073877Smycroft /* OSF/1 syscall() */ 1713c073877Smycroft code = framep->tf_regs[FRAME_A0]; 1723c073877Smycroft hidden = 1; 1733c073877Smycroft break; 1743c073877Smycroft default: 1753c073877Smycroft hidden = 0; 1763c073877Smycroft break; 1773c073877Smycroft } 1783c073877Smycroft 1793c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 1803c073877Smycroft callp += code; 1813c073877Smycroft 1823c073877Smycroft nargs = callp->sy_narg + hidden; 1833c073877Smycroft switch (nargs) { 1843c073877Smycroft default: 18553524e44Schristos error = copyin((void *)alpha_pal_rdusp(), ©args[6], 1863c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 1873c073877Smycroft if (error) 1883c073877Smycroft goto bad; 1893c073877Smycroft case 6: 1903c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 1913c073877Smycroft case 5: 1923c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 1933c073877Smycroft case 4: 1943c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 1953c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 1963c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 1973c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 1983c073877Smycroft args = copyargs; 1993c073877Smycroft break; 2003c073877Smycroft case 3: 2013c073877Smycroft case 2: 2023c073877Smycroft case 1: 2033c073877Smycroft case 0: 2043c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 2053c073877Smycroft break; 2063c073877Smycroft } 2073c073877Smycroft args += hidden; 2083c073877Smycroft 2093c073877Smycroft rval[0] = 0; 2103c073877Smycroft rval[1] = 0; 21123bc2503Sthorpej error = (*callp->sy_call)(l, args, rval); 2123c073877Smycroft 2133c073877Smycroft switch (error) { 2143c073877Smycroft case 0: 2153c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 2163c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 2173c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 2183c073877Smycroft break; 2193c073877Smycroft case ERESTART: 2203c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 2213c073877Smycroft break; 2223c073877Smycroft case EJUSTRETURN: 2233c073877Smycroft break; 2243c073877Smycroft default: 2253c073877Smycroft bad: 22633d5c07cSmycroft error = native_to_linux_errno[error]; 2273c073877Smycroft framep->tf_regs[FRAME_V0] = error; 2283c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 2293c073877Smycroft break; 2303c073877Smycroft } 2313c073877Smycroft 232b07ec3fcSad KERNEL_UNLOCK_LAST(l); 23323bc2503Sthorpej userret(l); 2343c073877Smycroft } 2353c073877Smycroft 2363c073877Smycroft void 23723bc2503Sthorpej linux_syscall_fancy(struct lwp *l, u_int64_t code, struct trapframe *framep) 2383c073877Smycroft { 2393c073877Smycroft const struct sysent *callp; 2403c073877Smycroft int error; 2413c073877Smycroft u_int64_t rval[2]; 24201ffeba8Smycroft u_int64_t *args, copyargs[10]; 2433c073877Smycroft u_int hidden, nargs; 24423bc2503Sthorpej struct proc *p = l->l_proc; 2453c073877Smycroft 2462b79369cSad LWP_CACHE_CREDS(l, p); 2472b79369cSad 248b07ec3fcSad KERNEL_LOCK(1, l); 2493c073877Smycroft 2503c073877Smycroft uvmexp.syscalls++; 25123bc2503Sthorpej l->l_md.md_tf = framep; 2523c073877Smycroft 2533c073877Smycroft callp = p->p_emul->e_sysent; 2543c073877Smycroft 2553c073877Smycroft switch (code) { 2563c073877Smycroft case LINUX_SYS_syscall: 2573c073877Smycroft /* OSF/1 syscall() */ 2583c073877Smycroft code = framep->tf_regs[FRAME_A0]; 2593c073877Smycroft hidden = 1; 2603c073877Smycroft break; 2613c073877Smycroft default: 2623c073877Smycroft hidden = 0; 2633c073877Smycroft break; 2643c073877Smycroft } 2653c073877Smycroft 2663c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 2673c073877Smycroft callp += code; 2683c073877Smycroft 2693c073877Smycroft nargs = callp->sy_narg + hidden; 2703c073877Smycroft switch (nargs) { 2713c073877Smycroft default: 27253524e44Schristos error = copyin((void *)alpha_pal_rdusp(), ©args[6], 2733c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 27401ffeba8Smycroft if (error) { 27501ffeba8Smycroft args = copyargs; 2763c073877Smycroft goto bad; 27701ffeba8Smycroft } 2783c073877Smycroft case 6: 2793c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 2803c073877Smycroft case 5: 2813c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 2823c073877Smycroft case 4: 2833c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 2843c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 2853c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 2863c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 2873c073877Smycroft args = copyargs; 2883c073877Smycroft break; 2893c073877Smycroft case 3: 2903c073877Smycroft case 2: 2913c073877Smycroft case 1: 2923c073877Smycroft case 0: 2933c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 2943c073877Smycroft break; 2953c073877Smycroft } 2963c073877Smycroft args += hidden; 2973c073877Smycroft 2983b50728cSchristos 299*c2a8c787Sdsl if ((error = trace_enter(code, args, callp->sy_narg)) != 0) 3006d30dceeSchristos goto out; 3013c073877Smycroft 3023c073877Smycroft rval[0] = 0; 3033c073877Smycroft rval[1] = 0; 30423bc2503Sthorpej error = (*callp->sy_call)(l, args, rval); 3056d30dceeSchristos out: 3063c073877Smycroft switch (error) { 3073c073877Smycroft case 0: 3083c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 3093c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 3103c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 3113c073877Smycroft break; 3123c073877Smycroft case ERESTART: 3133c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 3143c073877Smycroft break; 3153c073877Smycroft case EJUSTRETURN: 3163c073877Smycroft break; 3173c073877Smycroft default: 3183c073877Smycroft bad: 31933d5c07cSmycroft error = native_to_linux_errno[error]; 3203c073877Smycroft framep->tf_regs[FRAME_V0] = error; 3213c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 3223c073877Smycroft break; 3233c073877Smycroft } 3243c073877Smycroft 325b07ec3fcSad KERNEL_UNLOCK_LAST(l); 3263b50728cSchristos 327*c2a8c787Sdsl trace_exit(code, rval, error); 3283b50728cSchristos 32923bc2503Sthorpej userret(l); 3303c073877Smycroft } 331