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