xref: /netbsd-src/sys/arch/sh3/sh3/syscall.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1 /*	$NetBSD: syscall.c,v 1.2 2005/12/11 12:19:00 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the University of Utah, and William Jolitz.
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. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)trap.c	7.4 (Berkeley) 5/13/91
36  */
37 
38 /*-
39  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
40  *
41  * This code is derived from software contributed to Berkeley by
42  * the University of Utah, and William Jolitz.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *	This product includes software developed by the University of
55  *	California, Berkeley and its contributors.
56  * 4. Neither the name of the University nor the names of its contributors
57  *    may be used to endorse or promote products derived from this software
58  *    without specific prior written permission.
59  *
60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70  * SUCH DAMAGE.
71  *
72  *	@(#)trap.c	7.4 (Berkeley) 5/13/91
73  */
74 
75 /*
76  * SH3 Trap and System call handling
77  *
78  * T.Horiuchi 1998.06.8
79  */
80 
81 #include "opt_ktrace.h"
82 #include "opt_syscall_debug.h"
83 #include "opt_systrace.h"
84 
85 #include <sys/param.h>
86 #include <sys/systm.h>
87 #include <sys/proc.h>
88 #include <sys/sa.h>
89 #include <sys/savar.h>
90 #ifdef KTRACE
91 #include <sys/ktrace.h>
92 #endif
93 #ifdef SYSTRACE
94 #include <sys/systrace.h>
95 #endif
96 #include <sys/syscall.h>
97 
98 #include <sh3/userret.h>
99 
100 #include <uvm/uvm_extern.h>
101 
102 
103 static void syscall_plain(struct lwp *, struct trapframe *);
104 #if defined(KTRACE) || defined(SYSTRACE)
105 static void syscall_fancy(struct lwp *, struct trapframe *);
106 #endif
107 
108 
109 void
110 syscall_intern(struct proc *p)
111 {
112 
113 #ifdef KTRACE
114 	if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) {
115 		p->p_md.md_syscall = syscall_fancy;
116 		return;
117 	}
118 #endif
119 #ifdef SYSTRACE
120 	if (ISSET(p->p_flag, P_SYSTRACE)) {
121 		p->p_md.md_syscall = syscall_fancy;
122 		return;
123 	}
124 #endif
125 	p->p_md.md_syscall = syscall_plain;
126 }
127 
128 
129 /*
130  * System call request from POSIX system call gate interface to kernel.
131  *	l  ... curlwp when trap occurs.
132  *	tf ... full user context.
133  */
134 static void
135 syscall_plain(struct lwp *l, struct trapframe *tf)
136 {
137 	struct proc *p = l->l_proc;
138 	caddr_t params;
139 	const struct sysent *callp;
140 	int error, opc, nsys;
141 	size_t argsize;
142 	register_t code, args[8], rval[2], ocode;
143 
144 	uvmexp.syscalls++;
145 
146 	opc = tf->tf_spc;
147 	ocode = code = tf->tf_r0;
148 
149 	nsys = p->p_emul->e_nsysent;
150 	callp = p->p_emul->e_sysent;
151 
152 	params = (caddr_t)tf->tf_r15;
153 
154 	switch (code) {
155 	case SYS_syscall:
156 		/*
157 		 * Code is first argument, followed by actual args.
158 		 */
159 	        code = tf->tf_r4;  /* fuword(params); */
160 		/* params += sizeof(int); */
161 		break;
162 	case SYS___syscall:
163 		/*
164 		 * Like syscall, but code is a quad, so as to maintain
165 		 * quad alignment for the rest of the arguments.
166 		 */
167 		if (callp != sysent)
168 			break;
169 		/* fuword(params + _QUAD_LOWWORD * sizeof(int)); */
170 #if _BYTE_ORDER == BIG_ENDIAN
171 		code = tf->tf_r5;
172 #else
173 		code = tf->tf_r4;
174 #endif
175 		/* params += sizeof(quad_t); */
176 		break;
177 	default:
178 		break;
179 	}
180 	if (code < 0 || code >= nsys)
181 		callp += p->p_emul->e_nosys;		/* illegal */
182 	else
183 		callp += code;
184 	argsize = callp->sy_argsize;
185 
186 	if (ocode == SYS_syscall) {
187 		if (argsize) {
188 			args[0] = tf->tf_r5;
189 			args[1] = tf->tf_r6;
190 			args[2] = tf->tf_r7;
191 			if (argsize > 3 * sizeof(int)) {
192 				argsize -= 3 * sizeof(int);
193 				error = copyin(params, (caddr_t)&args[3],
194 					       argsize);
195 			} else
196 				error = 0;
197 		} else
198 			error = 0;
199 	}
200 	else if (ocode == SYS___syscall) {
201 		if (argsize) {
202 			args[0] = tf->tf_r6;
203 			args[1] = tf->tf_r7;
204 			if (argsize > 2 * sizeof(int)) {
205 				argsize -= 2 * sizeof(int);
206 				error = copyin(params, (caddr_t)&args[2],
207 					       argsize);
208 			} else
209 				error = 0;
210 		} else
211 			error = 0;
212 	} else {
213 		if (argsize) {
214 			args[0] = tf->tf_r4;
215 			args[1] = tf->tf_r5;
216 			args[2] = tf->tf_r6;
217 			args[3] = tf->tf_r7;
218 			if (argsize > 4 * sizeof(int)) {
219 				argsize -= 4 * sizeof(int);
220 				error = copyin(params, (caddr_t)&args[4],
221 					       argsize);
222 			} else
223 				error = 0;
224 		} else
225 			error = 0;
226 	}
227 
228 	if (error)
229 		goto bad;
230 
231 	rval[0] = 0;
232 	rval[1] = tf->tf_r1;
233 	error = (*callp->sy_call)(l, args, rval);
234 
235 	switch (error) {
236 	case 0:
237 		tf->tf_r0 = rval[0];
238 		tf->tf_r1 = rval[1];
239 		tf->tf_ssr |= PSL_TBIT;	/* T bit */
240 
241 		break;
242 	case ERESTART:
243 		/* 2 = TRAPA instruction size */
244 		tf->tf_spc = opc - 2;
245 
246 		break;
247 	case EJUSTRETURN:
248 		/* nothing to do */
249 		break;
250 	default:
251 	bad:
252 		if (p->p_emul->e_errno)
253 			error = p->p_emul->e_errno[error];
254 		tf->tf_r0 = error;
255 		tf->tf_ssr &= ~PSL_TBIT;	/* T bit */
256 
257 		break;
258 	}
259 
260 	userret(l);
261 }
262 
263 
264 #if defined(KTRACE) || defined(SYSTRACE)
265 /*
266  * Like syscall_plain but with trace_enter/trace_exit.
267  */
268 static void
269 syscall_fancy(struct lwp *l, struct trapframe *tf)
270 {
271 	struct proc *p = l->l_proc;
272 	caddr_t params;
273 	const struct sysent *callp;
274 	int error, opc, nsys;
275 	size_t argsize;
276 	register_t code, args[8], rval[2], ocode;
277 
278 	uvmexp.syscalls++;
279 
280 	opc = tf->tf_spc;
281 	ocode = code = tf->tf_r0;
282 
283 	nsys = p->p_emul->e_nsysent;
284 	callp = p->p_emul->e_sysent;
285 
286 	params = (caddr_t)tf->tf_r15;
287 
288 	switch (code) {
289 	case SYS_syscall:
290 		/*
291 		 * Code is first argument, followed by actual args.
292 		 */
293 	        code = tf->tf_r4;  /* fuword(params); */
294 		/* params += sizeof(int); */
295 		break;
296 	case SYS___syscall:
297 		/*
298 		 * Like syscall, but code is a quad, so as to maintain
299 		 * quad alignment for the rest of the arguments.
300 		 */
301 		if (callp != sysent)
302 			break;
303 		/* fuword(params + _QUAD_LOWWORD * sizeof(int)); */
304 #if _BYTE_ORDER == BIG_ENDIAN
305 		code = tf->tf_r5;
306 #else
307 		code = tf->tf_r4;
308 #endif
309 		/* params += sizeof(quad_t); */
310 		break;
311 	default:
312 		break;
313 	}
314 	if (code < 0 || code >= nsys)
315 		callp += p->p_emul->e_nosys;		/* illegal */
316 	else
317 		callp += code;
318 	argsize = callp->sy_argsize;
319 
320 	if (ocode == SYS_syscall) {
321 		if (argsize) {
322 			args[0] = tf->tf_r5;
323 			args[1] = tf->tf_r6;
324 			args[2] = tf->tf_r7;
325 			if (argsize > 3 * sizeof(int)) {
326 				argsize -= 3 * sizeof(int);
327 				error = copyin(params, (caddr_t)&args[3],
328 					       argsize);
329 			} else
330 				error = 0;
331 		} else
332 			error = 0;
333 	}
334 	else if (ocode == SYS___syscall) {
335 		if (argsize) {
336 			args[0] = tf->tf_r6;
337 			args[1] = tf->tf_r7;
338 			if (argsize > 2 * sizeof(int)) {
339 				argsize -= 2 * sizeof(int);
340 				error = copyin(params, (caddr_t)&args[2],
341 					       argsize);
342 			} else
343 				error = 0;
344 		} else
345 			error = 0;
346 	} else {
347 		if (argsize) {
348 			args[0] = tf->tf_r4;
349 			args[1] = tf->tf_r5;
350 			args[2] = tf->tf_r6;
351 			args[3] = tf->tf_r7;
352 			if (argsize > 4 * sizeof(int)) {
353 				argsize -= 4 * sizeof(int);
354 				error = copyin(params, (caddr_t)&args[4],
355 					       argsize);
356 			} else
357 				error = 0;
358 		} else
359 			error = 0;
360 	}
361 
362 	if (error)
363 		goto bad;
364 
365 	if ((error = trace_enter(l, code, code, NULL, args)) != 0)
366 		goto out;
367 
368 	rval[0] = 0;
369 	rval[1] = tf->tf_r1;
370 	error = (*callp->sy_call)(l, args, rval);
371 out:
372 	switch (error) {
373 	case 0:
374 		tf->tf_r0 = rval[0];
375 		tf->tf_r1 = rval[1];
376 		tf->tf_ssr |= PSL_TBIT;	/* T bit */
377 
378 		break;
379 	case ERESTART:
380 		/* 2 = TRAPA instruction size */
381 		tf->tf_spc = opc - 2;
382 
383 		break;
384 	case EJUSTRETURN:
385 		/* nothing to do */
386 		break;
387 	default:
388 	bad:
389 		if (p->p_emul->e_errno)
390 			error = p->p_emul->e_errno[error];
391 		tf->tf_r0 = error;
392 		tf->tf_ssr &= ~PSL_TBIT;	/* T bit */
393 
394 		break;
395 	}
396 
397 
398 	trace_exit(l, code, args, rval, error);
399 
400 	userret(l);
401 }
402 #endif /* KTRACE || SYSTRACE */
403