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