1*ccde4787Smatt /* $NetBSD: linux_syscall.c,v 1.31 2010/12/20 00:25:24 matt 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 * 203c073877Smycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 213c073877Smycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 223c073877Smycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 233c073877Smycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 243c073877Smycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 253c073877Smycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 263c073877Smycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 273c073877Smycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 283c073877Smycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 293c073877Smycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 303c073877Smycroft * POSSIBILITY OF SUCH DAMAGE. 313c073877Smycroft */ 323c073877Smycroft 333c073877Smycroft /* 343c073877Smycroft * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. 353c073877Smycroft * 363c073877Smycroft * Redistribution and use in source and binary forms, with or without 373c073877Smycroft * modification, are permitted provided that the following conditions 383c073877Smycroft * are met: 393c073877Smycroft * 1. Redistributions of source code must retain the above copyright 403c073877Smycroft * notice, this list of conditions and the following disclaimer. 413c073877Smycroft * 2. Redistributions in binary form must reproduce the above copyright 423c073877Smycroft * notice, this list of conditions and the following disclaimer in the 433c073877Smycroft * documentation and/or other materials provided with the distribution. 443c073877Smycroft * 3. All advertising materials mentioning features or use of this software 453c073877Smycroft * must display the following acknowledgement: 463c073877Smycroft * This product includes software developed by Christopher G. Demetriou 473c073877Smycroft * for the NetBSD Project. 483c073877Smycroft * 4. The name of the author may not be used to endorse or promote products 493c073877Smycroft * derived from this software without specific prior written permission 503c073877Smycroft * 513c073877Smycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 523c073877Smycroft * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 533c073877Smycroft * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 543c073877Smycroft * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 553c073877Smycroft * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 563c073877Smycroft * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 573c073877Smycroft * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 583c073877Smycroft * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 593c073877Smycroft * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 603c073877Smycroft * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 613c073877Smycroft */ 623c073877Smycroft 633c073877Smycroft /* 643c073877Smycroft * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 653c073877Smycroft * All rights reserved. 663c073877Smycroft * 673c073877Smycroft * Author: Chris G. Demetriou 683c073877Smycroft * 693c073877Smycroft * Permission to use, copy, modify and distribute this software and 703c073877Smycroft * its documentation is hereby granted, provided that both the copyright 713c073877Smycroft * notice and this permission notice appear in all copies of the 723c073877Smycroft * software, derivative works or modified versions, and any portions 733c073877Smycroft * thereof, and that both notices appear in supporting documentation. 743c073877Smycroft * 753c073877Smycroft * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 763c073877Smycroft * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 773c073877Smycroft * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 783c073877Smycroft * 793c073877Smycroft * Carnegie Mellon requests users of this software to return to 803c073877Smycroft * 813c073877Smycroft * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 823c073877Smycroft * School of Computer Science 833c073877Smycroft * Carnegie Mellon University 843c073877Smycroft * Pittsburgh PA 15213-3890 853c073877Smycroft * 863c073877Smycroft * any improvements or extensions that they make and grant Carnegie the 873c073877Smycroft * rights to redistribute these changes. 883c073877Smycroft */ 893c073877Smycroft 903c073877Smycroft #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 913c073877Smycroft 92*ccde4787Smatt __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.31 2010/12/20 00:25:24 matt Exp $"); 933c073877Smycroft 943c073877Smycroft #include <sys/param.h> 953c073877Smycroft #include <sys/systm.h> 963c073877Smycroft #include <sys/proc.h> 973c073877Smycroft #include <sys/signal.h> 983c073877Smycroft #include <sys/syscall.h> 99d1b01a37Sad #include <sys/syscallvar.h> 1003c073877Smycroft 1013c073877Smycroft #include <machine/cpu.h> 1023c073877Smycroft #include <machine/reg.h> 1033c073877Smycroft #include <machine/alpha.h> 10433338b63Sthorpej #include <machine/userret.h> 1053c073877Smycroft 10633d5c07cSmycroft #include <compat/linux/common/linux_types.h> 10733d5c07cSmycroft #include <compat/linux/common/linux_errno.h> 1083c073877Smycroft #include <compat/linux/linux_syscall.h> 10933d5c07cSmycroft #include <compat/linux/common/linux_signal.h> 11033d5c07cSmycroft #include <compat/linux/common/linux_siginfo.h> 1113c073877Smycroft #include <compat/linux/arch/alpha/linux_machdep.h> 1123c073877Smycroft 11333338b63Sthorpej void linux_syscall_intern(struct proc *); 11423bc2503Sthorpej void linux_syscall_plain(struct lwp *, u_int64_t, struct trapframe *); 11523bc2503Sthorpej void linux_syscall_fancy(struct lwp *, u_int64_t, struct trapframe *); 1163c073877Smycroft 1173c073877Smycroft void 11833338b63Sthorpej linux_syscall_intern(struct proc *p) 1193c073877Smycroft { 120be8b2353Sthorpej 121be8b2353Sthorpej if (trace_is_enabled(p)) 122a4495f4cSchristos p->p_md.md_syscall = linux_syscall_fancy; 123a4495f4cSchristos else 124ae0f07ddSthorpej p->p_md.md_syscall = linux_syscall_plain; 1253c073877Smycroft } 1263c073877Smycroft 1273c073877Smycroft /* 1283c073877Smycroft * Process a system call. 1293c073877Smycroft * 1303c073877Smycroft * System calls are strange beasts. They are passed the syscall number 1313c073877Smycroft * in v0, and the arguments in the registers (as normal). They return 1323c073877Smycroft * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 1333c073877Smycroft * and the return value (if any) in v0. 1343c073877Smycroft * 1353c073877Smycroft * The assembly stub takes care of moving the call number into a register 1363c073877Smycroft * we can get to, and moves all of the argument registers into their places 1373c073877Smycroft * in the trap frame. On return, it restores the callee-saved registers, 1383c073877Smycroft * a3, and v0 from the frame before returning to the user process. 1393c073877Smycroft */ 1403c073877Smycroft void 14123bc2503Sthorpej linux_syscall_plain(struct lwp *l, u_int64_t code, struct trapframe *framep) 1423c073877Smycroft { 1433c073877Smycroft const struct sysent *callp; 1443c073877Smycroft int error; 1453c073877Smycroft u_int64_t rval[2]; 1463c073877Smycroft u_int64_t *args, copyargs[10]; /* XXX */ 1473c073877Smycroft u_int hidden, nargs; 14823bc2503Sthorpej struct proc *p = l->l_proc; 1493c073877Smycroft 1502b79369cSad LWP_CACHE_CREDS(l, p); 1512b79369cSad 152*ccde4787Smatt curcpu()->ci_data.cpu_nsyscall++; 15323bc2503Sthorpej l->l_md.md_tf = framep; 1543c073877Smycroft 1553c073877Smycroft callp = p->p_emul->e_sysent; 1563c073877Smycroft 1573c073877Smycroft switch (code) { 1583c073877Smycroft case LINUX_SYS_syscall: 1593c073877Smycroft /* OSF/1 syscall() */ 1603c073877Smycroft code = framep->tf_regs[FRAME_A0]; 1613c073877Smycroft hidden = 1; 1623c073877Smycroft break; 1633c073877Smycroft default: 1643c073877Smycroft hidden = 0; 1653c073877Smycroft break; 1663c073877Smycroft } 1673c073877Smycroft 1683c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 1693c073877Smycroft callp += code; 1703c073877Smycroft 1713c073877Smycroft nargs = callp->sy_narg + hidden; 1723c073877Smycroft switch (nargs) { 1733c073877Smycroft default: 17453524e44Schristos error = copyin((void *)alpha_pal_rdusp(), ©args[6], 1753c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 1763c073877Smycroft if (error) 1773c073877Smycroft goto bad; 1783c073877Smycroft case 6: 1793c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 1803c073877Smycroft case 5: 1813c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 1823c073877Smycroft case 4: 1833c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 1843c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 1853c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 1863c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 1873c073877Smycroft args = copyargs; 1883c073877Smycroft break; 1893c073877Smycroft case 3: 1903c073877Smycroft case 2: 1913c073877Smycroft case 1: 1923c073877Smycroft case 0: 1933c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 1943c073877Smycroft break; 1953c073877Smycroft } 1963c073877Smycroft args += hidden; 1973c073877Smycroft 1983c073877Smycroft rval[0] = 0; 1993c073877Smycroft rval[1] = 0; 200d1b01a37Sad error = sy_call(callp, l, args, rval); 2013c073877Smycroft 2023c073877Smycroft switch (error) { 2033c073877Smycroft case 0: 2043c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 2053c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 2063c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 2073c073877Smycroft break; 2083c073877Smycroft case ERESTART: 2093c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 2103c073877Smycroft break; 2113c073877Smycroft case EJUSTRETURN: 2123c073877Smycroft break; 2133c073877Smycroft default: 2143c073877Smycroft bad: 21533d5c07cSmycroft error = native_to_linux_errno[error]; 2163c073877Smycroft framep->tf_regs[FRAME_V0] = error; 2173c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 2183c073877Smycroft break; 2193c073877Smycroft } 2203c073877Smycroft 22123bc2503Sthorpej userret(l); 2223c073877Smycroft } 2233c073877Smycroft 2243c073877Smycroft void 22523bc2503Sthorpej linux_syscall_fancy(struct lwp *l, u_int64_t code, struct trapframe *framep) 2263c073877Smycroft { 2273c073877Smycroft const struct sysent *callp; 2283c073877Smycroft int error; 2293c073877Smycroft u_int64_t rval[2]; 23001ffeba8Smycroft u_int64_t *args, copyargs[10]; 2313c073877Smycroft u_int hidden, nargs; 23223bc2503Sthorpej struct proc *p = l->l_proc; 2333c073877Smycroft 2342b79369cSad LWP_CACHE_CREDS(l, p); 2352b79369cSad 236*ccde4787Smatt curcpu()->ci_data.cpu_nsyscall++; 23723bc2503Sthorpej l->l_md.md_tf = framep; 2383c073877Smycroft 2393c073877Smycroft callp = p->p_emul->e_sysent; 2403c073877Smycroft 2413c073877Smycroft switch (code) { 2423c073877Smycroft case LINUX_SYS_syscall: 2433c073877Smycroft /* OSF/1 syscall() */ 2443c073877Smycroft code = framep->tf_regs[FRAME_A0]; 2453c073877Smycroft hidden = 1; 2463c073877Smycroft break; 2473c073877Smycroft default: 2483c073877Smycroft hidden = 0; 2493c073877Smycroft break; 2503c073877Smycroft } 2513c073877Smycroft 2523c073877Smycroft code &= (LINUX_SYS_NSYSENT - 1); 2533c073877Smycroft callp += code; 2543c073877Smycroft 2553c073877Smycroft nargs = callp->sy_narg + hidden; 2563c073877Smycroft switch (nargs) { 2573c073877Smycroft default: 25853524e44Schristos error = copyin((void *)alpha_pal_rdusp(), ©args[6], 2593c073877Smycroft (nargs - 6) * sizeof(u_int64_t)); 26001ffeba8Smycroft if (error) { 26101ffeba8Smycroft args = copyargs; 2623c073877Smycroft goto bad; 26301ffeba8Smycroft } 2643c073877Smycroft case 6: 2653c073877Smycroft copyargs[5] = framep->tf_regs[FRAME_A5]; 2663c073877Smycroft case 5: 2673c073877Smycroft copyargs[4] = framep->tf_regs[FRAME_A4]; 2683c073877Smycroft case 4: 2693c073877Smycroft copyargs[3] = framep->tf_regs[FRAME_A3]; 2703c073877Smycroft copyargs[2] = framep->tf_regs[FRAME_A2]; 2713c073877Smycroft copyargs[1] = framep->tf_regs[FRAME_A1]; 2723c073877Smycroft copyargs[0] = framep->tf_regs[FRAME_A0]; 2733c073877Smycroft args = copyargs; 2743c073877Smycroft break; 2753c073877Smycroft case 3: 2763c073877Smycroft case 2: 2773c073877Smycroft case 1: 2783c073877Smycroft case 0: 2793c073877Smycroft args = &framep->tf_regs[FRAME_A0]; 2803c073877Smycroft break; 2813c073877Smycroft } 2823c073877Smycroft args += hidden; 2833c073877Smycroft 2843b50728cSchristos 285c2a8c787Sdsl if ((error = trace_enter(code, args, callp->sy_narg)) != 0) 2866d30dceeSchristos goto out; 2873c073877Smycroft 2883c073877Smycroft rval[0] = 0; 2893c073877Smycroft rval[1] = 0; 290d1b01a37Sad error = sy_call(callp, l, args, rval); 2916d30dceeSchristos out: 2923c073877Smycroft switch (error) { 2933c073877Smycroft case 0: 2943c073877Smycroft framep->tf_regs[FRAME_V0] = rval[0]; 2953c073877Smycroft framep->tf_regs[FRAME_A4] = rval[1]; 2963c073877Smycroft framep->tf_regs[FRAME_A3] = 0; 2973c073877Smycroft break; 2983c073877Smycroft case ERESTART: 2993c073877Smycroft framep->tf_regs[FRAME_PC] -= 4; 3003c073877Smycroft break; 3013c073877Smycroft case EJUSTRETURN: 3023c073877Smycroft break; 3033c073877Smycroft default: 3043c073877Smycroft bad: 30533d5c07cSmycroft error = native_to_linux_errno[error]; 3063c073877Smycroft framep->tf_regs[FRAME_V0] = error; 3073c073877Smycroft framep->tf_regs[FRAME_A3] = 1; 3083c073877Smycroft break; 3093c073877Smycroft } 3103c073877Smycroft 311c2a8c787Sdsl trace_exit(code, rval, error); 3123b50728cSchristos 31323bc2503Sthorpej userret(l); 3143c073877Smycroft } 315