xref: /netbsd/sys/arch/alpha/alpha/linux_syscall.c (revision be8b2353)
1*be8b2353Sthorpej /* $NetBSD: linux_syscall.c,v 1.18 2006/03/07 03:32:04 thorpej 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 
9767afbd62Smrg #if defined(_KERNEL_OPT)
983c073877Smycroft #include "opt_syscall_debug.h"
99c0d0ffefSmycroft #endif
1003c073877Smycroft 
1013c073877Smycroft #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
1023c073877Smycroft 
103*be8b2353Sthorpej __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.18 2006/03/07 03:32:04 thorpej Exp $");
1043c073877Smycroft 
1053c073877Smycroft #include <sys/param.h>
1063c073877Smycroft #include <sys/systm.h>
1073c073877Smycroft #include <sys/proc.h>
10823bc2503Sthorpej #include <sys/sa.h>
10923bc2503Sthorpej #include <sys/savar.h>
1103c073877Smycroft #include <sys/user.h>
1113c073877Smycroft #include <sys/signal.h>
1123c073877Smycroft #include <sys/syscall.h>
1133c073877Smycroft 
1143c073877Smycroft #include <uvm/uvm_extern.h>
1153c073877Smycroft 
1163c073877Smycroft #include <machine/cpu.h>
1173c073877Smycroft #include <machine/reg.h>
1183c073877Smycroft #include <machine/alpha.h>
11933338b63Sthorpej #include <machine/userret.h>
1203c073877Smycroft 
12133d5c07cSmycroft #include <compat/linux/common/linux_types.h>
12233d5c07cSmycroft #include <compat/linux/common/linux_errno.h>
1233c073877Smycroft #include <compat/linux/linux_syscall.h>
12433d5c07cSmycroft #include <compat/linux/common/linux_signal.h>
12533d5c07cSmycroft #include <compat/linux/common/linux_siginfo.h>
1263c073877Smycroft #include <compat/linux/arch/alpha/linux_machdep.h>
1273c073877Smycroft 
12833338b63Sthorpej void	linux_syscall_intern(struct proc *);
12923bc2503Sthorpej void	linux_syscall_plain(struct lwp *, u_int64_t, struct trapframe *);
13023bc2503Sthorpej void	linux_syscall_fancy(struct lwp *, u_int64_t, struct trapframe *);
1313c073877Smycroft 
1323c073877Smycroft void
13333338b63Sthorpej linux_syscall_intern(struct proc *p)
1343c073877Smycroft {
135*be8b2353Sthorpej 
136*be8b2353Sthorpej 	if (trace_is_enabled(p))
137a4495f4cSchristos 		p->p_md.md_syscall = linux_syscall_fancy;
138a4495f4cSchristos 	else
139ae0f07ddSthorpej 		p->p_md.md_syscall = linux_syscall_plain;
1403c073877Smycroft }
1413c073877Smycroft 
1423c073877Smycroft /*
1433c073877Smycroft  * Process a system call.
1443c073877Smycroft  *
1453c073877Smycroft  * System calls are strange beasts.  They are passed the syscall number
1463c073877Smycroft  * in v0, and the arguments in the registers (as normal).  They return
1473c073877Smycroft  * an error flag in a3 (if a3 != 0 on return, the syscall had an error),
1483c073877Smycroft  * and the return value (if any) in v0.
1493c073877Smycroft  *
1503c073877Smycroft  * The assembly stub takes care of moving the call number into a register
1513c073877Smycroft  * we can get to, and moves all of the argument registers into their places
1523c073877Smycroft  * in the trap frame.  On return, it restores the callee-saved registers,
1533c073877Smycroft  * a3, and v0 from the frame before returning to the user process.
1543c073877Smycroft  */
1553c073877Smycroft void
15623bc2503Sthorpej linux_syscall_plain(struct lwp *l, u_int64_t code, struct trapframe *framep)
1573c073877Smycroft {
1583c073877Smycroft 	const struct sysent *callp;
1593c073877Smycroft 	int error;
1603c073877Smycroft 	u_int64_t rval[2];
1613c073877Smycroft 	u_int64_t *args, copyargs[10];				/* XXX */
1623c073877Smycroft 	u_int hidden, nargs;
16323bc2503Sthorpej 	struct proc *p = l->l_proc;
1643c073877Smycroft 
16523bc2503Sthorpej 	KERNEL_PROC_LOCK(l);
1663c073877Smycroft 
1673c073877Smycroft 	uvmexp.syscalls++;
16823bc2503Sthorpej 	l->l_md.md_tf = framep;
1693c073877Smycroft 
1703c073877Smycroft 	callp = p->p_emul->e_sysent;
1713c073877Smycroft 
1723c073877Smycroft 	switch (code) {
1733c073877Smycroft 	case LINUX_SYS_syscall:
1743c073877Smycroft 		/* OSF/1 syscall() */
1753c073877Smycroft 		code = framep->tf_regs[FRAME_A0];
1763c073877Smycroft 		hidden = 1;
1773c073877Smycroft 		break;
1783c073877Smycroft 	default:
1793c073877Smycroft 		hidden = 0;
1803c073877Smycroft 		break;
1813c073877Smycroft 	}
1823c073877Smycroft 
1833c073877Smycroft 	code &= (LINUX_SYS_NSYSENT - 1);
1843c073877Smycroft 	callp += code;
1853c073877Smycroft 
1863c073877Smycroft 	nargs = callp->sy_narg + hidden;
1873c073877Smycroft 	switch (nargs) {
1883c073877Smycroft 	default:
1893c073877Smycroft 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
1903c073877Smycroft 		    (nargs - 6) * sizeof(u_int64_t));
1913c073877Smycroft 		if (error)
1923c073877Smycroft 			goto bad;
1933c073877Smycroft 	case 6:
1943c073877Smycroft 		copyargs[5] = framep->tf_regs[FRAME_A5];
1953c073877Smycroft 	case 5:
1963c073877Smycroft 		copyargs[4] = framep->tf_regs[FRAME_A4];
1973c073877Smycroft 	case 4:
1983c073877Smycroft 		copyargs[3] = framep->tf_regs[FRAME_A3];
1993c073877Smycroft 		copyargs[2] = framep->tf_regs[FRAME_A2];
2003c073877Smycroft 		copyargs[1] = framep->tf_regs[FRAME_A1];
2013c073877Smycroft 		copyargs[0] = framep->tf_regs[FRAME_A0];
2023c073877Smycroft 		args = copyargs;
2033c073877Smycroft 		break;
2043c073877Smycroft 	case 3:
2053c073877Smycroft 	case 2:
2063c073877Smycroft 	case 1:
2073c073877Smycroft 	case 0:
2083c073877Smycroft 		args = &framep->tf_regs[FRAME_A0];
2093c073877Smycroft 		break;
2103c073877Smycroft 	}
2113c073877Smycroft 	args += hidden;
2123c073877Smycroft 
2133c073877Smycroft #ifdef SYSCALL_DEBUG
21423bc2503Sthorpej 	scdebug_call(l, code, args);
2153c073877Smycroft #endif
2163c073877Smycroft 
2173c073877Smycroft 	rval[0] = 0;
2183c073877Smycroft 	rval[1] = 0;
21923bc2503Sthorpej 	error = (*callp->sy_call)(l, args, rval);
2203c073877Smycroft 
2213c073877Smycroft 	switch (error) {
2223c073877Smycroft 	case 0:
2233c073877Smycroft 		framep->tf_regs[FRAME_V0] = rval[0];
2243c073877Smycroft 		framep->tf_regs[FRAME_A4] = rval[1];
2253c073877Smycroft 		framep->tf_regs[FRAME_A3] = 0;
2263c073877Smycroft 		break;
2273c073877Smycroft 	case ERESTART:
2283c073877Smycroft 		framep->tf_regs[FRAME_PC] -= 4;
2293c073877Smycroft 		break;
2303c073877Smycroft 	case EJUSTRETURN:
2313c073877Smycroft 		break;
2323c073877Smycroft 	default:
2333c073877Smycroft 	bad:
23433d5c07cSmycroft 		error = native_to_linux_errno[error];
2353c073877Smycroft 		framep->tf_regs[FRAME_V0] = error;
2363c073877Smycroft 		framep->tf_regs[FRAME_A3] = 1;
2373c073877Smycroft 		break;
2383c073877Smycroft 	}
2393c073877Smycroft 
2403c073877Smycroft #ifdef SYSCALL_DEBUG
24123bc2503Sthorpej 	scdebug_ret(l, code, error, rval);
2423c073877Smycroft #endif
24323bc2503Sthorpej 	KERNEL_PROC_UNLOCK(l);
24423bc2503Sthorpej 	userret(l);
2453c073877Smycroft }
2463c073877Smycroft 
2473c073877Smycroft void
24823bc2503Sthorpej linux_syscall_fancy(struct lwp *l, u_int64_t code, struct trapframe *framep)
2493c073877Smycroft {
2503c073877Smycroft 	const struct sysent *callp;
2513c073877Smycroft 	int error;
2523c073877Smycroft 	u_int64_t rval[2];
25301ffeba8Smycroft 	u_int64_t *args, copyargs[10];
2543c073877Smycroft 	u_int hidden, nargs;
25523bc2503Sthorpej 	struct proc *p = l->l_proc;
2563c073877Smycroft 
25723bc2503Sthorpej 	KERNEL_PROC_LOCK(l);
2583c073877Smycroft 
2593c073877Smycroft 	uvmexp.syscalls++;
26023bc2503Sthorpej 	l->l_md.md_tf = framep;
2613c073877Smycroft 
2623c073877Smycroft 	callp = p->p_emul->e_sysent;
2633c073877Smycroft 
2643c073877Smycroft 	switch (code) {
2653c073877Smycroft 	case LINUX_SYS_syscall:
2663c073877Smycroft 		/* OSF/1 syscall() */
2673c073877Smycroft 		code = framep->tf_regs[FRAME_A0];
2683c073877Smycroft 		hidden = 1;
2693c073877Smycroft 		break;
2703c073877Smycroft 	default:
2713c073877Smycroft 		hidden = 0;
2723c073877Smycroft 		break;
2733c073877Smycroft 	}
2743c073877Smycroft 
2753c073877Smycroft 	code &= (LINUX_SYS_NSYSENT - 1);
2763c073877Smycroft 	callp += code;
2773c073877Smycroft 
2783c073877Smycroft 	nargs = callp->sy_narg + hidden;
2793c073877Smycroft 	switch (nargs) {
2803c073877Smycroft 	default:
2813c073877Smycroft 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
2823c073877Smycroft 		    (nargs - 6) * sizeof(u_int64_t));
28301ffeba8Smycroft 		if (error) {
28401ffeba8Smycroft 			args = copyargs;
2853c073877Smycroft 			goto bad;
28601ffeba8Smycroft 		}
2873c073877Smycroft 	case 6:
2883c073877Smycroft 		copyargs[5] = framep->tf_regs[FRAME_A5];
2893c073877Smycroft 	case 5:
2903c073877Smycroft 		copyargs[4] = framep->tf_regs[FRAME_A4];
2913c073877Smycroft 	case 4:
2923c073877Smycroft 		copyargs[3] = framep->tf_regs[FRAME_A3];
2933c073877Smycroft 		copyargs[2] = framep->tf_regs[FRAME_A2];
2943c073877Smycroft 		copyargs[1] = framep->tf_regs[FRAME_A1];
2953c073877Smycroft 		copyargs[0] = framep->tf_regs[FRAME_A0];
2963c073877Smycroft 		args = copyargs;
2973c073877Smycroft 		break;
2983c073877Smycroft 	case 3:
2993c073877Smycroft 	case 2:
3003c073877Smycroft 	case 1:
3013c073877Smycroft 	case 0:
3023c073877Smycroft 		args = &framep->tf_regs[FRAME_A0];
3033c073877Smycroft 		break;
3043c073877Smycroft 	}
3053c073877Smycroft 	args += hidden;
3063c073877Smycroft 
3073b50728cSchristos 
3086d85c5e0Ssimonb 	if ((error = trace_enter(l, code, code, NULL, args)) != 0)
3096d30dceeSchristos 		goto out;
3103c073877Smycroft 
3113c073877Smycroft 	rval[0] = 0;
3123c073877Smycroft 	rval[1] = 0;
31323bc2503Sthorpej 	error = (*callp->sy_call)(l, args, rval);
3146d30dceeSchristos out:
3153c073877Smycroft 	switch (error) {
3163c073877Smycroft 	case 0:
3173c073877Smycroft 		framep->tf_regs[FRAME_V0] = rval[0];
3183c073877Smycroft 		framep->tf_regs[FRAME_A4] = rval[1];
3193c073877Smycroft 		framep->tf_regs[FRAME_A3] = 0;
3203c073877Smycroft 		break;
3213c073877Smycroft 	case ERESTART:
3223c073877Smycroft 		framep->tf_regs[FRAME_PC] -= 4;
3233c073877Smycroft 		break;
3243c073877Smycroft 	case EJUSTRETURN:
3253c073877Smycroft 		break;
3263c073877Smycroft 	default:
3273c073877Smycroft 	bad:
32833d5c07cSmycroft 		error = native_to_linux_errno[error];
3293c073877Smycroft 		framep->tf_regs[FRAME_V0] = error;
3303c073877Smycroft 		framep->tf_regs[FRAME_A3] = 1;
3313c073877Smycroft 		break;
3323c073877Smycroft 	}
3333c073877Smycroft 
33423bc2503Sthorpej 	KERNEL_PROC_UNLOCK(l);
3353b50728cSchristos 
33623bc2503Sthorpej 	trace_exit(l, code, args, rval, error);
3373b50728cSchristos 
33823bc2503Sthorpej 	userret(l);
3393c073877Smycroft }
340