1 /* $NetBSD: syscall.c,v 1.6 2006/03/07 07:21:50 thorpej 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 <sys/param.h> 82 #include <sys/systm.h> 83 #include <sys/proc.h> 84 #include <sys/sa.h> 85 #include <sys/savar.h> 86 #include <sys/syscall.h> 87 88 #include <sh3/userret.h> 89 90 #include <uvm/uvm_extern.h> 91 92 93 static void syscall_plain(struct lwp *, struct trapframe *); 94 static void syscall_fancy(struct lwp *, struct trapframe *); 95 96 97 void 98 syscall_intern(struct proc *p) 99 { 100 101 if (trace_is_enabled(p)) 102 p->p_md.md_syscall = syscall_fancy; 103 else 104 p->p_md.md_syscall = syscall_plain; 105 } 106 107 108 /* 109 * System call request from POSIX system call gate interface to kernel. 110 * l ... curlwp when trap occurs. 111 * tf ... full user context. 112 */ 113 static void 114 syscall_plain(struct lwp *l, struct trapframe *tf) 115 { 116 struct proc *p = l->l_proc; 117 caddr_t params; 118 const struct sysent *callp; 119 int error, opc, nsys; 120 size_t argsize; 121 register_t code, args[8], rval[2], ocode; 122 123 uvmexp.syscalls++; 124 125 opc = tf->tf_spc; 126 ocode = code = tf->tf_r0; 127 128 nsys = p->p_emul->e_nsysent; 129 callp = p->p_emul->e_sysent; 130 131 params = (caddr_t)tf->tf_r15; 132 133 switch (code) { 134 case SYS_syscall: 135 /* 136 * Code is first argument, followed by actual args. 137 */ 138 code = tf->tf_r4; /* fuword(params); */ 139 /* params += sizeof(int); */ 140 break; 141 case SYS___syscall: 142 /* 143 * Like syscall, but code is a quad, so as to maintain 144 * quad alignment for the rest of the arguments. 145 */ 146 if (callp != sysent) 147 break; 148 /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */ 149 #if _BYTE_ORDER == BIG_ENDIAN 150 code = tf->tf_r5; 151 #else 152 code = tf->tf_r4; 153 #endif 154 /* params += sizeof(quad_t); */ 155 break; 156 default: 157 break; 158 } 159 if (code < 0 || code >= nsys) 160 callp += p->p_emul->e_nosys; /* illegal */ 161 else 162 callp += code; 163 argsize = callp->sy_argsize; 164 165 if (ocode == SYS_syscall) { 166 if (argsize) { 167 args[0] = tf->tf_r5; 168 args[1] = tf->tf_r6; 169 args[2] = tf->tf_r7; 170 if (argsize > 3 * sizeof(int)) { 171 argsize -= 3 * sizeof(int); 172 error = copyin(params, (caddr_t)&args[3], 173 argsize); 174 } else 175 error = 0; 176 } else 177 error = 0; 178 } 179 else if (ocode == SYS___syscall) { 180 if (argsize) { 181 args[0] = tf->tf_r6; 182 args[1] = tf->tf_r7; 183 if (argsize > 2 * sizeof(int)) { 184 argsize -= 2 * sizeof(int); 185 error = copyin(params, (caddr_t)&args[2], 186 argsize); 187 } else 188 error = 0; 189 } else 190 error = 0; 191 } else { 192 if (argsize) { 193 args[0] = tf->tf_r4; 194 args[1] = tf->tf_r5; 195 args[2] = tf->tf_r6; 196 args[3] = tf->tf_r7; 197 if (argsize > 4 * sizeof(int)) { 198 argsize -= 4 * sizeof(int); 199 error = copyin(params, (caddr_t)&args[4], 200 argsize); 201 } else 202 error = 0; 203 } else 204 error = 0; 205 } 206 207 if (error) 208 goto bad; 209 210 rval[0] = 0; 211 rval[1] = tf->tf_r1; 212 error = (*callp->sy_call)(l, args, rval); 213 214 switch (error) { 215 case 0: 216 tf->tf_r0 = rval[0]; 217 tf->tf_r1 = rval[1]; 218 tf->tf_ssr |= PSL_TBIT; /* T bit */ 219 220 break; 221 case ERESTART: 222 /* 2 = TRAPA instruction size */ 223 tf->tf_spc = opc - 2; 224 225 break; 226 case EJUSTRETURN: 227 /* nothing to do */ 228 break; 229 default: 230 bad: 231 if (p->p_emul->e_errno) 232 error = p->p_emul->e_errno[error]; 233 tf->tf_r0 = error; 234 tf->tf_ssr &= ~PSL_TBIT; /* T bit */ 235 236 break; 237 } 238 239 userret(l); 240 } 241 242 243 /* 244 * Like syscall_plain but with trace_enter/trace_exit. 245 */ 246 static void 247 syscall_fancy(struct lwp *l, struct trapframe *tf) 248 { 249 struct proc *p = l->l_proc; 250 caddr_t params; 251 const struct sysent *callp; 252 int error, opc, nsys; 253 size_t argsize; 254 register_t code, args[8], rval[2], ocode; 255 256 uvmexp.syscalls++; 257 258 opc = tf->tf_spc; 259 ocode = code = tf->tf_r0; 260 261 nsys = p->p_emul->e_nsysent; 262 callp = p->p_emul->e_sysent; 263 264 params = (caddr_t)tf->tf_r15; 265 266 switch (code) { 267 case SYS_syscall: 268 /* 269 * Code is first argument, followed by actual args. 270 */ 271 code = tf->tf_r4; /* fuword(params); */ 272 /* params += sizeof(int); */ 273 break; 274 case SYS___syscall: 275 /* 276 * Like syscall, but code is a quad, so as to maintain 277 * quad alignment for the rest of the arguments. 278 */ 279 if (callp != sysent) 280 break; 281 /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */ 282 #if _BYTE_ORDER == BIG_ENDIAN 283 code = tf->tf_r5; 284 #else 285 code = tf->tf_r4; 286 #endif 287 /* params += sizeof(quad_t); */ 288 break; 289 default: 290 break; 291 } 292 if (code < 0 || code >= nsys) 293 callp += p->p_emul->e_nosys; /* illegal */ 294 else 295 callp += code; 296 argsize = callp->sy_argsize; 297 298 if (ocode == SYS_syscall) { 299 if (argsize) { 300 args[0] = tf->tf_r5; 301 args[1] = tf->tf_r6; 302 args[2] = tf->tf_r7; 303 if (argsize > 3 * sizeof(int)) { 304 argsize -= 3 * sizeof(int); 305 error = copyin(params, (caddr_t)&args[3], 306 argsize); 307 } else 308 error = 0; 309 } else 310 error = 0; 311 } 312 else if (ocode == SYS___syscall) { 313 if (argsize) { 314 args[0] = tf->tf_r6; 315 args[1] = tf->tf_r7; 316 if (argsize > 2 * sizeof(int)) { 317 argsize -= 2 * sizeof(int); 318 error = copyin(params, (caddr_t)&args[2], 319 argsize); 320 } else 321 error = 0; 322 } else 323 error = 0; 324 } else { 325 if (argsize) { 326 args[0] = tf->tf_r4; 327 args[1] = tf->tf_r5; 328 args[2] = tf->tf_r6; 329 args[3] = tf->tf_r7; 330 if (argsize > 4 * sizeof(int)) { 331 argsize -= 4 * sizeof(int); 332 error = copyin(params, (caddr_t)&args[4], 333 argsize); 334 } else 335 error = 0; 336 } else 337 error = 0; 338 } 339 340 if (error) 341 goto bad; 342 343 if ((error = trace_enter(l, code, code, NULL, args)) != 0) 344 goto out; 345 346 rval[0] = 0; 347 rval[1] = tf->tf_r1; 348 error = (*callp->sy_call)(l, args, rval); 349 out: 350 switch (error) { 351 case 0: 352 tf->tf_r0 = rval[0]; 353 tf->tf_r1 = rval[1]; 354 tf->tf_ssr |= PSL_TBIT; /* T bit */ 355 356 break; 357 case ERESTART: 358 /* 2 = TRAPA instruction size */ 359 tf->tf_spc = opc - 2; 360 361 break; 362 case EJUSTRETURN: 363 /* nothing to do */ 364 break; 365 default: 366 bad: 367 if (p->p_emul->e_errno) 368 error = p->p_emul->e_errno[error]; 369 tf->tf_r0 = error; 370 tf->tf_ssr &= ~PSL_TBIT; /* T bit */ 371 372 break; 373 } 374 375 376 trace_exit(l, code, args, rval, error); 377 378 userret(l); 379 } 380