1*2890a59cSchristos /* $NetBSD: linux_syscall.c,v 1.33 2015/03/07 18:51:44 christos 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*2890a59cSchristos __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.33 2015/03/07 18:51:44 christos 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 *);
114b627dca8Smatt void linux_syscall_plain(struct lwp *, uint64_t, struct trapframe *);
115b627dca8Smatt void linux_syscall_fancy(struct lwp *, uint64_t, struct trapframe *);
1163c073877Smycroft
1173c073877Smycroft void
linux_syscall_intern(struct proc * p)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
linux_syscall_plain(struct lwp * l,uint64_t code,struct trapframe * framep)141b627dca8Smatt linux_syscall_plain(struct lwp *l, uint64_t code, struct trapframe *framep)
1423c073877Smycroft {
1433c073877Smycroft const struct sysent *callp;
1443c073877Smycroft int error;
145b627dca8Smatt uint64_t rval[2];
146b627dca8Smatt uint64_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
152ccde4787Smatt 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],
175b627dca8Smatt (nargs - 6) * sizeof(uint64_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
linux_syscall_fancy(struct lwp * l,uint64_t code,struct trapframe * framep)225b627dca8Smatt linux_syscall_fancy(struct lwp *l, uint64_t code, struct trapframe *framep)
2263c073877Smycroft {
2273c073877Smycroft const struct sysent *callp;
2283c073877Smycroft int error;
229b627dca8Smatt uint64_t rval[2];
230b627dca8Smatt uint64_t *args, copyargs[10];
2313c073877Smycroft u_int hidden, nargs;
23223bc2503Sthorpej struct proc *p = l->l_proc;
2333c073877Smycroft
2342b79369cSad LWP_CACHE_CREDS(l, p);
2352b79369cSad
236ccde4787Smatt 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],
259b627dca8Smatt (nargs - 6) * sizeof(uint64_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
285*2890a59cSchristos if ((error = trace_enter(code, callp, args)) != 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
311*2890a59cSchristos trace_exit(code, callp, args, rval, error);
3123b50728cSchristos
31323bc2503Sthorpej userret(l);
3143c073877Smycroft }
315