11.24Sthorpej/* $NetBSD: sunos_syscall.c,v 1.24 2019/04/06 03:06:26 thorpej Exp $ */ 21.1Sscw 31.1Sscw/*- 41.1Sscw * Portions Copyright (c) 2000 The NetBSD Foundation, Inc. 51.1Sscw * All rights reserved. 61.1Sscw * 71.1Sscw * Redistribution and use in source and binary forms, with or without 81.1Sscw * modification, are permitted provided that the following conditions 91.1Sscw * are met: 101.1Sscw * 1. Redistributions of source code must retain the above copyright 111.1Sscw * notice, this list of conditions and the following disclaimer. 121.1Sscw * 2. Redistributions in binary form must reproduce the above copyright 131.1Sscw * notice, this list of conditions and the following disclaimer in the 141.1Sscw * documentation and/or other materials provided with the distribution. 151.1Sscw * 161.1Sscw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Sscw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Sscw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Sscw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Sscw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Sscw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Sscw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Sscw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Sscw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Sscw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Sscw * POSSIBILITY OF SUCH DAMAGE. 271.1Sscw */ 281.1Sscw 291.1Sscw/* 301.22Srmind * Copyright (c) 1988 University of Utah. 311.1Sscw * Copyright (c) 1982, 1986, 1990, 1993 321.1Sscw * The Regents of the University of California. All rights reserved. 331.1Sscw * 341.1Sscw * This code is derived from software contributed to Berkeley by 351.1Sscw * the Systems Programming Group of the University of Utah Computer 361.1Sscw * Science Department. 371.1Sscw * 381.1Sscw * Redistribution and use in source and binary forms, with or without 391.1Sscw * modification, are permitted provided that the following conditions 401.1Sscw * are met: 411.1Sscw * 1. Redistributions of source code must retain the above copyright 421.1Sscw * notice, this list of conditions and the following disclaimer. 431.1Sscw * 2. Redistributions in binary form must reproduce the above copyright 441.1Sscw * notice, this list of conditions and the following disclaimer in the 451.1Sscw * documentation and/or other materials provided with the distribution. 461.6Sagc * 3. Neither the name of the University nor the names of its contributors 471.6Sagc * may be used to endorse or promote products derived from this software 481.6Sagc * without specific prior written permission. 491.6Sagc * 501.6Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 511.6Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 521.6Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 531.6Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 541.6Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 551.6Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 561.6Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 571.6Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 581.6Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 591.6Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 601.6Sagc * SUCH DAMAGE. 611.6Sagc * 621.6Sagc * from: Utah $Hdr: trap.c 1.37 92/12/20$ 631.6Sagc * 641.6Sagc * @(#)trap.c 8.5 (Berkeley) 1/4/94 651.6Sagc */ 661.5Slukem 671.5Slukem#include <sys/cdefs.h> 681.24Sthorpej__KERNEL_RCSID(0, "$NetBSD: sunos_syscall.c,v 1.24 2019/04/06 03:06:26 thorpej Exp $"); 691.1Sscw 701.20Stsutsui#ifdef _KERNEL_OPT 711.1Sscw#include "opt_execfmt.h" 721.20Stsutsui#endif 731.1Sscw 741.1Sscw#include <sys/param.h> 751.1Sscw#include <sys/systm.h> 761.1Sscw#include <sys/proc.h> 771.1Sscw#include <sys/acct.h> 781.1Sscw#include <sys/kernel.h> 791.1Sscw#include <sys/syscall.h> 801.19Sad#include <sys/syscallvar.h> 811.1Sscw#include <sys/syslog.h> 821.1Sscw 831.1Sscw#include <machine/psl.h> 841.1Sscw#include <machine/cpu.h> 851.1Sscw#include <machine/reg.h> 861.1Sscw 871.1Sscw#include <uvm/uvm_extern.h> 881.1Sscw 891.1Sscw#include <compat/sunos/sunos_syscall.h> 901.1Sscw#include <compat/sunos/sunos_exec.h> 911.1Sscw 921.1Sscwvoid sunos_syscall_intern(struct proc *); 931.4Sthorpejstatic void sunos_syscall_plain(register_t, struct lwp *, struct frame *); 941.4Sthorpejstatic void sunos_syscall_fancy(register_t, struct lwp *, struct frame *); 951.1Sscw 961.1Sscwvoid 971.1Sscwsunos_syscall_intern(struct proc *p) 981.1Sscw{ 991.12Sthorpej 1001.12Sthorpej if (trace_is_enabled(p)) 1011.1Sscw p->p_md.md_syscall = sunos_syscall_fancy; 1021.1Sscw else 1031.1Sscw p->p_md.md_syscall = sunos_syscall_plain; 1041.1Sscw} 1051.1Sscw 1061.1Sscwstatic void 1071.4Sthorpejsunos_syscall_plain(register_t code, struct lwp *l, struct frame *frame) 1081.1Sscw{ 1091.4Sthorpej struct proc *p = l->l_proc; 1101.16Stsutsui char *params; 1111.1Sscw const struct sysent *callp; 1121.1Sscw int error, nsys; 1131.1Sscw size_t argsize; 1141.1Sscw register_t args[16], rval[2]; 1151.1Sscw 1161.1Sscw nsys = p->p_emul->e_nsysent; 1171.1Sscw callp = p->p_emul->e_sysent; 1181.1Sscw 1191.1Sscw /* 1201.1Sscw * SunOS passes the syscall-number on the stack, whereas 1211.1Sscw * BSD passes it in D0. So, we have to get the real "code" 1221.1Sscw * from the stack, and clean up the stack, as SunOS glue 1231.1Sscw * code assumes the kernel pops the syscall argument the 1241.1Sscw * glue pushed on the stack. Sigh... 1251.1Sscw */ 1261.24Sthorpej error = ufetch_long((void *)frame->f_regs[SP], (u_long *)&code); 1271.24Sthorpej if (error) 1281.24Sthorpej goto bad; 1291.1Sscw 1301.1Sscw /* 1311.1Sscw * XXX 1321.1Sscw * Don't do this for sunos_sigreturn, as there's no stored pc 1331.1Sscw * on the stack to skip, the argument follows the syscall 1341.1Sscw * number without a gap. 1351.1Sscw */ 1361.1Sscw if (code != SUNOS_SYS_sigreturn) { 1371.1Sscw frame->f_regs[SP] += sizeof (int); 1381.1Sscw /* 1391.14Stsutsui * remember that we adjusted the SP, 1401.1Sscw * might have to undo this if the system call 1411.1Sscw * returns ERESTART. 1421.1Sscw */ 1431.4Sthorpej l->l_md.md_flags |= MDL_STACKADJ; 1441.1Sscw } else 1451.4Sthorpej l->l_md.md_flags &= ~MDL_STACKADJ; 1461.1Sscw 1471.16Stsutsui params = (char *)frame->f_regs[SP] + sizeof(int); 1481.1Sscw 1491.1Sscw switch (code) { 1501.1Sscw case SUNOS_SYS_syscall: 1511.1Sscw /* 1521.1Sscw * Code is first argument, followed by actual args. 1531.1Sscw */ 1541.24Sthorpej error = ufetch_long((void *)params, (u_long *)&code); 1551.24Sthorpej if (error) 1561.24Sthorpej goto bad; 1571.1Sscw params += sizeof(int); 1581.1Sscw break; 1591.1Sscw default: 1601.1Sscw break; 1611.1Sscw } 1621.1Sscw 1631.1Sscw if (code < 0 || code >= nsys) 1641.1Sscw callp += p->p_emul->e_nosys; /* illegal */ 1651.1Sscw else 1661.1Sscw callp += code; 1671.1Sscw 1681.1Sscw argsize = callp->sy_argsize; 1691.1Sscw if (argsize) { 1701.15Schristos error = copyin(params, (void *)args, argsize); 1711.1Sscw if (error) 1721.1Sscw goto bad; 1731.1Sscw } 1741.1Sscw 1751.1Sscw rval[0] = 0; 1761.1Sscw rval[1] = frame->f_regs[D1]; 1771.19Sad error = sy_call(callp, l, args, rval); 1781.1Sscw 1791.1Sscw switch (error) { 1801.1Sscw case 0: 1811.1Sscw /* 1821.1Sscw * Reinitialize proc pointer `p' as it may be different 1831.1Sscw * if this is a child returning from fork syscall. 1841.1Sscw */ 1851.1Sscw p = curproc; 1861.1Sscw frame->f_regs[D0] = rval[0]; 1871.1Sscw frame->f_regs[D1] = rval[1]; 1881.1Sscw frame->f_sr &= ~PSL_C; /* carry bit */ 1891.1Sscw break; 1901.1Sscw case ERESTART: 1911.1Sscw /* 1921.1Sscw * We always enter through a `trap' instruction, which is 2 1931.1Sscw * bytes, so adjust the pc by that amount. 1941.1Sscw */ 1951.1Sscw frame->f_pc = frame->f_pc - 2; 1961.1Sscw break; 1971.1Sscw case EJUSTRETURN: 1981.1Sscw /* nothing to do */ 1991.1Sscw break; 2001.1Sscw default: 2011.1Sscw bad: 2021.1Sscw frame->f_regs[D0] = error; 2031.1Sscw frame->f_sr |= PSL_C; /* carry bit */ 2041.1Sscw break; 2051.1Sscw } 2061.1Sscw 2071.1Sscw /* need new p-value for this */ 2081.4Sthorpej if (l->l_md.md_flags & MDL_STACKADJ) { 2091.4Sthorpej l->l_md.md_flags &= ~MDL_STACKADJ; 2101.1Sscw if (error == ERESTART) 2111.1Sscw frame->f_regs[SP] -= sizeof (int); 2121.1Sscw } 2131.1Sscw} 2141.1Sscw 2151.1Sscwstatic void 2161.4Sthorpejsunos_syscall_fancy(register_t code, struct lwp *l, struct frame *frame) 2171.1Sscw{ 2181.4Sthorpej struct proc *p = l->l_proc; 2191.16Stsutsui char *params; 2201.1Sscw const struct sysent *callp; 2211.1Sscw int error, nsys; 2221.1Sscw size_t argsize; 2231.1Sscw register_t args[16], rval[2]; 2241.1Sscw 2251.1Sscw nsys = p->p_emul->e_nsysent; 2261.1Sscw callp = p->p_emul->e_sysent; 2271.1Sscw 2281.1Sscw /* 2291.1Sscw * SunOS passes the syscall-number on the stack, whereas 2301.1Sscw * BSD passes it in D0. So, we have to get the real "code" 2311.1Sscw * from the stack, and clean up the stack, as SunOS glue 2321.1Sscw * code assumes the kernel pops the syscall argument the 2331.1Sscw * glue pushed on the stack. Sigh... 2341.1Sscw */ 2351.24Sthorpej error = ufetch_long((void *)frame->f_regs[SP], (u_long *)&code); 2361.24Sthorpej if (error) 2371.24Sthorpej goto bad; 2381.1Sscw 2391.1Sscw /* 2401.1Sscw * XXX 2411.1Sscw * Don't do this for sunos_sigreturn, as there's no stored pc 2421.1Sscw * on the stack to skip, the argument follows the syscall 2431.1Sscw * number without a gap. 2441.1Sscw */ 2451.1Sscw if (code != SUNOS_SYS_sigreturn) { 2461.1Sscw frame->f_regs[SP] += sizeof (int); 2471.1Sscw /* 2481.14Stsutsui * remember that we adjusted the SP, 2491.1Sscw * might have to undo this if the system call 2501.1Sscw * returns ERESTART. 2511.1Sscw */ 2521.4Sthorpej l->l_md.md_flags |= MDL_STACKADJ; 2531.1Sscw } else 2541.4Sthorpej l->l_md.md_flags &= ~MDL_STACKADJ; 2551.1Sscw 2561.16Stsutsui params = (char *)frame->f_regs[SP] + sizeof(int); 2571.1Sscw 2581.1Sscw switch (code) { 2591.1Sscw case SUNOS_SYS_syscall: 2601.1Sscw /* 2611.1Sscw * Code is first argument, followed by actual args. 2621.1Sscw */ 2631.24Sthorpej error = ufetch_long((void *)params, (u_long *)&code); 2641.24Sthorpej if (error) 2651.24Sthorpej goto bad; 2661.1Sscw params += sizeof(int); 2671.1Sscw break; 2681.1Sscw default: 2691.1Sscw break; 2701.1Sscw } 2711.1Sscw 2721.1Sscw if (code < 0 || code >= nsys) 2731.1Sscw callp += p->p_emul->e_nosys; /* illegal */ 2741.1Sscw else 2751.1Sscw callp += code; 2761.1Sscw 2771.1Sscw argsize = callp->sy_argsize; 2781.1Sscw if (argsize) { 2791.15Schristos error = copyin(params, (void *)args, argsize); 2801.1Sscw if (error) 2811.1Sscw goto bad; 2821.1Sscw } 2831.1Sscw 2841.23Schristos if ((error = trace_enter(code, callp, args)) != 0) 2851.8Schristos goto out; 2861.1Sscw 2871.1Sscw rval[0] = 0; 2881.1Sscw rval[1] = frame->f_regs[D1]; 2891.19Sad error = sy_call(callp, l, args, rval); 2901.8Schristosout: 2911.1Sscw switch (error) { 2921.1Sscw case 0: 2931.1Sscw /* 2941.1Sscw * Reinitialize proc pointer `p' as it may be different 2951.1Sscw * if this is a child returning from fork syscall. 2961.1Sscw */ 2971.1Sscw p = curproc; 2981.1Sscw frame->f_regs[D0] = rval[0]; 2991.1Sscw frame->f_regs[D1] = rval[1]; 3001.1Sscw frame->f_sr &= ~PSL_C; /* carry bit */ 3011.1Sscw break; 3021.1Sscw case ERESTART: 3031.1Sscw /* 3041.1Sscw * We always enter through a `trap' instruction, which is 2 3051.1Sscw * bytes, so adjust the pc by that amount. 3061.1Sscw */ 3071.1Sscw frame->f_pc = frame->f_pc - 2; 3081.1Sscw break; 3091.1Sscw case EJUSTRETURN: 3101.1Sscw /* nothing to do */ 3111.1Sscw break; 3121.1Sscw default: 3131.1Sscw bad: 3141.1Sscw frame->f_regs[D0] = error; 3151.1Sscw frame->f_sr |= PSL_C; /* carry bit */ 3161.1Sscw break; 3171.1Sscw } 3181.1Sscw 3191.1Sscw /* need new p-value for this */ 3201.4Sthorpej if (l->l_md.md_flags & MDL_STACKADJ) { 3211.4Sthorpej l->l_md.md_flags &= ~MDL_STACKADJ; 3221.1Sscw if (error == ERESTART) 3231.1Sscw frame->f_regs[SP] -= sizeof (int); 3241.1Sscw } 3251.1Sscw 3261.23Schristos trace_exit(code, callp, args, rval, error); 3271.1Sscw} 328