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