1/* $NetBSD: linux_syscall.c,v 1.31 2010/12/20 00:25:24 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: linux_syscall.c,v 1.31 2010/12/20 00:25:24 matt Exp $"); 93 94#include <sys/param.h> 95#include <sys/systm.h> 96#include <sys/proc.h> 97#include <sys/signal.h> 98#include <sys/syscall.h> 99#include <sys/syscallvar.h> 100 101#include <machine/cpu.h> 102#include <machine/reg.h> 103#include <machine/alpha.h> 104#include <machine/userret.h> 105 106#include <compat/linux/common/linux_types.h> 107#include <compat/linux/common/linux_errno.h> 108#include <compat/linux/linux_syscall.h> 109#include <compat/linux/common/linux_signal.h> 110#include <compat/linux/common/linux_siginfo.h> 111#include <compat/linux/arch/alpha/linux_machdep.h> 112 113void linux_syscall_intern(struct proc *); 114void linux_syscall_plain(struct lwp *, uint64_t, struct trapframe *); 115void linux_syscall_fancy(struct lwp *, uint64_t, struct trapframe *); 116 117void 118linux_syscall_intern(struct proc *p) 119{ 120 121 if (trace_is_enabled(p)) 122 p->p_md.md_syscall = linux_syscall_fancy; 123 else 124 p->p_md.md_syscall = linux_syscall_plain; 125} 126 127/* 128 * Process a system call. 129 * 130 * System calls are strange beasts. They are passed the syscall number 131 * in v0, and the arguments in the registers (as normal). They return 132 * an error flag in a3 (if a3 != 0 on return, the syscall had an error), 133 * and the return value (if any) in v0. 134 * 135 * The assembly stub takes care of moving the call number into a register 136 * we can get to, and moves all of the argument registers into their places 137 * in the trap frame. On return, it restores the callee-saved registers, 138 * a3, and v0 from the frame before returning to the user process. 139 */ 140void 141linux_syscall_plain(struct lwp *l, uint64_t code, struct trapframe *framep) 142{ 143 const struct sysent *callp; 144 int error; 145 uint64_t rval[2]; 146 uint64_t *args, copyargs[10]; /* XXX */ 147 u_int hidden, nargs; 148 struct proc *p = l->l_proc; 149 150 LWP_CACHE_CREDS(l, p); 151 152 curcpu()->ci_data.cpu_nsyscall++; 153 l->l_md.md_tf = framep; 154 155 callp = p->p_emul->e_sysent; 156 157 switch (code) { 158 case LINUX_SYS_syscall: 159 /* OSF/1 syscall() */ 160 code = framep->tf_regs[FRAME_A0]; 161 hidden = 1; 162 break; 163 default: 164 hidden = 0; 165 break; 166 } 167 168 code &= (LINUX_SYS_NSYSENT - 1); 169 callp += code; 170 171 nargs = callp->sy_narg + hidden; 172 switch (nargs) { 173 default: 174 error = copyin((void *)alpha_pal_rdusp(), ©args[6], 175 (nargs - 6) * sizeof(uint64_t)); 176 if (error) 177 goto bad; 178 case 6: 179 copyargs[5] = framep->tf_regs[FRAME_A5]; 180 case 5: 181 copyargs[4] = framep->tf_regs[FRAME_A4]; 182 case 4: 183 copyargs[3] = framep->tf_regs[FRAME_A3]; 184 copyargs[2] = framep->tf_regs[FRAME_A2]; 185 copyargs[1] = framep->tf_regs[FRAME_A1]; 186 copyargs[0] = framep->tf_regs[FRAME_A0]; 187 args = copyargs; 188 break; 189 case 3: 190 case 2: 191 case 1: 192 case 0: 193 args = &framep->tf_regs[FRAME_A0]; 194 break; 195 } 196 args += hidden; 197 198 rval[0] = 0; 199 rval[1] = 0; 200 error = sy_call(callp, l, args, rval); 201 202 switch (error) { 203 case 0: 204 framep->tf_regs[FRAME_V0] = rval[0]; 205 framep->tf_regs[FRAME_A4] = rval[1]; 206 framep->tf_regs[FRAME_A3] = 0; 207 break; 208 case ERESTART: 209 framep->tf_regs[FRAME_PC] -= 4; 210 break; 211 case EJUSTRETURN: 212 break; 213 default: 214 bad: 215 error = native_to_linux_errno[error]; 216 framep->tf_regs[FRAME_V0] = error; 217 framep->tf_regs[FRAME_A3] = 1; 218 break; 219 } 220 221 userret(l); 222} 223 224void 225linux_syscall_fancy(struct lwp *l, uint64_t code, struct trapframe *framep) 226{ 227 const struct sysent *callp; 228 int error; 229 uint64_t rval[2]; 230 uint64_t *args, copyargs[10]; 231 u_int hidden, nargs; 232 struct proc *p = l->l_proc; 233 234 LWP_CACHE_CREDS(l, p); 235 236 curcpu()->ci_data.cpu_nsyscall++; 237 l->l_md.md_tf = framep; 238 239 callp = p->p_emul->e_sysent; 240 241 switch (code) { 242 case LINUX_SYS_syscall: 243 /* OSF/1 syscall() */ 244 code = framep->tf_regs[FRAME_A0]; 245 hidden = 1; 246 break; 247 default: 248 hidden = 0; 249 break; 250 } 251 252 code &= (LINUX_SYS_NSYSENT - 1); 253 callp += code; 254 255 nargs = callp->sy_narg + hidden; 256 switch (nargs) { 257 default: 258 error = copyin((void *)alpha_pal_rdusp(), ©args[6], 259 (nargs - 6) * sizeof(uint64_t)); 260 if (error) { 261 args = copyargs; 262 goto bad; 263 } 264 case 6: 265 copyargs[5] = framep->tf_regs[FRAME_A5]; 266 case 5: 267 copyargs[4] = framep->tf_regs[FRAME_A4]; 268 case 4: 269 copyargs[3] = framep->tf_regs[FRAME_A3]; 270 copyargs[2] = framep->tf_regs[FRAME_A2]; 271 copyargs[1] = framep->tf_regs[FRAME_A1]; 272 copyargs[0] = framep->tf_regs[FRAME_A0]; 273 args = copyargs; 274 break; 275 case 3: 276 case 2: 277 case 1: 278 case 0: 279 args = &framep->tf_regs[FRAME_A0]; 280 break; 281 } 282 args += hidden; 283 284 285 if ((error = trace_enter(code, args, callp->sy_narg)) != 0) 286 goto out; 287 288 rval[0] = 0; 289 rval[1] = 0; 290 error = sy_call(callp, l, args, rval); 291out: 292 switch (error) { 293 case 0: 294 framep->tf_regs[FRAME_V0] = rval[0]; 295 framep->tf_regs[FRAME_A4] = rval[1]; 296 framep->tf_regs[FRAME_A3] = 0; 297 break; 298 case ERESTART: 299 framep->tf_regs[FRAME_PC] -= 4; 300 break; 301 case EJUSTRETURN: 302 break; 303 default: 304 bad: 305 error = native_to_linux_errno[error]; 306 framep->tf_regs[FRAME_V0] = error; 307 framep->tf_regs[FRAME_A3] = 1; 308 break; 309 } 310 311 trace_exit(code, rval, error); 312 313 userret(l); 314} 315