sunos_syscall.c revision 1.15
1/* $NetBSD: sunos_syscall.c,v 1.15 2007/03/04 06:00:06 christos 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.15 2007/03/04 06:00:06 christos Exp $"); 114 115#include "opt_execfmt.h" 116 117#include <sys/param.h> 118#include <sys/systm.h> 119#include <sys/proc.h> 120#include <sys/acct.h> 121#include <sys/kernel.h> 122#include <sys/syscall.h> 123#include <sys/syslog.h> 124#include <sys/user.h> 125 126#include <machine/psl.h> 127#include <machine/cpu.h> 128#include <machine/reg.h> 129 130#include <uvm/uvm_extern.h> 131 132#include <compat/sunos/sunos_syscall.h> 133#include <compat/sunos/sunos_exec.h> 134 135void sunos_syscall_intern(struct proc *); 136static void sunos_syscall_plain(register_t, struct lwp *, struct frame *); 137static void sunos_syscall_fancy(register_t, struct lwp *, struct frame *); 138 139void 140sunos_syscall_intern(struct proc *p) 141{ 142 143 if (trace_is_enabled(p)) 144 p->p_md.md_syscall = sunos_syscall_fancy; 145 else 146 p->p_md.md_syscall = sunos_syscall_plain; 147} 148 149static void 150sunos_syscall_plain(register_t code, struct lwp *l, struct frame *frame) 151{ 152 struct proc *p = l->l_proc; 153 void *params; 154 const struct sysent *callp; 155 int error, nsys; 156 size_t argsize; 157 register_t args[16], rval[2]; 158 159 nsys = p->p_emul->e_nsysent; 160 callp = p->p_emul->e_sysent; 161 162 /* 163 * SunOS passes the syscall-number on the stack, whereas 164 * BSD passes it in D0. So, we have to get the real "code" 165 * from the stack, and clean up the stack, as SunOS glue 166 * code assumes the kernel pops the syscall argument the 167 * glue pushed on the stack. Sigh... 168 */ 169 code = fuword((void *)frame->f_regs[SP]); 170 171 /* 172 * XXX 173 * Don't do this for sunos_sigreturn, as there's no stored pc 174 * on the stack to skip, the argument follows the syscall 175 * number without a gap. 176 */ 177 if (code != SUNOS_SYS_sigreturn) { 178 frame->f_regs[SP] += sizeof (int); 179 /* 180 * remember that we adjusted the SP, 181 * might have to undo this if the system call 182 * returns ERESTART. 183 */ 184 l->l_md.md_flags |= MDL_STACKADJ; 185 } else 186 l->l_md.md_flags &= ~MDL_STACKADJ; 187 188 params = (void *)frame->f_regs[SP] + sizeof(int); 189 190 switch (code) { 191 case SUNOS_SYS_syscall: 192 /* 193 * Code is first argument, followed by actual args. 194 */ 195 code = fuword(params); 196 params += sizeof(int); 197 break; 198 default: 199 break; 200 } 201 202 if (code < 0 || code >= nsys) 203 callp += p->p_emul->e_nosys; /* illegal */ 204 else 205 callp += code; 206 207 argsize = callp->sy_argsize; 208 if (argsize) { 209 error = copyin(params, (void *)args, argsize); 210 if (error) 211 goto bad; 212 } 213 214 rval[0] = 0; 215 rval[1] = frame->f_regs[D1]; 216 error = (*callp->sy_call)(l, args, rval); 217 218 switch (error) { 219 case 0: 220 /* 221 * Reinitialize proc pointer `p' as it may be different 222 * if this is a child returning from fork syscall. 223 */ 224 p = curproc; 225 frame->f_regs[D0] = rval[0]; 226 frame->f_regs[D1] = rval[1]; 227 frame->f_sr &= ~PSL_C; /* carry bit */ 228 break; 229 case ERESTART: 230 /* 231 * We always enter through a `trap' instruction, which is 2 232 * bytes, so adjust the pc by that amount. 233 */ 234 frame->f_pc = frame->f_pc - 2; 235 break; 236 case EJUSTRETURN: 237 /* nothing to do */ 238 break; 239 default: 240 bad: 241 frame->f_regs[D0] = error; 242 frame->f_sr |= PSL_C; /* carry bit */ 243 break; 244 } 245 246 /* need new p-value for this */ 247 if (l->l_md.md_flags & MDL_STACKADJ) { 248 l->l_md.md_flags &= ~MDL_STACKADJ; 249 if (error == ERESTART) 250 frame->f_regs[SP] -= sizeof (int); 251 } 252} 253 254static void 255sunos_syscall_fancy(register_t code, struct lwp *l, struct frame *frame) 256{ 257 struct proc *p = l->l_proc; 258 void *params; 259 const struct sysent *callp; 260 int error, nsys; 261 size_t argsize; 262 register_t args[16], rval[2]; 263 264 nsys = p->p_emul->e_nsysent; 265 callp = p->p_emul->e_sysent; 266 267 /* 268 * SunOS passes the syscall-number on the stack, whereas 269 * BSD passes it in D0. So, we have to get the real "code" 270 * from the stack, and clean up the stack, as SunOS glue 271 * code assumes the kernel pops the syscall argument the 272 * glue pushed on the stack. Sigh... 273 */ 274 code = fuword((void *)frame->f_regs[SP]); 275 276 /* 277 * XXX 278 * Don't do this for sunos_sigreturn, as there's no stored pc 279 * on the stack to skip, the argument follows the syscall 280 * number without a gap. 281 */ 282 if (code != SUNOS_SYS_sigreturn) { 283 frame->f_regs[SP] += sizeof (int); 284 /* 285 * remember that we adjusted the SP, 286 * might have to undo this if the system call 287 * returns ERESTART. 288 */ 289 l->l_md.md_flags |= MDL_STACKADJ; 290 } else 291 l->l_md.md_flags &= ~MDL_STACKADJ; 292 293 params = (void *)frame->f_regs[SP] + sizeof(int); 294 295 switch (code) { 296 case SUNOS_SYS_syscall: 297 /* 298 * Code is first argument, followed by actual args. 299 */ 300 code = fuword(params); 301 params += sizeof(int); 302 break; 303 default: 304 break; 305 } 306 307 if (code < 0 || code >= nsys) 308 callp += p->p_emul->e_nosys; /* illegal */ 309 else 310 callp += code; 311 312 argsize = callp->sy_argsize; 313 if (argsize) { 314 error = copyin(params, (void *)args, argsize); 315 if (error) 316 goto bad; 317 } 318 319 if ((error = trace_enter(l, code, code, NULL, args)) != 0) 320 goto out; 321 322 rval[0] = 0; 323 rval[1] = frame->f_regs[D1]; 324 error = (*callp->sy_call)(l, args, rval); 325out: 326 switch (error) { 327 case 0: 328 /* 329 * Reinitialize proc pointer `p' as it may be different 330 * if this is a child returning from fork syscall. 331 */ 332 p = curproc; 333 frame->f_regs[D0] = rval[0]; 334 frame->f_regs[D1] = rval[1]; 335 frame->f_sr &= ~PSL_C; /* carry bit */ 336 break; 337 case ERESTART: 338 /* 339 * We always enter through a `trap' instruction, which is 2 340 * bytes, so adjust the pc by that amount. 341 */ 342 frame->f_pc = frame->f_pc - 2; 343 break; 344 case EJUSTRETURN: 345 /* nothing to do */ 346 break; 347 default: 348 bad: 349 frame->f_regs[D0] = error; 350 frame->f_sr |= PSL_C; /* carry bit */ 351 break; 352 } 353 354 /* need new p-value for this */ 355 if (l->l_md.md_flags & MDL_STACKADJ) { 356 l->l_md.md_flags &= ~MDL_STACKADJ; 357 if (error == ERESTART) 358 frame->f_regs[SP] -= sizeof (int); 359 } 360 361 trace_exit(l, code, args, rval, error); 362} 363