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