1 /* $NetBSD: syscall.c,v 1.3 2001/01/03 22:15:38 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center, and by Charles M. Hannum. 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. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by Christopher G. Demetriou 54 * for the NetBSD Project. 55 * 4. The name of the author may not be used to endorse or promote products 56 * derived from this software without specific prior written permission 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 */ 69 70 /* 71 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 72 * All rights reserved. 73 * 74 * Author: Chris G. Demetriou 75 * 76 * Permission to use, copy, modify and distribute this software and 77 * its documentation is hereby granted, provided that both the copyright 78 * notice and this permission notice appear in all copies of the 79 * software, derivative works or modified versions, and any portions 80 * thereof, and that both notices appear in supporting documentation. 81 * 82 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 83 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 84 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 85 * 86 * Carnegie Mellon requests users of this software to return to 87 * 88 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 89 * School of Computer Science 90 * Carnegie Mellon University 91 * Pittsburgh PA 15213-3890 92 * 93 * any improvements or extensions that they make and grant Carnegie the 94 * rights to redistribute these changes. 95 */ 96 97 #include "opt_syscall_debug.h" 98 #include "opt_ktrace.h" 99 100 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 101 102 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.3 2001/01/03 22:15:38 thorpej Exp $"); 103 104 #include <sys/param.h> 105 #include <sys/systm.h> 106 #include <sys/proc.h> 107 #include <sys/user.h> 108 #include <sys/signal.h> 109 #ifdef KTRACE 110 #include <sys/ktrace.h> 111 #endif 112 #include <sys/syscall.h> 113 114 #include <uvm/uvm_extern.h> 115 116 #include <machine/cpu.h> 117 #include <machine/reg.h> 118 #include <machine/alpha.h> 119 #include <machine/userret.h> 120 121 void syscall_intern(struct proc *); 122 void syscall_plain(struct proc *, u_int64_t, struct trapframe *); 123 void syscall_fancy(struct proc *, u_int64_t, struct trapframe *); 124 125 void 126 syscall_intern(struct proc *p) 127 { 128 129 #ifdef KTRACE 130 if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) 131 p->p_md.md_syscall = syscall_fancy; 132 else 133 #endif 134 p->p_md.md_syscall = syscall_plain; 135 } 136 137 /* 138 * Process a system call. 139 * 140 * System calls are strange beasts. They are passed the syscall number 141 * in v0, and the arguments in the registers (as normal). They return 142 * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 143 * and the return value (if any) in v0. 144 * 145 * The assembly stub takes care of moving the call number into a register 146 * we can get to, and moves all of the argument registers into their places 147 * in the trap frame. On return, it restores the callee-saved registers, 148 * a3, and v0 from the frame before returning to the user process. 149 */ 150 void 151 syscall_plain(struct proc *p, u_int64_t code, struct trapframe *framep) 152 { 153 const struct sysent *callp; 154 int error; 155 u_int64_t rval[2]; 156 u_int64_t *args, copyargs[10]; /* XXX */ 157 u_int hidden, nargs; 158 159 KERNEL_PROC_LOCK(p); 160 161 uvmexp.syscalls++; 162 p->p_md.md_tf = framep; 163 164 callp = p->p_emul->e_sysent; 165 166 switch (code) { 167 case SYS_syscall: 168 case SYS___syscall: 169 /* 170 * syscall() and __syscall() are handled the same on 171 * the alpha, as everything is 64-bit aligned, anyway. 172 */ 173 code = framep->tf_regs[FRAME_A0]; 174 hidden = 1; 175 break; 176 default: 177 hidden = 0; 178 break; 179 } 180 181 code &= (SYS_NSYSENT - 1); 182 callp += code; 183 184 nargs = callp->sy_narg + hidden; 185 switch (nargs) { 186 default: 187 error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 188 (nargs - 6) * sizeof(u_int64_t)); 189 if (error) 190 goto bad; 191 case 6: 192 copyargs[5] = framep->tf_regs[FRAME_A5]; 193 case 5: 194 copyargs[4] = framep->tf_regs[FRAME_A4]; 195 case 4: 196 copyargs[3] = framep->tf_regs[FRAME_A3]; 197 copyargs[2] = framep->tf_regs[FRAME_A2]; 198 copyargs[1] = framep->tf_regs[FRAME_A1]; 199 copyargs[0] = framep->tf_regs[FRAME_A0]; 200 args = copyargs; 201 break; 202 case 3: 203 case 2: 204 case 1: 205 case 0: 206 args = &framep->tf_regs[FRAME_A0]; 207 break; 208 } 209 args += hidden; 210 211 #ifdef SYSCALL_DEBUG 212 scdebug_call(p, code, args); 213 #endif 214 215 rval[0] = 0; 216 rval[1] = 0; 217 error = (*callp->sy_call)(p, args, rval); 218 219 switch (error) { 220 case 0: 221 framep->tf_regs[FRAME_V0] = rval[0]; 222 framep->tf_regs[FRAME_A4] = rval[1]; 223 framep->tf_regs[FRAME_A3] = 0; 224 break; 225 case ERESTART: 226 framep->tf_regs[FRAME_PC] -= 4; 227 break; 228 case EJUSTRETURN: 229 break; 230 default: 231 bad: 232 framep->tf_regs[FRAME_V0] = error; 233 framep->tf_regs[FRAME_A3] = 1; 234 break; 235 } 236 237 #ifdef SYSCALL_DEBUG 238 scdebug_ret(p, code, error, rval); 239 #endif 240 KERNEL_PROC_UNLOCK(p); 241 userret(p); 242 } 243 244 void 245 syscall_fancy(struct proc *p, u_int64_t code, struct trapframe *framep) 246 { 247 const struct sysent *callp; 248 int error; 249 u_int64_t rval[2]; 250 u_int64_t *args, copyargs[10]; /* XXX */ 251 u_int hidden, nargs; 252 253 KERNEL_PROC_LOCK(p); 254 255 uvmexp.syscalls++; 256 p->p_md.md_tf = framep; 257 258 callp = p->p_emul->e_sysent; 259 260 switch (code) { 261 case SYS_syscall: 262 case SYS___syscall: 263 /* 264 * syscall() and __syscall() are handled the same on 265 * the alpha, as everything is 64-bit aligned, anyway. 266 */ 267 code = framep->tf_regs[FRAME_A0]; 268 hidden = 1; 269 break; 270 default: 271 hidden = 0; 272 break; 273 } 274 275 code &= (SYS_NSYSENT - 1); 276 callp += code; 277 278 nargs = callp->sy_narg + hidden; 279 switch (nargs) { 280 default: 281 error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 282 (nargs - 6) * sizeof(u_int64_t)); 283 if (error) 284 goto bad; 285 case 6: 286 copyargs[5] = framep->tf_regs[FRAME_A5]; 287 case 5: 288 copyargs[4] = framep->tf_regs[FRAME_A4]; 289 case 4: 290 copyargs[3] = framep->tf_regs[FRAME_A3]; 291 copyargs[2] = framep->tf_regs[FRAME_A2]; 292 copyargs[1] = framep->tf_regs[FRAME_A1]; 293 copyargs[0] = framep->tf_regs[FRAME_A0]; 294 args = copyargs; 295 break; 296 case 3: 297 case 2: 298 case 1: 299 case 0: 300 args = &framep->tf_regs[FRAME_A0]; 301 break; 302 } 303 args += hidden; 304 305 #ifdef KTRACE 306 if (KTRPOINT(p, KTR_SYSCALL)) 307 ktrsyscall(p, code, callp->sy_argsize, args); 308 #endif 309 #ifdef SYSCALL_DEBUG 310 scdebug_call(p, code, args); 311 #endif 312 313 rval[0] = 0; 314 rval[1] = 0; 315 error = (*callp->sy_call)(p, args, rval); 316 317 switch (error) { 318 case 0: 319 framep->tf_regs[FRAME_V0] = rval[0]; 320 framep->tf_regs[FRAME_A4] = rval[1]; 321 framep->tf_regs[FRAME_A3] = 0; 322 break; 323 case ERESTART: 324 framep->tf_regs[FRAME_PC] -= 4; 325 break; 326 case EJUSTRETURN: 327 break; 328 default: 329 bad: 330 framep->tf_regs[FRAME_V0] = error; 331 framep->tf_regs[FRAME_A3] = 1; 332 break; 333 } 334 335 #ifdef SYSCALL_DEBUG 336 scdebug_ret(p, code, error, rval); 337 #endif 338 KERNEL_PROC_UNLOCK(p); 339 userret(p); 340 #ifdef KTRACE 341 if (KTRPOINT(p, KTR_SYSRET)) { 342 KERNEL_PROC_LOCK(p); 343 ktrsysret(p, code, error, rval[0]); 344 KERNEL_PROC_UNLOCK(p); 345 } 346 #endif 347 } 348 349 /* 350 * Process the tail end of a fork() for the child. 351 */ 352 void 353 child_return(void *arg) 354 { 355 struct proc *p = arg; 356 357 /* 358 * Return values in the frame set by cpu_fork(). 359 */ 360 361 KERNEL_PROC_UNLOCK(p); 362 userret(p); 363 #ifdef KTRACE 364 if (KTRPOINT(p, KTR_SYSRET)) { 365 KERNEL_PROC_LOCK(p); 366 ktrsysret(p, SYS_fork, 0, 0); 367 KERNEL_PROC_UNLOCK(p); 368 } 369 #endif 370 } 371