sunos_syscall.c revision 1.22
1/* $NetBSD: sunos_syscall.c,v 1.22 2011/02/08 20:20:16 rmind Exp $ */ 2 3/*- 4 * Portions Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * Copyright (c) 1988 University of Utah. 31 * Copyright (c) 1982, 1986, 1990, 1993 32 * The Regents of the University of California. All rights reserved. 33 * 34 * This code is derived from software contributed to Berkeley by 35 * the Systems Programming Group of the University of Utah Computer 36 * Science Department. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. Neither the name of the University nor the names of its contributors 47 * may be used to endorse or promote products derived from this software 48 * without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 * 62 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 63 * 64 * @(#)trap.c 8.5 (Berkeley) 1/4/94 65 */ 66 67#include <sys/cdefs.h> 68__KERNEL_RCSID(0, "$NetBSD: sunos_syscall.c,v 1.22 2011/02/08 20:20:16 rmind Exp $"); 69 70#ifdef _KERNEL_OPT 71#include "opt_execfmt.h" 72#endif 73 74#include <sys/param.h> 75#include <sys/systm.h> 76#include <sys/proc.h> 77#include <sys/acct.h> 78#include <sys/kernel.h> 79#include <sys/syscall.h> 80#include <sys/syscallvar.h> 81#include <sys/syslog.h> 82 83#include <machine/psl.h> 84#include <machine/cpu.h> 85#include <machine/reg.h> 86 87#include <uvm/uvm_extern.h> 88 89#include <compat/sunos/sunos_syscall.h> 90#include <compat/sunos/sunos_exec.h> 91 92void sunos_syscall_intern(struct proc *); 93static void sunos_syscall_plain(register_t, struct lwp *, struct frame *); 94static void sunos_syscall_fancy(register_t, struct lwp *, struct frame *); 95 96void 97sunos_syscall_intern(struct proc *p) 98{ 99 100 if (trace_is_enabled(p)) 101 p->p_md.md_syscall = sunos_syscall_fancy; 102 else 103 p->p_md.md_syscall = sunos_syscall_plain; 104} 105 106static void 107sunos_syscall_plain(register_t code, struct lwp *l, struct frame *frame) 108{ 109 struct proc *p = l->l_proc; 110 char *params; 111 const struct sysent *callp; 112 int error, nsys; 113 size_t argsize; 114 register_t args[16], rval[2]; 115 116 nsys = p->p_emul->e_nsysent; 117 callp = p->p_emul->e_sysent; 118 119 /* 120 * SunOS passes the syscall-number on the stack, whereas 121 * BSD passes it in D0. So, we have to get the real "code" 122 * from the stack, and clean up the stack, as SunOS glue 123 * code assumes the kernel pops the syscall argument the 124 * glue pushed on the stack. Sigh... 125 */ 126 code = fuword((void *)frame->f_regs[SP]); 127 128 /* 129 * XXX 130 * Don't do this for sunos_sigreturn, as there's no stored pc 131 * on the stack to skip, the argument follows the syscall 132 * number without a gap. 133 */ 134 if (code != SUNOS_SYS_sigreturn) { 135 frame->f_regs[SP] += sizeof (int); 136 /* 137 * remember that we adjusted the SP, 138 * might have to undo this if the system call 139 * returns ERESTART. 140 */ 141 l->l_md.md_flags |= MDL_STACKADJ; 142 } else 143 l->l_md.md_flags &= ~MDL_STACKADJ; 144 145 params = (char *)frame->f_regs[SP] + sizeof(int); 146 147 switch (code) { 148 case SUNOS_SYS_syscall: 149 /* 150 * Code is first argument, followed by actual args. 151 */ 152 code = fuword(params); 153 params += sizeof(int); 154 break; 155 default: 156 break; 157 } 158 159 if (code < 0 || code >= nsys) 160 callp += p->p_emul->e_nosys; /* illegal */ 161 else 162 callp += code; 163 164 argsize = callp->sy_argsize; 165 if (argsize) { 166 error = copyin(params, (void *)args, argsize); 167 if (error) 168 goto bad; 169 } 170 171 rval[0] = 0; 172 rval[1] = frame->f_regs[D1]; 173 error = sy_call(callp, l, args, rval); 174 175 switch (error) { 176 case 0: 177 /* 178 * Reinitialize proc pointer `p' as it may be different 179 * if this is a child returning from fork syscall. 180 */ 181 p = curproc; 182 frame->f_regs[D0] = rval[0]; 183 frame->f_regs[D1] = rval[1]; 184 frame->f_sr &= ~PSL_C; /* carry bit */ 185 break; 186 case ERESTART: 187 /* 188 * We always enter through a `trap' instruction, which is 2 189 * bytes, so adjust the pc by that amount. 190 */ 191 frame->f_pc = frame->f_pc - 2; 192 break; 193 case EJUSTRETURN: 194 /* nothing to do */ 195 break; 196 default: 197 bad: 198 frame->f_regs[D0] = error; 199 frame->f_sr |= PSL_C; /* carry bit */ 200 break; 201 } 202 203 /* need new p-value for this */ 204 if (l->l_md.md_flags & MDL_STACKADJ) { 205 l->l_md.md_flags &= ~MDL_STACKADJ; 206 if (error == ERESTART) 207 frame->f_regs[SP] -= sizeof (int); 208 } 209} 210 211static void 212sunos_syscall_fancy(register_t code, struct lwp *l, struct frame *frame) 213{ 214 struct proc *p = l->l_proc; 215 char *params; 216 const struct sysent *callp; 217 int error, nsys; 218 size_t argsize; 219 register_t args[16], rval[2]; 220 221 nsys = p->p_emul->e_nsysent; 222 callp = p->p_emul->e_sysent; 223 224 /* 225 * SunOS passes the syscall-number on the stack, whereas 226 * BSD passes it in D0. So, we have to get the real "code" 227 * from the stack, and clean up the stack, as SunOS glue 228 * code assumes the kernel pops the syscall argument the 229 * glue pushed on the stack. Sigh... 230 */ 231 code = fuword((void *)frame->f_regs[SP]); 232 233 /* 234 * XXX 235 * Don't do this for sunos_sigreturn, as there's no stored pc 236 * on the stack to skip, the argument follows the syscall 237 * number without a gap. 238 */ 239 if (code != SUNOS_SYS_sigreturn) { 240 frame->f_regs[SP] += sizeof (int); 241 /* 242 * remember that we adjusted the SP, 243 * might have to undo this if the system call 244 * returns ERESTART. 245 */ 246 l->l_md.md_flags |= MDL_STACKADJ; 247 } else 248 l->l_md.md_flags &= ~MDL_STACKADJ; 249 250 params = (char *)frame->f_regs[SP] + sizeof(int); 251 252 switch (code) { 253 case SUNOS_SYS_syscall: 254 /* 255 * Code is first argument, followed by actual args. 256 */ 257 code = fuword(params); 258 params += sizeof(int); 259 break; 260 default: 261 break; 262 } 263 264 if (code < 0 || code >= nsys) 265 callp += p->p_emul->e_nosys; /* illegal */ 266 else 267 callp += code; 268 269 argsize = callp->sy_argsize; 270 if (argsize) { 271 error = copyin(params, (void *)args, argsize); 272 if (error) 273 goto bad; 274 } 275 276 if ((error = trace_enter(code, args, callp->sy_narg)) != 0) 277 goto out; 278 279 rval[0] = 0; 280 rval[1] = frame->f_regs[D1]; 281 error = sy_call(callp, l, args, rval); 282out: 283 switch (error) { 284 case 0: 285 /* 286 * Reinitialize proc pointer `p' as it may be different 287 * if this is a child returning from fork syscall. 288 */ 289 p = curproc; 290 frame->f_regs[D0] = rval[0]; 291 frame->f_regs[D1] = rval[1]; 292 frame->f_sr &= ~PSL_C; /* carry bit */ 293 break; 294 case ERESTART: 295 /* 296 * We always enter through a `trap' instruction, which is 2 297 * bytes, so adjust the pc by that amount. 298 */ 299 frame->f_pc = frame->f_pc - 2; 300 break; 301 case EJUSTRETURN: 302 /* nothing to do */ 303 break; 304 default: 305 bad: 306 frame->f_regs[D0] = error; 307 frame->f_sr |= PSL_C; /* carry bit */ 308 break; 309 } 310 311 /* need new p-value for this */ 312 if (l->l_md.md_flags & MDL_STACKADJ) { 313 l->l_md.md_flags &= ~MDL_STACKADJ; 314 if (error == ERESTART) 315 frame->f_regs[SP] -= sizeof (int); 316 } 317 318 trace_exit(code, rval, error); 319} 320