xref: /netbsd/sys/arch/alpha/alpha/linux_syscall.c (revision 3c073877)
1*3c073877Smycroft /* $NetBSD: linux_syscall.c,v 1.1 2000/12/14 18:06:13 mycroft Exp $ */
2*3c073877Smycroft 
3*3c073877Smycroft /*-
4*3c073877Smycroft  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5*3c073877Smycroft  * All rights reserved.
6*3c073877Smycroft  *
7*3c073877Smycroft  * This code is derived from software contributed to The NetBSD Foundation
8*3c073877Smycroft  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9*3c073877Smycroft  * NASA Ames Research Center, and by Charles M. Hannum.
10*3c073877Smycroft  *
11*3c073877Smycroft  * Redistribution and use in source and binary forms, with or without
12*3c073877Smycroft  * modification, are permitted provided that the following conditions
13*3c073877Smycroft  * are met:
14*3c073877Smycroft  * 1. Redistributions of source code must retain the above copyright
15*3c073877Smycroft  *    notice, this list of conditions and the following disclaimer.
16*3c073877Smycroft  * 2. Redistributions in binary form must reproduce the above copyright
17*3c073877Smycroft  *    notice, this list of conditions and the following disclaimer in the
18*3c073877Smycroft  *    documentation and/or other materials provided with the distribution.
19*3c073877Smycroft  * 3. All advertising materials mentioning features or use of this software
20*3c073877Smycroft  *    must display the following acknowledgement:
21*3c073877Smycroft  *	This product includes software developed by the NetBSD
22*3c073877Smycroft  *	Foundation, Inc. and its contributors.
23*3c073877Smycroft  * 4. Neither the name of The NetBSD Foundation nor the names of its
24*3c073877Smycroft  *    contributors may be used to endorse or promote products derived
25*3c073877Smycroft  *    from this software without specific prior written permission.
26*3c073877Smycroft  *
27*3c073877Smycroft  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28*3c073877Smycroft  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29*3c073877Smycroft  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30*3c073877Smycroft  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31*3c073877Smycroft  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*3c073877Smycroft  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*3c073877Smycroft  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*3c073877Smycroft  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*3c073877Smycroft  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*3c073877Smycroft  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*3c073877Smycroft  * POSSIBILITY OF SUCH DAMAGE.
38*3c073877Smycroft  */
39*3c073877Smycroft 
40*3c073877Smycroft /*
41*3c073877Smycroft  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
42*3c073877Smycroft  *
43*3c073877Smycroft  * Redistribution and use in source and binary forms, with or without
44*3c073877Smycroft  * modification, are permitted provided that the following conditions
45*3c073877Smycroft  * are met:
46*3c073877Smycroft  * 1. Redistributions of source code must retain the above copyright
47*3c073877Smycroft  *    notice, this list of conditions and the following disclaimer.
48*3c073877Smycroft  * 2. Redistributions in binary form must reproduce the above copyright
49*3c073877Smycroft  *    notice, this list of conditions and the following disclaimer in the
50*3c073877Smycroft  *    documentation and/or other materials provided with the distribution.
51*3c073877Smycroft  * 3. All advertising materials mentioning features or use of this software
52*3c073877Smycroft  *    must display the following acknowledgement:
53*3c073877Smycroft  *      This product includes software developed by Christopher G. Demetriou
54*3c073877Smycroft  *	for the NetBSD Project.
55*3c073877Smycroft  * 4. The name of the author may not be used to endorse or promote products
56*3c073877Smycroft  *    derived from this software without specific prior written permission
57*3c073877Smycroft  *
58*3c073877Smycroft  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59*3c073877Smycroft  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60*3c073877Smycroft  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61*3c073877Smycroft  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62*3c073877Smycroft  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63*3c073877Smycroft  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64*3c073877Smycroft  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65*3c073877Smycroft  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66*3c073877Smycroft  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67*3c073877Smycroft  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68*3c073877Smycroft  */
69*3c073877Smycroft 
70*3c073877Smycroft /*
71*3c073877Smycroft  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
72*3c073877Smycroft  * All rights reserved.
73*3c073877Smycroft  *
74*3c073877Smycroft  * Author: Chris G. Demetriou
75*3c073877Smycroft  *
76*3c073877Smycroft  * Permission to use, copy, modify and distribute this software and
77*3c073877Smycroft  * its documentation is hereby granted, provided that both the copyright
78*3c073877Smycroft  * notice and this permission notice appear in all copies of the
79*3c073877Smycroft  * software, derivative works or modified versions, and any portions
80*3c073877Smycroft  * thereof, and that both notices appear in supporting documentation.
81*3c073877Smycroft  *
82*3c073877Smycroft  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
83*3c073877Smycroft  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
84*3c073877Smycroft  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
85*3c073877Smycroft  *
86*3c073877Smycroft  * Carnegie Mellon requests users of this software to return to
87*3c073877Smycroft  *
88*3c073877Smycroft  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
89*3c073877Smycroft  *  School of Computer Science
90*3c073877Smycroft  *  Carnegie Mellon University
91*3c073877Smycroft  *  Pittsburgh PA 15213-3890
92*3c073877Smycroft  *
93*3c073877Smycroft  * any improvements or extensions that they make and grant Carnegie the
94*3c073877Smycroft  * rights to redistribute these changes.
95*3c073877Smycroft  */
96*3c073877Smycroft 
97*3c073877Smycroft #include "opt_syscall_debug.h"
98*3c073877Smycroft #include "opt_ktrace.h"
99*3c073877Smycroft 
100*3c073877Smycroft #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
101*3c073877Smycroft 
102*3c073877Smycroft __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.1 2000/12/14 18:06:13 mycroft Exp $");
103*3c073877Smycroft 
104*3c073877Smycroft #include <sys/param.h>
105*3c073877Smycroft #include <sys/systm.h>
106*3c073877Smycroft #include <sys/proc.h>
107*3c073877Smycroft #include <sys/user.h>
108*3c073877Smycroft #include <sys/signal.h>
109*3c073877Smycroft #ifdef KTRACE
110*3c073877Smycroft #include <sys/ktrace.h>
111*3c073877Smycroft #endif
112*3c073877Smycroft #include <sys/syscall.h>
113*3c073877Smycroft 
114*3c073877Smycroft #include <uvm/uvm_extern.h>
115*3c073877Smycroft 
116*3c073877Smycroft #include <machine/cpu.h>
117*3c073877Smycroft #include <machine/reg.h>
118*3c073877Smycroft #include <machine/alpha.h>
119*3c073877Smycroft 
120*3c073877Smycroft #include <compat/linux/arch/alpha/linux_errno.h>
121*3c073877Smycroft #include <compat/linux/linux_syscall.h>
122*3c073877Smycroft #include <compat/linux/arch/alpha/linux_signal.h>
123*3c073877Smycroft #include <compat/linux/arch/alpha/linux_machdep.h>
124*3c073877Smycroft 
125*3c073877Smycroft void	userret __P((struct proc *));
126*3c073877Smycroft void	linux_syscall_intern __P((struct proc *));
127*3c073877Smycroft void	linux_syscall_plain __P((struct proc *, u_int64_t, struct trapframe *));
128*3c073877Smycroft void	linux_syscall_fancy __P((struct proc *, u_int64_t, struct trapframe *));
129*3c073877Smycroft 
130*3c073877Smycroft void
131*3c073877Smycroft linux_syscall_intern(p)
132*3c073877Smycroft 	struct proc *p;
133*3c073877Smycroft {
134*3c073877Smycroft 
135*3c073877Smycroft #ifdef KTRACE
136*3c073877Smycroft 	if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET))
137*3c073877Smycroft 		p->p_md.md_syscall = linux_syscall_fancy;
138*3c073877Smycroft 	else
139*3c073877Smycroft #endif
140*3c073877Smycroft 		p->p_md.md_syscall = linux_syscall_plain;
141*3c073877Smycroft }
142*3c073877Smycroft 
143*3c073877Smycroft /*
144*3c073877Smycroft  * Process a system call.
145*3c073877Smycroft  *
146*3c073877Smycroft  * System calls are strange beasts.  They are passed the syscall number
147*3c073877Smycroft  * in v0, and the arguments in the registers (as normal).  They return
148*3c073877Smycroft  * an error flag in a3 (if a3 != 0 on return, the syscall had an error),
149*3c073877Smycroft  * and the return value (if any) in v0.
150*3c073877Smycroft  *
151*3c073877Smycroft  * The assembly stub takes care of moving the call number into a register
152*3c073877Smycroft  * we can get to, and moves all of the argument registers into their places
153*3c073877Smycroft  * in the trap frame.  On return, it restores the callee-saved registers,
154*3c073877Smycroft  * a3, and v0 from the frame before returning to the user process.
155*3c073877Smycroft  */
156*3c073877Smycroft void
157*3c073877Smycroft linux_syscall_plain(p, code, framep)
158*3c073877Smycroft 	struct proc *p;
159*3c073877Smycroft 	u_int64_t code;
160*3c073877Smycroft 	struct trapframe *framep;
161*3c073877Smycroft {
162*3c073877Smycroft 	const struct sysent *callp;
163*3c073877Smycroft 	int error;
164*3c073877Smycroft 	u_int64_t rval[2];
165*3c073877Smycroft 	u_int64_t *args, copyargs[10];				/* XXX */
166*3c073877Smycroft 	u_int hidden, nargs;
167*3c073877Smycroft 
168*3c073877Smycroft 	KERNEL_PROC_LOCK(p);
169*3c073877Smycroft 
170*3c073877Smycroft 	uvmexp.syscalls++;
171*3c073877Smycroft 	p->p_md.md_tf = framep;
172*3c073877Smycroft 
173*3c073877Smycroft 	callp = p->p_emul->e_sysent;
174*3c073877Smycroft 
175*3c073877Smycroft 	switch (code) {
176*3c073877Smycroft 	case LINUX_SYS_syscall:
177*3c073877Smycroft 		/* OSF/1 syscall() */
178*3c073877Smycroft 		code = framep->tf_regs[FRAME_A0];
179*3c073877Smycroft 		hidden = 1;
180*3c073877Smycroft 		break;
181*3c073877Smycroft 	default:
182*3c073877Smycroft 		hidden = 0;
183*3c073877Smycroft 		break;
184*3c073877Smycroft 	}
185*3c073877Smycroft 
186*3c073877Smycroft 	code &= (LINUX_SYS_NSYSENT - 1);
187*3c073877Smycroft 	callp += code;
188*3c073877Smycroft 
189*3c073877Smycroft 	nargs = callp->sy_narg + hidden;
190*3c073877Smycroft 	switch (nargs) {
191*3c073877Smycroft 	default:
192*3c073877Smycroft 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
193*3c073877Smycroft 		    (nargs - 6) * sizeof(u_int64_t));
194*3c073877Smycroft 		if (error)
195*3c073877Smycroft 			goto bad;
196*3c073877Smycroft 	case 6:
197*3c073877Smycroft 		copyargs[5] = framep->tf_regs[FRAME_A5];
198*3c073877Smycroft 	case 5:
199*3c073877Smycroft 		copyargs[4] = framep->tf_regs[FRAME_A4];
200*3c073877Smycroft 	case 4:
201*3c073877Smycroft 		copyargs[3] = framep->tf_regs[FRAME_A3];
202*3c073877Smycroft 		copyargs[2] = framep->tf_regs[FRAME_A2];
203*3c073877Smycroft 		copyargs[1] = framep->tf_regs[FRAME_A1];
204*3c073877Smycroft 		copyargs[0] = framep->tf_regs[FRAME_A0];
205*3c073877Smycroft 		args = copyargs;
206*3c073877Smycroft 		break;
207*3c073877Smycroft 	case 3:
208*3c073877Smycroft 	case 2:
209*3c073877Smycroft 	case 1:
210*3c073877Smycroft 	case 0:
211*3c073877Smycroft 		args = &framep->tf_regs[FRAME_A0];
212*3c073877Smycroft 		break;
213*3c073877Smycroft 	}
214*3c073877Smycroft 	args += hidden;
215*3c073877Smycroft 
216*3c073877Smycroft #ifdef SYSCALL_DEBUG
217*3c073877Smycroft 	scdebug_call(p, code, args);
218*3c073877Smycroft #endif
219*3c073877Smycroft 
220*3c073877Smycroft 	rval[0] = 0;
221*3c073877Smycroft 	rval[1] = 0;
222*3c073877Smycroft 	error = (*callp->sy_call)(p, args, rval);
223*3c073877Smycroft 
224*3c073877Smycroft 	switch (error) {
225*3c073877Smycroft 	case 0:
226*3c073877Smycroft 		framep->tf_regs[FRAME_V0] = rval[0];
227*3c073877Smycroft 		framep->tf_regs[FRAME_A4] = rval[1];
228*3c073877Smycroft 		framep->tf_regs[FRAME_A3] = 0;
229*3c073877Smycroft 		break;
230*3c073877Smycroft 	case ERESTART:
231*3c073877Smycroft 		framep->tf_regs[FRAME_PC] -= 4;
232*3c073877Smycroft 		break;
233*3c073877Smycroft 	case EJUSTRETURN:
234*3c073877Smycroft 		break;
235*3c073877Smycroft 	default:
236*3c073877Smycroft 	bad:
237*3c073877Smycroft 		error = linux_errno_rxlist[error];
238*3c073877Smycroft 		framep->tf_regs[FRAME_V0] = error;
239*3c073877Smycroft 		framep->tf_regs[FRAME_A3] = 1;
240*3c073877Smycroft 		break;
241*3c073877Smycroft 	}
242*3c073877Smycroft 
243*3c073877Smycroft #ifdef SYSCALL_DEBUG
244*3c073877Smycroft 	scdebug_ret(p, code, error, rval);
245*3c073877Smycroft #endif
246*3c073877Smycroft 	KERNEL_PROC_UNLOCK(p);
247*3c073877Smycroft 	userret(p);
248*3c073877Smycroft }
249*3c073877Smycroft 
250*3c073877Smycroft void
251*3c073877Smycroft linux_syscall_fancy(p, code, framep)
252*3c073877Smycroft 	struct proc *p;
253*3c073877Smycroft 	u_int64_t code;
254*3c073877Smycroft 	struct trapframe *framep;
255*3c073877Smycroft {
256*3c073877Smycroft 	const struct sysent *callp;
257*3c073877Smycroft 	int error;
258*3c073877Smycroft 	u_int64_t rval[2];
259*3c073877Smycroft 	u_int64_t *args, copyargs[10];				/* XXX */
260*3c073877Smycroft 	u_int hidden, nargs;
261*3c073877Smycroft 
262*3c073877Smycroft 	KERNEL_PROC_LOCK(p);
263*3c073877Smycroft 
264*3c073877Smycroft 	uvmexp.syscalls++;
265*3c073877Smycroft 	p->p_md.md_tf = framep;
266*3c073877Smycroft 
267*3c073877Smycroft 	callp = p->p_emul->e_sysent;
268*3c073877Smycroft 
269*3c073877Smycroft 	switch (code) {
270*3c073877Smycroft 	case LINUX_SYS_syscall:
271*3c073877Smycroft 		/* OSF/1 syscall() */
272*3c073877Smycroft 		code = framep->tf_regs[FRAME_A0];
273*3c073877Smycroft 		hidden = 1;
274*3c073877Smycroft 		break;
275*3c073877Smycroft 	default:
276*3c073877Smycroft 		hidden = 0;
277*3c073877Smycroft 		break;
278*3c073877Smycroft 	}
279*3c073877Smycroft 
280*3c073877Smycroft 	code &= (LINUX_SYS_NSYSENT - 1);
281*3c073877Smycroft 	callp += code;
282*3c073877Smycroft 
283*3c073877Smycroft 	nargs = callp->sy_narg + hidden;
284*3c073877Smycroft 	switch (nargs) {
285*3c073877Smycroft 	default:
286*3c073877Smycroft 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
287*3c073877Smycroft 		    (nargs - 6) * sizeof(u_int64_t));
288*3c073877Smycroft 		if (error)
289*3c073877Smycroft 			goto bad;
290*3c073877Smycroft 	case 6:
291*3c073877Smycroft 		copyargs[5] = framep->tf_regs[FRAME_A5];
292*3c073877Smycroft 	case 5:
293*3c073877Smycroft 		copyargs[4] = framep->tf_regs[FRAME_A4];
294*3c073877Smycroft 	case 4:
295*3c073877Smycroft 		copyargs[3] = framep->tf_regs[FRAME_A3];
296*3c073877Smycroft 		copyargs[2] = framep->tf_regs[FRAME_A2];
297*3c073877Smycroft 		copyargs[1] = framep->tf_regs[FRAME_A1];
298*3c073877Smycroft 		copyargs[0] = framep->tf_regs[FRAME_A0];
299*3c073877Smycroft 		args = copyargs;
300*3c073877Smycroft 		break;
301*3c073877Smycroft 	case 3:
302*3c073877Smycroft 	case 2:
303*3c073877Smycroft 	case 1:
304*3c073877Smycroft 	case 0:
305*3c073877Smycroft 		args = &framep->tf_regs[FRAME_A0];
306*3c073877Smycroft 		break;
307*3c073877Smycroft 	}
308*3c073877Smycroft 	args += hidden;
309*3c073877Smycroft 
310*3c073877Smycroft #ifdef KTRACE
311*3c073877Smycroft 	if (KTRPOINT(p, KTR_SYSCALL))
312*3c073877Smycroft 		ktrsyscall(p, code, callp->sy_argsize, args);
313*3c073877Smycroft #endif
314*3c073877Smycroft #ifdef SYSCALL_DEBUG
315*3c073877Smycroft 	scdebug_call(p, code, args);
316*3c073877Smycroft #endif
317*3c073877Smycroft 
318*3c073877Smycroft 	rval[0] = 0;
319*3c073877Smycroft 	rval[1] = 0;
320*3c073877Smycroft 	error = (*callp->sy_call)(p, args, rval);
321*3c073877Smycroft 
322*3c073877Smycroft 	switch (error) {
323*3c073877Smycroft 	case 0:
324*3c073877Smycroft 		framep->tf_regs[FRAME_V0] = rval[0];
325*3c073877Smycroft 		framep->tf_regs[FRAME_A4] = rval[1];
326*3c073877Smycroft 		framep->tf_regs[FRAME_A3] = 0;
327*3c073877Smycroft 		break;
328*3c073877Smycroft 	case ERESTART:
329*3c073877Smycroft 		framep->tf_regs[FRAME_PC] -= 4;
330*3c073877Smycroft 		break;
331*3c073877Smycroft 	case EJUSTRETURN:
332*3c073877Smycroft 		break;
333*3c073877Smycroft 	default:
334*3c073877Smycroft 	bad:
335*3c073877Smycroft 		error = linux_errno_rxlist[error];
336*3c073877Smycroft 		framep->tf_regs[FRAME_V0] = error;
337*3c073877Smycroft 		framep->tf_regs[FRAME_A3] = 1;
338*3c073877Smycroft 		break;
339*3c073877Smycroft 	}
340*3c073877Smycroft 
341*3c073877Smycroft #ifdef SYSCALL_DEBUG
342*3c073877Smycroft 	scdebug_ret(p, code, error, rval);
343*3c073877Smycroft #endif
344*3c073877Smycroft 	KERNEL_PROC_UNLOCK(p);
345*3c073877Smycroft 	userret(p);
346*3c073877Smycroft #ifdef KTRACE
347*3c073877Smycroft 	if (KTRPOINT(p, KTR_SYSRET)) {
348*3c073877Smycroft 		KERNEL_PROC_LOCK(p);
349*3c073877Smycroft 		ktrsysret(p, code, error, rval[0]);
350*3c073877Smycroft 		KERNEL_PROC_UNLOCK(p);
351*3c073877Smycroft 	}
352*3c073877Smycroft #endif
353*3c073877Smycroft }
354