Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / m68k / m68k / m68k_syscall.c
blobeccfb314c1c937a49166ca0379ec3023918b7b71
1 /* $NetBSD: m68k_syscall.c,v 1.37 2009/01/11 20:40:31 martin Exp $ */
3 /*-
4 * Portions Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
37 * Copyright (c) 1982, 1986, 1990, 1993
38 * The Regents of the University of California. All rights reserved.
40 * This code is derived from software contributed to Berkeley by
41 * the Systems Programming Group of the University of Utah Computer
42 * Science Department.
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. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
68 * from: Utah $Hdr: trap.c 1.37 92/12/20$
70 * @(#)trap.c 8.5 (Berkeley) 1/4/94
73 * Copyright (c) 1988 University of Utah.
75 * This code is derived from software contributed to Berkeley by
76 * the Systems Programming Group of the University of Utah Computer
77 * Science Department.
79 * Redistribution and use in source and binary forms, with or without
80 * modification, are permitted provided that the following conditions
81 * are met:
82 * 1. Redistributions of source code must retain the above copyright
83 * notice, this list of conditions and the following disclaimer.
84 * 2. Redistributions in binary form must reproduce the above copyright
85 * notice, this list of conditions and the following disclaimer in the
86 * documentation and/or other materials provided with the distribution.
87 * 3. All advertising materials mentioning features or use of this software
88 * must display the following acknowledgement:
89 * This product includes software developed by the University of
90 * California, Berkeley and its contributors.
91 * 4. Neither the name of the University nor the names of its contributors
92 * may be used to endorse or promote products derived from this software
93 * without specific prior written permission.
95 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105 * SUCH DAMAGE.
107 * from: Utah $Hdr: trap.c 1.37 92/12/20$
109 * @(#)trap.c 8.5 (Berkeley) 1/4/94
112 #include <sys/cdefs.h>
113 __KERNEL_RCSID(0, "$NetBSD: m68k_syscall.c,v 1.37 2009/01/11 20:40:31 martin Exp $");
115 #include "opt_execfmt.h"
116 #include "opt_compat_netbsd.h"
117 #include "opt_compat_aout_m68k.h"
118 #include "opt_sa.h"
120 #include <sys/param.h>
121 #include <sys/systm.h>
122 #include <sys/proc.h>
123 #include <sys/pool.h>
124 #include <sys/acct.h>
125 #include <sys/kernel.h>
126 #include <sys/sa.h>
127 #include <sys/savar.h>
128 #include <sys/syscall.h>
129 #include <sys/syscallvar.h>
130 #include <sys/syslog.h>
131 #include <sys/ktrace.h>
133 #include <machine/psl.h>
134 #include <machine/cpu.h>
135 #include <machine/reg.h>
137 #include <uvm/uvm_extern.h>
140 * Defined in machine-specific code (usually trap.c)
141 * XXX: This will disappear when all m68k ports share common trap() code...
143 extern void machine_userret(struct lwp *, struct frame *, u_quad_t);
145 void syscall(register_t, struct frame);
147 #ifdef COMPAT_AOUT_M68K
148 void aoutm68k_syscall_intern(struct proc *);
149 #endif
150 static void syscall_plain(register_t, struct lwp *, struct frame *);
151 static void syscall_fancy(register_t, struct lwp *, struct frame *);
155 * Process a system call.
157 void
158 syscall(register_t code, struct frame frame)
160 struct lwp *l;
161 struct proc *p;
162 u_quad_t sticks;
164 uvmexp.syscalls++;
165 if (!USERMODE(frame.f_sr))
166 panic("syscall");
168 l = curlwp;
169 p = l->l_proc;
170 sticks = p->p_sticks;
171 l->l_md.md_regs = frame.f_regs;
172 LWP_CACHE_CREDS(l, p);
174 #ifdef KERN_SA
175 if (__predict_false((l->l_savp)
176 && (l->l_savp->savp_pflags & SAVP_FLAG_DELIVERING)))
177 l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING;
178 #endif
180 (p->p_md.md_syscall)(code, l, &frame);
182 machine_userret(l, &frame, sticks);
185 void
186 syscall_intern(struct proc *p)
189 if (trace_is_enabled(p))
190 p->p_md.md_syscall = syscall_fancy;
191 else
192 p->p_md.md_syscall = syscall_plain;
195 #ifdef COMPAT_AOUT_M68K
197 * Not worth the effort of a whole new set of syscall_{plain,fancy} functions
199 void
200 aoutm68k_syscall_intern(struct proc *p)
203 if (trace_is_enabled(p))
204 p->p_md.md_syscall = syscall_fancy;
205 else
206 p->p_md.md_syscall = syscall_plain;
208 #endif
210 static void
211 syscall_plain(register_t code, struct lwp *l, struct frame *frame)
213 char *params;
214 const struct sysent *callp;
215 int error, nsys;
216 size_t argsize;
217 register_t args[16], rval[2];
218 struct proc *p = l->l_proc;
220 nsys = p->p_emul->e_nsysent;
221 callp = p->p_emul->e_sysent;
223 params = (char *)frame->f_regs[SP] + sizeof(int);
225 switch (code) {
226 case SYS_syscall:
228 * Code is first argument, followed by actual args.
230 code = fuword(params);
231 params += sizeof(int);
232 #if defined(COMPAT_13) || defined(COMPAT_16)
234 * XXX sigreturn requires special stack manipulation
235 * that is only done if entered via the sigreturn
236 * trap. Cannot allow it here so make sure we fail.
238 switch (code) {
239 #ifdef COMPAT_13
240 case SYS_compat_13_sigreturn13:
241 #endif
242 #ifdef COMPAT_16
243 case SYS_compat_16___sigreturn14:
244 #endif
245 code = nsys;
246 break;
248 #endif
249 break;
250 case SYS___syscall:
252 * Like syscall, but code is a quad, so as to maintain
253 * quad alignment for the rest of the arguments.
255 code = fuword(params + _QUAD_LOWWORD * sizeof(int));
256 params += sizeof(quad_t);
257 break;
258 default:
259 break;
262 if (code < 0 || code >= nsys)
263 callp += p->p_emul->e_nosys; /* illegal */
264 else
265 callp += code;
267 argsize = callp->sy_argsize;
268 if (argsize) {
269 error = copyin(params, (void *)args, argsize);
270 if (error)
271 goto bad;
274 rval[0] = 0;
275 rval[1] = frame->f_regs[D1];
276 error = sy_call(callp, l, args, rval);
278 switch (error) {
279 case 0:
281 * Reinitialize proc pointer `p' as it may be different
282 * if this is a child returning from fork syscall.
284 l = curlwp;
285 p = l->l_proc;
286 frame->f_regs[D0] = rval[0];
287 frame->f_regs[D1] = rval[1];
288 frame->f_sr &= ~PSL_C; /* carry bit */
289 #ifdef COMPAT_50
291 * Starting with the 5.0 release all libc assembler
292 * stubs properly handle returning pointers in %a0
293 * themselves, so no need to copy the syscall return
294 * value there. However, -current binaries post 4.0
295 * but pre-5.0 might still require this copy, so we
296 * select this behaviour based on COMPAT_50 as we have
297 * no equivvalent for the exact in-between version.
299 #ifdef COMPAT_AOUT_M68K
301 extern struct emul emul_netbsd_aoutm68k;
304 * Some pre-m68k ELF libc assembler stubs assume
305 * %a0 is preserved across system calls...
307 if (p->p_emul != &emul_netbsd_aoutm68k)
308 frame->f_regs[A0] = rval[0];
310 #else
311 frame->f_regs[A0] = rval[0];
312 #endif
313 #endif
314 break;
315 case ERESTART:
317 * We always enter through a `trap' instruction, which is 2
318 * bytes, so adjust the pc by that amount.
320 frame->f_pc = frame->f_pc - 2;
321 break;
322 case EJUSTRETURN:
323 /* nothing to do */
324 break;
325 default:
326 bad:
328 * XXX: SVR4 uses this code-path, so we may have
329 * to translate errno.
331 if (p->p_emul->e_errno)
332 error = p->p_emul->e_errno[error];
333 frame->f_regs[D0] = error;
334 frame->f_sr |= PSL_C; /* carry bit */
335 break;
339 static void
340 syscall_fancy(register_t code, struct lwp *l, struct frame *frame)
342 char *params;
343 const struct sysent *callp;
344 int error, nsys;
345 size_t argsize;
346 register_t args[16], rval[2];
347 struct proc *p = l->l_proc;
349 nsys = p->p_emul->e_nsysent;
350 callp = p->p_emul->e_sysent;
352 params = (char *)frame->f_regs[SP] + sizeof(int);
354 switch (code) {
355 case SYS_syscall:
357 * Code is first argument, followed by actual args.
359 code = fuword(params);
360 params += sizeof(int);
361 #if defined(COMPAT_13) || defined(COMPAT_16)
363 * XXX sigreturn requires special stack manipulation
364 * that is only done if entered via the sigreturn
365 * trap. Cannot allow it here so make sure we fail.
367 switch (code) {
368 #ifdef COMPAT_13
369 case SYS_compat_13_sigreturn13:
370 #endif
371 #ifdef COMPAT_16
372 case SYS_compat_16___sigreturn14:
373 #endif
374 code = nsys;
375 break;
377 #endif
378 break;
379 case SYS___syscall:
381 * Like syscall, but code is a quad, so as to maintain
382 * quad alignment for the rest of the arguments.
384 code = fuword(params + _QUAD_LOWWORD * sizeof(int));
385 params += sizeof(quad_t);
386 break;
387 default:
388 break;
391 if (code < 0 || code >= nsys)
392 callp += p->p_emul->e_nosys; /* illegal */
393 else
394 callp += code;
396 argsize = callp->sy_argsize;
397 if (argsize) {
398 error = copyin(params, (void *)args, argsize);
399 if (error)
400 goto bad;
403 if ((error = trace_enter(code, args, callp->sy_narg)) != 0)
404 goto out;
406 rval[0] = 0;
407 rval[1] = frame->f_regs[D1];
408 error = sy_call(callp, l, args, rval);
409 out:
410 switch (error) {
411 case 0:
413 * Reinitialize lwp/proc pointers as they may be different
414 * if this is a child returning from fork syscall.
416 l = curlwp;
417 p = l->l_proc;
418 frame->f_regs[D0] = rval[0];
419 frame->f_regs[D1] = rval[1];
420 frame->f_sr &= ~PSL_C; /* carry bit */
421 #ifdef COMPAT_50
422 /* see syscall_plain for a comment explaining this */
423 #ifdef COMPAT_AOUT_M68K
425 extern struct emul emul_netbsd_aoutm68k;
428 * Some pre-m68k ELF libc assembler stubs assume
429 * %a0 is preserved across system calls...
431 if (p->p_emul != &emul_netbsd_aoutm68k)
432 frame->f_regs[A0] = rval[0];
434 #else
435 frame->f_regs[A0] = rval[0];
436 #endif
437 #endif
438 break;
439 case ERESTART:
441 * We always enter through a `trap' instruction, which is 2
442 * bytes, so adjust the pc by that amount.
444 frame->f_pc = frame->f_pc - 2;
445 break;
446 case EJUSTRETURN:
447 /* nothing to do */
448 break;
449 default:
450 bad:
452 * XXX: SVR4 uses this code-path, so we may have
453 * to translate errno.
455 if (p->p_emul->e_errno)
456 error = p->p_emul->e_errno[error];
457 frame->f_regs[D0] = error;
458 frame->f_sr |= PSL_C; /* carry bit */
459 break;
462 trace_exit(code, rval, error);
465 void
466 child_return(void *arg)
468 struct lwp *l = arg;
469 /* See cpu_fork() */
470 struct frame *f = (struct frame *)l->l_md.md_regs;
472 f->f_regs[D0] = 0;
473 f->f_sr &= ~PSL_C;
474 f->f_format = FMT0;
476 machine_userret(l, f, 0);
477 ktrsysret(SYS_fork, 0, 0);
481 * Start a new LWP
483 void
484 startlwp(void *arg)
486 int err;
487 ucontext_t *uc = arg;
488 struct lwp *l = curlwp;
489 struct frame *f = (struct frame *)l->l_md.md_regs;
491 f->f_regs[D0] = 0;
492 f->f_sr &= ~PSL_C;
493 f->f_format = FMT0;
495 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
496 #if DIAGNOSTIC
497 if (err) {
498 printf("Error %d from cpu_setmcontext.", err);
500 #endif
501 pool_put(&lwp_uc_pool, uc);
503 machine_userret(l, f, 0);
507 * XXX This is a terrible name.
509 void
510 upcallret(struct lwp *l)
512 struct frame *f = (struct frame *)l->l_md.md_regs;
514 machine_userret(l, f, 0);