xref: /netbsd/sys/arch/alpha/alpha/linux_syscall.c (revision 2890a59c)
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(), &copyargs[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(), &copyargs[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