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