Home | History | Annotate | Line # | Download | only in m68k
      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 
     92 void	sunos_syscall_intern(struct proc *);
     93 static void sunos_syscall_plain(register_t, struct lwp *, struct frame *);
     94 static void sunos_syscall_fancy(register_t, struct lwp *, struct frame *);
     95 
     96 void
     97 sunos_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 
    106 static void
    107 sunos_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 
    215 static void
    216 sunos_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);
    290 out:
    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