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