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