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