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