1 /* $NetBSD: linux_syscall.c,v 1.8 2002/11/15 20:06:00 manu 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 #if defined(_KERNEL_OPT) 98 #include "opt_syscall_debug.h" 99 #include "opt_ktrace.h" 100 #include "opt_systrace.h" 101 #endif 102 103 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 104 105 __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.8 2002/11/15 20:06:00 manu Exp $"); 106 107 #include <sys/param.h> 108 #include <sys/systm.h> 109 #include <sys/proc.h> 110 #include <sys/user.h> 111 #include <sys/signal.h> 112 #ifdef KTRACE 113 #include <sys/ktrace.h> 114 #endif 115 #ifdef SYSTRACE 116 #include <sys/systrace.h> 117 #endif 118 #include <sys/syscall.h> 119 120 #include <uvm/uvm_extern.h> 121 122 #include <machine/cpu.h> 123 #include <machine/reg.h> 124 #include <machine/alpha.h> 125 #include <machine/userret.h> 126 127 #include <compat/linux/common/linux_types.h> 128 #include <compat/linux/common/linux_errno.h> 129 #include <compat/linux/linux_syscall.h> 130 #include <compat/linux/common/linux_signal.h> 131 #include <compat/linux/common/linux_siginfo.h> 132 #include <compat/linux/arch/alpha/linux_machdep.h> 133 134 void linux_syscall_intern(struct proc *); 135 void linux_syscall_plain(struct proc *, u_int64_t, struct trapframe *); 136 void linux_syscall_fancy(struct proc *, u_int64_t, struct trapframe *); 137 138 void 139 linux_syscall_intern(struct proc *p) 140 { 141 142 #ifdef KTRACE 143 if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) { 144 p->p_md.md_syscall = linux_syscall_fancy; 145 return; 146 } 147 #endif 148 #ifdef SYSTRACE 149 if (ISSET(p->p_flag, P_SYSTRACE)) { 150 p->p_md.md_syscall = linux_syscall_fancy; 151 return; 152 } 153 #endif 154 p->p_md.md_syscall = linux_syscall_plain; 155 } 156 157 /* 158 * Process a system call. 159 * 160 * System calls are strange beasts. They are passed the syscall number 161 * in v0, and the arguments in the registers (as normal). They return 162 * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 163 * and the return value (if any) in v0. 164 * 165 * The assembly stub takes care of moving the call number into a register 166 * we can get to, and moves all of the argument registers into their places 167 * in the trap frame. On return, it restores the callee-saved registers, 168 * a3, and v0 from the frame before returning to the user process. 169 */ 170 void 171 linux_syscall_plain(struct proc *p, u_int64_t code, struct trapframe *framep) 172 { 173 const struct sysent *callp; 174 int error; 175 u_int64_t rval[2]; 176 u_int64_t *args, copyargs[10]; /* XXX */ 177 u_int hidden, nargs; 178 179 KERNEL_PROC_LOCK(p); 180 181 uvmexp.syscalls++; 182 p->p_md.md_tf = framep; 183 184 callp = p->p_emul->e_sysent; 185 186 switch (code) { 187 case LINUX_SYS_syscall: 188 /* OSF/1 syscall() */ 189 code = framep->tf_regs[FRAME_A0]; 190 hidden = 1; 191 break; 192 default: 193 hidden = 0; 194 break; 195 } 196 197 code &= (LINUX_SYS_NSYSENT - 1); 198 callp += code; 199 200 nargs = callp->sy_narg + hidden; 201 switch (nargs) { 202 default: 203 error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 204 (nargs - 6) * sizeof(u_int64_t)); 205 if (error) 206 goto bad; 207 case 6: 208 copyargs[5] = framep->tf_regs[FRAME_A5]; 209 case 5: 210 copyargs[4] = framep->tf_regs[FRAME_A4]; 211 case 4: 212 copyargs[3] = framep->tf_regs[FRAME_A3]; 213 copyargs[2] = framep->tf_regs[FRAME_A2]; 214 copyargs[1] = framep->tf_regs[FRAME_A1]; 215 copyargs[0] = framep->tf_regs[FRAME_A0]; 216 args = copyargs; 217 break; 218 case 3: 219 case 2: 220 case 1: 221 case 0: 222 args = &framep->tf_regs[FRAME_A0]; 223 break; 224 } 225 args += hidden; 226 227 #ifdef SYSCALL_DEBUG 228 scdebug_call(p, code, args); 229 #endif 230 231 rval[0] = 0; 232 rval[1] = 0; 233 error = (*callp->sy_call)(p, args, rval); 234 235 switch (error) { 236 case 0: 237 framep->tf_regs[FRAME_V0] = rval[0]; 238 framep->tf_regs[FRAME_A4] = rval[1]; 239 framep->tf_regs[FRAME_A3] = 0; 240 break; 241 case ERESTART: 242 framep->tf_regs[FRAME_PC] -= 4; 243 break; 244 case EJUSTRETURN: 245 break; 246 default: 247 bad: 248 error = native_to_linux_errno[error]; 249 framep->tf_regs[FRAME_V0] = error; 250 framep->tf_regs[FRAME_A3] = 1; 251 break; 252 } 253 254 #ifdef SYSCALL_DEBUG 255 scdebug_ret(p, code, error, rval); 256 #endif 257 KERNEL_PROC_UNLOCK(p); 258 userret(p); 259 } 260 261 void 262 linux_syscall_fancy(struct proc *p, u_int64_t code, struct trapframe *framep) 263 { 264 const struct sysent *callp; 265 int error; 266 u_int64_t rval[2]; 267 u_int64_t *args, copyargs[10]; /* XXX */ 268 u_int hidden, nargs; 269 270 KERNEL_PROC_LOCK(p); 271 272 uvmexp.syscalls++; 273 p->p_md.md_tf = framep; 274 275 callp = p->p_emul->e_sysent; 276 277 switch (code) { 278 case LINUX_SYS_syscall: 279 /* OSF/1 syscall() */ 280 code = framep->tf_regs[FRAME_A0]; 281 hidden = 1; 282 break; 283 default: 284 hidden = 0; 285 break; 286 } 287 288 code &= (LINUX_SYS_NSYSENT - 1); 289 callp += code; 290 291 nargs = callp->sy_narg + hidden; 292 switch (nargs) { 293 default: 294 error = copyin((caddr_t)alpha_pal_rdusp(), ©args[6], 295 (nargs - 6) * sizeof(u_int64_t)); 296 if (error) 297 goto bad; 298 case 6: 299 copyargs[5] = framep->tf_regs[FRAME_A5]; 300 case 5: 301 copyargs[4] = framep->tf_regs[FRAME_A4]; 302 case 4: 303 copyargs[3] = framep->tf_regs[FRAME_A3]; 304 copyargs[2] = framep->tf_regs[FRAME_A2]; 305 copyargs[1] = framep->tf_regs[FRAME_A1]; 306 copyargs[0] = framep->tf_regs[FRAME_A0]; 307 args = copyargs; 308 break; 309 case 3: 310 case 2: 311 case 1: 312 case 0: 313 args = &framep->tf_regs[FRAME_A0]; 314 break; 315 } 316 args += hidden; 317 318 319 if ((error = trace_enter(p, code, code, args, rval)) != 0) 320 goto bad; 321 322 rval[0] = 0; 323 rval[1] = 0; 324 error = (*callp->sy_call)(p, args, rval); 325 326 switch (error) { 327 case 0: 328 framep->tf_regs[FRAME_V0] = rval[0]; 329 framep->tf_regs[FRAME_A4] = rval[1]; 330 framep->tf_regs[FRAME_A3] = 0; 331 break; 332 case ERESTART: 333 framep->tf_regs[FRAME_PC] -= 4; 334 break; 335 case EJUSTRETURN: 336 break; 337 default: 338 bad: 339 error = native_to_linux_errno[error]; 340 framep->tf_regs[FRAME_V0] = error; 341 framep->tf_regs[FRAME_A3] = 1; 342 break; 343 } 344 345 KERNEL_PROC_UNLOCK(p); 346 347 trace_exit(p, code, args, rval, error); 348 349 userret(p); 350 } 351