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