1 /* $NetBSD: m68k_syscall.c,v 1.1 2000/12/19 21:09:59 scw 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_compat_netbsd.h" 82 #include "opt_compat_aout_m68k.h" 83 #include "opt_compat_sunos.h" 84 #include "opt_compat_hpux.h" 85 #include "opt_compat_linux.h" 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/proc.h> 90 #include <sys/acct.h> 91 #include <sys/kernel.h> 92 #include <sys/syscall.h> 93 #include <sys/syslog.h> 94 #include <sys/user.h> 95 #ifdef KTRACE 96 #include <sys/ktrace.h> 97 #endif 98 99 #include <machine/psl.h> 100 #include <machine/cpu.h> 101 #include <machine/reg.h> 102 103 #include <uvm/uvm_extern.h> 104 105 #ifdef COMPAT_HPUX 106 #include <compat/hpux/hpux.h> 107 #endif 108 109 #ifdef COMPAT_SUNOS 110 #include <compat/sunos/sunos_syscall.h> 111 #include <compat/sunos/sunos_exec.h> 112 #endif 113 114 #ifdef COMPAT_LINUX 115 extern struct emul emul_linux; 116 #endif 117 118 #ifdef COMPAT_AOUT_M68K 119 extern struct emul emul_netbsd_aoutm68k; 120 #endif 121 122 /* 123 * Defined in machine-specific code (usually trap.c) 124 * XXX: This will disappear when all m68k ports share common trap() code... 125 */ 126 extern void machine_userret(struct proc *, struct frame *, u_quad_t); 127 128 void syscall(register_t, struct frame); 129 130 /* 131 * Process a system call. 132 */ 133 void 134 syscall(code, frame) 135 register_t code; 136 struct frame frame; 137 { 138 caddr_t params; 139 const struct sysent *callp; 140 struct proc *p; 141 int error, opc, nsys; 142 size_t argsize; 143 register_t args[8], rval[2]; 144 u_quad_t sticks; 145 146 uvmexp.syscalls++; 147 if (!USERMODE(frame.f_sr)) 148 panic("syscall"); 149 p = curproc; 150 sticks = p->p_sticks; 151 p->p_md.md_regs = frame.f_regs; 152 opc = frame.f_pc; 153 154 nsys = p->p_emul->e_nsysent; 155 callp = p->p_emul->e_sysent; 156 157 #ifdef COMPAT_SUNOS 158 if (p->p_emul == &emul_sunos) { 159 /* 160 * SunOS passes the syscall-number on the stack, whereas 161 * BSD passes it in D0. So, we have to get the real "code" 162 * from the stack, and clean up the stack, as SunOS glue 163 * code assumes the kernel pops the syscall argument the 164 * glue pushed on the stack. Sigh... 165 */ 166 code = fuword((caddr_t)frame.f_regs[SP]); 167 168 /* 169 * XXX 170 * Don't do this for sunos_sigreturn, as there's no stored pc 171 * on the stack to skip, the argument follows the syscall 172 * number without a gap. 173 */ 174 if (code != SUNOS_SYS_sigreturn) { 175 frame.f_regs[SP] += sizeof (int); 176 /* 177 * remember that we adjusted the SP, 178 * might have to undo this if the system call 179 * returns ERESTART. 180 */ 181 p->p_md.md_flags |= MDP_STACKADJ; 182 } else 183 p->p_md.md_flags &= ~MDP_STACKADJ; 184 } 185 #endif 186 187 params = (caddr_t)frame.f_regs[SP] + sizeof(int); 188 189 switch (code) { 190 case SYS_syscall: 191 /* 192 * Code is first argument, followed by actual args. 193 */ 194 code = fuword(params); 195 params += sizeof(int); 196 /* 197 * XXX sigreturn requires special stack manipulation 198 * that is only done if entered via the sigreturn 199 * trap. Cannot allow it here so make sure we fail. 200 */ 201 switch (code) { 202 #ifdef COMPAT_13 203 case SYS_compat_13_sigreturn13: 204 #endif 205 case SYS___sigreturn14: 206 code = nsys; 207 break; 208 } 209 break; 210 case SYS___syscall: 211 /* 212 * Like syscall, but code is a quad, so as to maintain 213 * quad alignment for the rest of the arguments. 214 */ 215 if (p->p_emul->e_flags & EMUL_HAS_SYS___syscall) { 216 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 217 params += sizeof(quad_t); 218 } 219 break; 220 default: 221 break; 222 } 223 if (code < 0 || code >= nsys) 224 callp += p->p_emul->e_nosys; /* illegal */ 225 else 226 callp += code; 227 argsize = callp->sy_argsize; 228 #ifdef COMPAT_LINUX 229 if (p->p_emul == &emul_linux) { 230 /* 231 * Linux passes the args in d1-d5 232 */ 233 switch (argsize) { 234 case 20: 235 args[4] = frame.f_regs[D5]; 236 case 16: 237 args[3] = frame.f_regs[D4]; 238 case 12: 239 args[2] = frame.f_regs[D3]; 240 case 8: 241 args[1] = frame.f_regs[D2]; 242 case 4: 243 args[0] = frame.f_regs[D1]; 244 case 0: 245 error = 0; 246 break; 247 default: 248 #ifdef DEBUG 249 panic("linux syscall %d weird argsize %d", 250 code, argsize); 251 #else 252 error = EINVAL; 253 #endif 254 break; 255 } 256 } else 257 #endif 258 if (argsize) 259 error = copyin(params, (caddr_t)args, argsize); 260 else 261 error = 0; 262 #ifdef SYSCALL_DEBUG 263 scdebug_call(p, code, args); 264 #endif 265 #ifdef KTRACE 266 if (KTRPOINT(p, KTR_SYSCALL)) 267 ktrsyscall(p, code, argsize, args); 268 #endif 269 if (error) 270 goto bad; 271 rval[0] = 0; 272 rval[1] = frame.f_regs[D1]; 273 error = (*callp->sy_call)(p, args, rval); 274 switch (error) { 275 case 0: 276 /* 277 * Reinitialize proc pointer `p' as it may be different 278 * if this is a child returning from fork syscall. 279 */ 280 p = curproc; 281 frame.f_regs[D0] = rval[0]; 282 frame.f_regs[D1] = rval[1]; 283 #ifdef COMPAT_AOUT_M68K 284 /* 285 * Some pre-m68k ELF libc assembler stubs assume 286 * %a0 is preserved across system calls... 287 */ 288 if (p->p_emul != &emul_netbsd_aoutm68k) 289 frame.f_regs[A0] = rval[0]; 290 #endif 291 frame.f_sr &= ~PSL_C; /* carry bit */ 292 break; 293 case ERESTART: 294 /* 295 * We always enter through a `trap' instruction, which is 2 296 * bytes, so adjust the pc by that amount. 297 */ 298 frame.f_pc = opc - 2; 299 break; 300 case EJUSTRETURN: 301 /* nothing to do */ 302 break; 303 default: 304 bad: 305 if (p->p_emul->e_errno) 306 error = p->p_emul->e_errno[error]; 307 frame.f_regs[D0] = error; 308 frame.f_sr |= PSL_C; /* carry bit */ 309 break; 310 } 311 312 #ifdef SYSCALL_DEBUG 313 scdebug_ret(p, code, error, rval); 314 #endif 315 #ifdef COMPAT_SUNOS 316 /* need new p-value for this */ 317 if (p->p_md.md_flags & MDP_STACKADJ) { 318 p->p_md.md_flags &= ~MDP_STACKADJ; 319 if (error == ERESTART) 320 frame.f_regs[SP] -= sizeof (int); 321 } 322 #endif 323 machine_userret(p, &frame, sticks); 324 #ifdef KTRACE 325 if (KTRPOINT(p, KTR_SYSRET)) 326 ktrsysret(p, code, error, rval[0]); 327 #endif 328 } 329 330 void 331 child_return(arg) 332 void *arg; 333 { 334 struct proc *p = arg; 335 /* See cpu_fork() */ 336 struct frame *f = (struct frame *)p->p_md.md_regs; 337 338 f->f_regs[D0] = 0; 339 f->f_sr &= ~PSL_C; 340 f->f_format = FMT0; 341 342 machine_userret(p, f, 0); 343 #ifdef KTRACE 344 if (KTRPOINT(p, KTR_SYSRET)) 345 ktrsysret(p, SYS_fork, 0, 0); 346 #endif 347 } 348