xref: /netbsd/sys/arch/alpha/alpha/linux_syscall.c (revision bf9ec67e)
1 /* $NetBSD: linux_syscall.c,v 1.5 2001/05/30 12:28:38 mrg 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 #endif
101 
102 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
103 
104 __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.5 2001/05/30 12:28:38 mrg Exp $");
105 
106 #include <sys/param.h>
107 #include <sys/systm.h>
108 #include <sys/proc.h>
109 #include <sys/user.h>
110 #include <sys/signal.h>
111 #ifdef KTRACE
112 #include <sys/ktrace.h>
113 #endif
114 #include <sys/syscall.h>
115 
116 #include <uvm/uvm_extern.h>
117 
118 #include <machine/cpu.h>
119 #include <machine/reg.h>
120 #include <machine/alpha.h>
121 #include <machine/userret.h>
122 
123 #include <compat/linux/common/linux_types.h>
124 #include <compat/linux/common/linux_errno.h>
125 #include <compat/linux/linux_syscall.h>
126 #include <compat/linux/common/linux_signal.h>
127 #include <compat/linux/common/linux_siginfo.h>
128 #include <compat/linux/arch/alpha/linux_machdep.h>
129 
130 void	linux_syscall_intern(struct proc *);
131 void	linux_syscall_plain(struct proc *, u_int64_t, struct trapframe *);
132 void	linux_syscall_fancy(struct proc *, u_int64_t, struct trapframe *);
133 
134 void
135 linux_syscall_intern(struct proc *p)
136 {
137 
138 #ifdef KTRACE
139 	if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET))
140 		p->p_md.md_syscall = linux_syscall_fancy;
141 	else
142 #endif
143 		p->p_md.md_syscall = linux_syscall_plain;
144 }
145 
146 /*
147  * Process a system call.
148  *
149  * System calls are strange beasts.  They are passed the syscall number
150  * in v0, and the arguments in the registers (as normal).  They return
151  * an error flag in a3 (if a3 != 0 on return, the syscall had an error),
152  * and the return value (if any) in v0.
153  *
154  * The assembly stub takes care of moving the call number into a register
155  * we can get to, and moves all of the argument registers into their places
156  * in the trap frame.  On return, it restores the callee-saved registers,
157  * a3, and v0 from the frame before returning to the user process.
158  */
159 void
160 linux_syscall_plain(struct proc *p, u_int64_t code, struct trapframe *framep)
161 {
162 	const struct sysent *callp;
163 	int error;
164 	u_int64_t rval[2];
165 	u_int64_t *args, copyargs[10];				/* XXX */
166 	u_int hidden, nargs;
167 
168 	KERNEL_PROC_LOCK(p);
169 
170 	uvmexp.syscalls++;
171 	p->p_md.md_tf = framep;
172 
173 	callp = p->p_emul->e_sysent;
174 
175 	switch (code) {
176 	case LINUX_SYS_syscall:
177 		/* OSF/1 syscall() */
178 		code = framep->tf_regs[FRAME_A0];
179 		hidden = 1;
180 		break;
181 	default:
182 		hidden = 0;
183 		break;
184 	}
185 
186 	code &= (LINUX_SYS_NSYSENT - 1);
187 	callp += code;
188 
189 	nargs = callp->sy_narg + hidden;
190 	switch (nargs) {
191 	default:
192 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
193 		    (nargs - 6) * sizeof(u_int64_t));
194 		if (error)
195 			goto bad;
196 	case 6:
197 		copyargs[5] = framep->tf_regs[FRAME_A5];
198 	case 5:
199 		copyargs[4] = framep->tf_regs[FRAME_A4];
200 	case 4:
201 		copyargs[3] = framep->tf_regs[FRAME_A3];
202 		copyargs[2] = framep->tf_regs[FRAME_A2];
203 		copyargs[1] = framep->tf_regs[FRAME_A1];
204 		copyargs[0] = framep->tf_regs[FRAME_A0];
205 		args = copyargs;
206 		break;
207 	case 3:
208 	case 2:
209 	case 1:
210 	case 0:
211 		args = &framep->tf_regs[FRAME_A0];
212 		break;
213 	}
214 	args += hidden;
215 
216 #ifdef SYSCALL_DEBUG
217 	scdebug_call(p, code, args);
218 #endif
219 
220 	rval[0] = 0;
221 	rval[1] = 0;
222 	error = (*callp->sy_call)(p, args, rval);
223 
224 	switch (error) {
225 	case 0:
226 		framep->tf_regs[FRAME_V0] = rval[0];
227 		framep->tf_regs[FRAME_A4] = rval[1];
228 		framep->tf_regs[FRAME_A3] = 0;
229 		break;
230 	case ERESTART:
231 		framep->tf_regs[FRAME_PC] -= 4;
232 		break;
233 	case EJUSTRETURN:
234 		break;
235 	default:
236 	bad:
237 		error = native_to_linux_errno[error];
238 		framep->tf_regs[FRAME_V0] = error;
239 		framep->tf_regs[FRAME_A3] = 1;
240 		break;
241 	}
242 
243 #ifdef SYSCALL_DEBUG
244 	scdebug_ret(p, code, error, rval);
245 #endif
246 	KERNEL_PROC_UNLOCK(p);
247 	userret(p);
248 }
249 
250 void
251 linux_syscall_fancy(struct proc *p, u_int64_t code, struct trapframe *framep)
252 {
253 	const struct sysent *callp;
254 	int error;
255 	u_int64_t rval[2];
256 	u_int64_t *args, copyargs[10];				/* XXX */
257 	u_int hidden, nargs;
258 
259 	KERNEL_PROC_LOCK(p);
260 
261 	uvmexp.syscalls++;
262 	p->p_md.md_tf = framep;
263 
264 	callp = p->p_emul->e_sysent;
265 
266 	switch (code) {
267 	case LINUX_SYS_syscall:
268 		/* OSF/1 syscall() */
269 		code = framep->tf_regs[FRAME_A0];
270 		hidden = 1;
271 		break;
272 	default:
273 		hidden = 0;
274 		break;
275 	}
276 
277 	code &= (LINUX_SYS_NSYSENT - 1);
278 	callp += code;
279 
280 	nargs = callp->sy_narg + hidden;
281 	switch (nargs) {
282 	default:
283 		error = copyin((caddr_t)alpha_pal_rdusp(), &copyargs[6],
284 		    (nargs - 6) * sizeof(u_int64_t));
285 		if (error)
286 			goto bad;
287 	case 6:
288 		copyargs[5] = framep->tf_regs[FRAME_A5];
289 	case 5:
290 		copyargs[4] = framep->tf_regs[FRAME_A4];
291 	case 4:
292 		copyargs[3] = framep->tf_regs[FRAME_A3];
293 		copyargs[2] = framep->tf_regs[FRAME_A2];
294 		copyargs[1] = framep->tf_regs[FRAME_A1];
295 		copyargs[0] = framep->tf_regs[FRAME_A0];
296 		args = copyargs;
297 		break;
298 	case 3:
299 	case 2:
300 	case 1:
301 	case 0:
302 		args = &framep->tf_regs[FRAME_A0];
303 		break;
304 	}
305 	args += hidden;
306 
307 #ifdef KTRACE
308 	if (KTRPOINT(p, KTR_SYSCALL))
309 		ktrsyscall(p, code, callp->sy_argsize, args);
310 #endif
311 #ifdef SYSCALL_DEBUG
312 	scdebug_call(p, code, args);
313 #endif
314 
315 	rval[0] = 0;
316 	rval[1] = 0;
317 	error = (*callp->sy_call)(p, args, rval);
318 
319 	switch (error) {
320 	case 0:
321 		framep->tf_regs[FRAME_V0] = rval[0];
322 		framep->tf_regs[FRAME_A4] = rval[1];
323 		framep->tf_regs[FRAME_A3] = 0;
324 		break;
325 	case ERESTART:
326 		framep->tf_regs[FRAME_PC] -= 4;
327 		break;
328 	case EJUSTRETURN:
329 		break;
330 	default:
331 	bad:
332 		error = native_to_linux_errno[error];
333 		framep->tf_regs[FRAME_V0] = error;
334 		framep->tf_regs[FRAME_A3] = 1;
335 		break;
336 	}
337 
338 #ifdef SYSCALL_DEBUG
339 	scdebug_ret(p, code, error, rval);
340 #endif
341 	KERNEL_PROC_UNLOCK(p);
342 	userret(p);
343 #ifdef KTRACE
344 	if (KTRPOINT(p, KTR_SYSRET)) {
345 		KERNEL_PROC_LOCK(p);
346 		ktrsysret(p, code, error, rval[0]);
347 		KERNEL_PROC_UNLOCK(p);
348 	}
349 #endif
350 }
351