xref: /netbsd-src/sys/arch/m68k/m68k/sunos_syscall.c (revision 91bfaeb6759937927739ef3693f1c0059f6796f8)
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
sunos_syscall_intern(struct proc * p)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
sunos_syscall_plain(register_t code,struct lwp * l,struct frame * frame)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
sunos_syscall_fancy(register_t code,struct lwp * l,struct frame * frame)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