1 /* $NetBSD: m68k_syscall.c,v 1.5 2002/11/15 20:06:02 manu Exp $ */ 2 3 /*- 4 * Portions Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 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. 22 * 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. 34 */ 35 36 /* 37 * Copyright (c) 1988 University of Utah. 38 * Copyright (c) 1982, 1986, 1990, 1993 39 * The Regents of the University of California. All rights reserved. 40 * 41 * This code is derived from software contributed to Berkeley by 42 * the Systems Programming Group of the University of Utah Computer 43 * Science Department. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the University of 56 * California, Berkeley and its contributors. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 * 73 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 74 * 75 * @(#)trap.c 8.5 (Berkeley) 1/4/94 76 */ 77 78 #include "opt_syscall_debug.h" 79 #include "opt_execfmt.h" 80 #include "opt_ktrace.h" 81 #include "opt_systrace.h" 82 #include "opt_compat_netbsd.h" 83 #include "opt_compat_aout_m68k.h" 84 85 #include <sys/param.h> 86 #include <sys/systm.h> 87 #include <sys/proc.h> 88 #include <sys/acct.h> 89 #include <sys/kernel.h> 90 #include <sys/syscall.h> 91 #include <sys/syslog.h> 92 #include <sys/user.h> 93 #ifdef KTRACE 94 #include <sys/ktrace.h> 95 #endif 96 #ifdef SYSTRACE 97 #include <sys/systrace.h> 98 #endif 99 100 #include <machine/psl.h> 101 #include <machine/cpu.h> 102 #include <machine/reg.h> 103 104 #include <uvm/uvm_extern.h> 105 106 /* 107 * Defined in machine-specific code (usually trap.c) 108 * XXX: This will disappear when all m68k ports share common trap() code... 109 */ 110 extern void machine_userret(struct proc *, struct frame *, u_quad_t); 111 112 void syscall(register_t, struct frame); 113 114 void syscall_intern(struct proc *); 115 #ifdef COMPAT_AOUT_M68K 116 void aoutm68k_syscall_intern(struct proc *); 117 #endif 118 static void syscall_plain(register_t, struct proc *, struct frame *); 119 #if defined(KTRACE) || defined(SYSTRACE) 120 static void syscall_fancy(register_t, struct proc *, struct frame *); 121 #endif 122 123 124 /* 125 * Process a system call. 126 */ 127 void 128 syscall(code, frame) 129 register_t code; 130 struct frame frame; 131 { 132 struct proc *p; 133 u_quad_t sticks; 134 135 uvmexp.syscalls++; 136 if (!USERMODE(frame.f_sr)) 137 panic("syscall"); 138 139 p = curproc; 140 sticks = p->p_sticks; 141 p->p_md.md_regs = frame.f_regs; 142 143 (p->p_md.md_syscall)(code, p, &frame); 144 145 machine_userret(p, &frame, sticks); 146 } 147 148 void 149 syscall_intern(struct proc *p) 150 { 151 152 #ifdef KTRACE 153 if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) 154 p->p_md.md_syscall = syscall_fancy; 155 else 156 #endif 157 #ifdef SYSTRACE 158 if (ISSET(p->p_flag, P_SYSTRACE)) 159 p->p_md.md_syscall = syscall_fancy; 160 else 161 #endif 162 p->p_md.md_syscall = syscall_plain; 163 } 164 165 #ifdef COMPAT_AOUT_M68K 166 /* 167 * Not worth the effort of a whole new set of syscall_{plain,fancy} functions 168 */ 169 void 170 aoutm68k_syscall_intern(struct proc *p) 171 { 172 173 #ifdef KTRACE 174 if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) 175 p->p_md.md_syscall = syscall_fancy; 176 else 177 #endif 178 #ifdef SYSTRACE 179 if (ISSET(p->p_flag, P_SYSTRACE)) 180 p->p_md.md_syscall = syscall_fancy; 181 else 182 #endif 183 p->p_md.md_syscall = syscall_plain; 184 } 185 #endif 186 187 static void 188 syscall_plain(register_t code, struct proc *p, struct frame *frame) 189 { 190 caddr_t params; 191 const struct sysent *callp; 192 int error, nsys; 193 size_t argsize; 194 register_t args[16], rval[2]; 195 196 nsys = p->p_emul->e_nsysent; 197 callp = p->p_emul->e_sysent; 198 199 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 200 201 switch (code) { 202 case SYS_syscall: 203 /* 204 * Code is first argument, followed by actual args. 205 */ 206 code = fuword(params); 207 params += sizeof(int); 208 /* 209 * XXX sigreturn requires special stack manipulation 210 * that is only done if entered via the sigreturn 211 * trap. Cannot allow it here so make sure we fail. 212 */ 213 switch (code) { 214 #ifdef COMPAT_13 215 case SYS_compat_13_sigreturn13: 216 #endif 217 case SYS___sigreturn14: 218 code = nsys; 219 break; 220 } 221 break; 222 case SYS___syscall: 223 /* 224 * Like syscall, but code is a quad, so as to maintain 225 * quad alignment for the rest of the arguments. 226 */ 227 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 228 params += sizeof(quad_t); 229 break; 230 default: 231 break; 232 } 233 234 if (code < 0 || code >= nsys) 235 callp += p->p_emul->e_nosys; /* illegal */ 236 else 237 callp += code; 238 239 argsize = callp->sy_argsize; 240 if (argsize) { 241 error = copyin(params, (caddr_t)args, argsize); 242 if (error) 243 goto bad; 244 } 245 246 #ifdef SYSCALL_DEBUG 247 scdebug_call(p, code, args); 248 #endif 249 250 rval[0] = 0; 251 rval[1] = frame->f_regs[D1]; 252 error = (*callp->sy_call)(p, args, rval); 253 254 switch (error) { 255 case 0: 256 /* 257 * Reinitialize proc pointer `p' as it may be different 258 * if this is a child returning from fork syscall. 259 */ 260 p = curproc; 261 frame->f_regs[D0] = rval[0]; 262 frame->f_regs[D1] = rval[1]; 263 frame->f_sr &= ~PSL_C; /* carry bit */ 264 #ifdef COMPAT_AOUT_M68K 265 { 266 extern struct emul emul_netbsd_aoutm68k; 267 268 /* 269 * Some pre-m68k ELF libc assembler stubs assume 270 * %a0 is preserved across system calls... 271 */ 272 if (p->p_emul != &emul_netbsd_aoutm68k) 273 frame->f_regs[A0] = rval[0]; 274 } 275 #endif 276 break; 277 case ERESTART: 278 /* 279 * We always enter through a `trap' instruction, which is 2 280 * bytes, so adjust the pc by that amount. 281 */ 282 frame->f_pc = frame->f_pc - 2; 283 break; 284 case EJUSTRETURN: 285 /* nothing to do */ 286 break; 287 default: 288 bad: 289 /* 290 * XXX: HPUX and SVR4 use this code-path, so we may have 291 * to translate errno. 292 */ 293 if (p->p_emul->e_errno) 294 error = p->p_emul->e_errno[error]; 295 frame->f_regs[D0] = error; 296 frame->f_sr |= PSL_C; /* carry bit */ 297 break; 298 } 299 300 #ifdef SYSCALL_DEBUG 301 scdebug_ret(p, code, error, rval) 302 #endif 303 } 304 305 #if defined(KTRACE) || defined(SYSTRACE) 306 static void 307 syscall_fancy(register_t code, struct proc *p, struct frame *frame) 308 { 309 caddr_t params; 310 const struct sysent *callp; 311 int error, nsys; 312 size_t argsize; 313 register_t args[16], rval[2]; 314 315 nsys = p->p_emul->e_nsysent; 316 callp = p->p_emul->e_sysent; 317 318 params = (caddr_t)frame->f_regs[SP] + sizeof(int); 319 320 switch (code) { 321 case SYS_syscall: 322 /* 323 * Code is first argument, followed by actual args. 324 */ 325 code = fuword(params); 326 params += sizeof(int); 327 /* 328 * XXX sigreturn requires special stack manipulation 329 * that is only done if entered via the sigreturn 330 * trap. Cannot allow it here so make sure we fail. 331 */ 332 switch (code) { 333 #ifdef COMPAT_13 334 case SYS_compat_13_sigreturn13: 335 #endif 336 case SYS___sigreturn14: 337 code = nsys; 338 break; 339 } 340 break; 341 case SYS___syscall: 342 /* 343 * Like syscall, but code is a quad, so as to maintain 344 * quad alignment for the rest of the arguments. 345 */ 346 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 347 params += sizeof(quad_t); 348 break; 349 default: 350 break; 351 } 352 353 if (code < 0 || code >= nsys) 354 callp += p->p_emul->e_nosys; /* illegal */ 355 else 356 callp += code; 357 358 argsize = callp->sy_argsize; 359 if (argsize) { 360 error = copyin(params, (caddr_t)args, argsize); 361 if (error) 362 goto bad; 363 } 364 365 if ((error = trace_enter(p, code, code, args, rval)) != 0) 366 goto bad; 367 368 rval[0] = 0; 369 rval[1] = frame->f_regs[D1]; 370 error = (*callp->sy_call)(p, args, rval); 371 372 switch (error) { 373 case 0: 374 /* 375 * Reinitialize proc pointer `p' as it may be different 376 * if this is a child returning from fork syscall. 377 */ 378 p = curproc; 379 frame->f_regs[D0] = rval[0]; 380 frame->f_regs[D1] = rval[1]; 381 frame->f_sr &= ~PSL_C; /* carry bit */ 382 #ifdef COMPAT_AOUT_M68K 383 { 384 extern struct emul emul_netbsd_aoutm68k; 385 386 /* 387 * Some pre-m68k ELF libc assembler stubs assume 388 * %a0 is preserved across system calls... 389 */ 390 if (p->p_emul != &emul_netbsd_aoutm68k) 391 frame->f_regs[A0] = rval[0]; 392 } 393 #endif 394 break; 395 case ERESTART: 396 /* 397 * We always enter through a `trap' instruction, which is 2 398 * bytes, so adjust the pc by that amount. 399 */ 400 frame->f_pc = frame->f_pc - 2; 401 break; 402 case EJUSTRETURN: 403 /* nothing to do */ 404 break; 405 default: 406 bad: 407 /* 408 * XXX: HPUX and SVR4 use this code-path, so we may have 409 * to translate errno. 410 */ 411 if (p->p_emul->e_errno) 412 error = p->p_emul->e_errno[error]; 413 frame->f_regs[D0] = error; 414 frame->f_sr |= PSL_C; /* carry bit */ 415 break; 416 } 417 418 trace_exit(p, code, args, rval, error); 419 } 420 #endif /* KTRACE || SYSTRACE */ 421 422 void 423 child_return(arg) 424 void *arg; 425 { 426 struct proc *p = arg; 427 /* See cpu_fork() */ 428 struct frame *f = (struct frame *)p->p_md.md_regs; 429 430 f->f_regs[D0] = 0; 431 f->f_sr &= ~PSL_C; 432 f->f_format = FMT0; 433 434 machine_userret(p, f, 0); 435 #ifdef KTRACE 436 if (KTRPOINT(p, KTR_SYSRET)) 437 ktrsysret(p, SYS_fork, 0, 0); 438 #endif 439 } 440