xref: /netbsd-src/sys/arch/alpha/alpha/linux_syscall.c (revision 68fa58437753598de948829082f591c269b48777)
1 /* $NetBSD: linux_syscall.c,v 1.34 2023/10/05 19:41:03 ad Exp $ */
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center, and by Charles M. Hannum.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. All advertising materials mentioning features or use of this software
45  *    must display the following acknowledgement:
46  *      This product includes software developed by Christopher G. Demetriou
47  *	for the NetBSD Project.
48  * 4. The name of the author may not be used to endorse or promote products
49  *    derived from this software without specific prior written permission
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
53  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
54  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
55  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62 
63 /*
64  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
65  * All rights reserved.
66  *
67  * Author: Chris G. Demetriou
68  *
69  * Permission to use, copy, modify and distribute this software and
70  * its documentation is hereby granted, provided that both the copyright
71  * notice and this permission notice appear in all copies of the
72  * software, derivative works or modified versions, and any portions
73  * thereof, and that both notices appear in supporting documentation.
74  *
75  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
76  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
77  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
78  *
79  * Carnegie Mellon requests users of this software to return to
80  *
81  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
82  *  School of Computer Science
83  *  Carnegie Mellon University
84  *  Pittsburgh PA 15213-3890
85  *
86  * any improvements or extensions that they make and grant Carnegie the
87  * rights to redistribute these changes.
88  */
89 
90 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
91 
92 __KERNEL_RCSID(0, "$NetBSD: linux_syscall.c,v 1.34 2023/10/05 19:41:03 ad Exp $");
93 
94 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/proc.h>
97 #include <sys/signal.h>
98 #include <sys/syscall.h>
99 #include <sys/syscallvar.h>
100 
101 #include <machine/cpu.h>
102 #include <machine/reg.h>
103 #include <machine/alpha.h>
104 #include <machine/userret.h>
105 
106 #include <compat/linux/common/linux_types.h>
107 #include <compat/linux/common/linux_errno.h>
108 #include <compat/linux/linux_syscall.h>
109 #include <compat/linux/common/linux_signal.h>
110 #include <compat/linux/common/linux_siginfo.h>
111 #include <compat/linux/arch/alpha/linux_machdep.h>
112 
113 void	linux_syscall_intern(struct proc *);
114 void	linux_syscall_plain(struct lwp *, uint64_t, struct trapframe *);
115 void	linux_syscall_fancy(struct lwp *, uint64_t, struct trapframe *);
116 
117 void
linux_syscall_intern(struct proc * p)118 linux_syscall_intern(struct proc *p)
119 {
120 
121 	if (trace_is_enabled(p))
122 		p->p_md.md_syscall = linux_syscall_fancy;
123 	else
124 		p->p_md.md_syscall = linux_syscall_plain;
125 }
126 
127 /*
128  * Process a system call.
129  *
130  * System calls are strange beasts.  They are passed the syscall number
131  * in v0, and the arguments in the registers (as normal).  They return
132  * an error flag in a3 (if a3 != 0 on return, the syscall had an error),
133  * and the return value (if any) in v0.
134  *
135  * The assembly stub takes care of moving the call number into a register
136  * we can get to, and moves all of the argument registers into their places
137  * in the trap frame.  On return, it restores the callee-saved registers,
138  * a3, and v0 from the frame before returning to the user process.
139  */
140 void
linux_syscall_plain(struct lwp * l,uint64_t code,struct trapframe * framep)141 linux_syscall_plain(struct lwp *l, uint64_t code, struct trapframe *framep)
142 {
143 	const struct sysent *callp;
144 	int error;
145 	uint64_t rval[2];
146 	uint64_t *args, copyargs[10];				/* XXX */
147 	u_int hidden, nargs;
148 	struct proc *p = l->l_proc;
149 
150 	curcpu()->ci_data.cpu_nsyscall++;
151 	l->l_md.md_tf = framep;
152 
153 	callp = p->p_emul->e_sysent;
154 
155 	switch (code) {
156 	case LINUX_SYS_syscall:
157 		/* OSF/1 syscall() */
158 		code = framep->tf_regs[FRAME_A0];
159 		hidden = 1;
160 		break;
161 	default:
162 		hidden = 0;
163 		break;
164 	}
165 
166 	code &= (LINUX_SYS_NSYSENT - 1);
167 	callp += code;
168 
169 	nargs = callp->sy_narg + hidden;
170 	switch (nargs) {
171 	default:
172 		error = copyin((void *)alpha_pal_rdusp(), &copyargs[6],
173 		    (nargs - 6) * sizeof(uint64_t));
174 		if (error)
175 			goto bad;
176 	case 6:
177 		copyargs[5] = framep->tf_regs[FRAME_A5];
178 	case 5:
179 		copyargs[4] = framep->tf_regs[FRAME_A4];
180 	case 4:
181 		copyargs[3] = framep->tf_regs[FRAME_A3];
182 		copyargs[2] = framep->tf_regs[FRAME_A2];
183 		copyargs[1] = framep->tf_regs[FRAME_A1];
184 		copyargs[0] = framep->tf_regs[FRAME_A0];
185 		args = copyargs;
186 		break;
187 	case 3:
188 	case 2:
189 	case 1:
190 	case 0:
191 		args = &framep->tf_regs[FRAME_A0];
192 		break;
193 	}
194 	args += hidden;
195 
196 	rval[0] = 0;
197 	rval[1] = 0;
198 	error = sy_call(callp, l, args, rval);
199 
200 	switch (error) {
201 	case 0:
202 		framep->tf_regs[FRAME_V0] = rval[0];
203 		framep->tf_regs[FRAME_A4] = rval[1];
204 		framep->tf_regs[FRAME_A3] = 0;
205 		break;
206 	case ERESTART:
207 		framep->tf_regs[FRAME_PC] -= 4;
208 		break;
209 	case EJUSTRETURN:
210 		break;
211 	default:
212 	bad:
213 		error = native_to_linux_errno[error];
214 		framep->tf_regs[FRAME_V0] = error;
215 		framep->tf_regs[FRAME_A3] = 1;
216 		break;
217 	}
218 
219 	userret(l);
220 }
221 
222 void
linux_syscall_fancy(struct lwp * l,uint64_t code,struct trapframe * framep)223 linux_syscall_fancy(struct lwp *l, uint64_t code, struct trapframe *framep)
224 {
225 	const struct sysent *callp;
226 	int error;
227 	uint64_t rval[2];
228 	uint64_t *args, copyargs[10];
229 	u_int hidden, nargs;
230 	struct proc *p = l->l_proc;
231 
232 	curcpu()->ci_data.cpu_nsyscall++;
233 	l->l_md.md_tf = framep;
234 
235 	callp = p->p_emul->e_sysent;
236 
237 	switch (code) {
238 	case LINUX_SYS_syscall:
239 		/* OSF/1 syscall() */
240 		code = framep->tf_regs[FRAME_A0];
241 		hidden = 1;
242 		break;
243 	default:
244 		hidden = 0;
245 		break;
246 	}
247 
248 	code &= (LINUX_SYS_NSYSENT - 1);
249 	callp += code;
250 
251 	nargs = callp->sy_narg + hidden;
252 	switch (nargs) {
253 	default:
254 		error = copyin((void *)alpha_pal_rdusp(), &copyargs[6],
255 		    (nargs - 6) * sizeof(uint64_t));
256 		if (error) {
257 			args = copyargs;
258 			goto bad;
259 		}
260 	case 6:
261 		copyargs[5] = framep->tf_regs[FRAME_A5];
262 	case 5:
263 		copyargs[4] = framep->tf_regs[FRAME_A4];
264 	case 4:
265 		copyargs[3] = framep->tf_regs[FRAME_A3];
266 		copyargs[2] = framep->tf_regs[FRAME_A2];
267 		copyargs[1] = framep->tf_regs[FRAME_A1];
268 		copyargs[0] = framep->tf_regs[FRAME_A0];
269 		args = copyargs;
270 		break;
271 	case 3:
272 	case 2:
273 	case 1:
274 	case 0:
275 		args = &framep->tf_regs[FRAME_A0];
276 		break;
277 	}
278 	args += hidden;
279 
280 
281 	if ((error = trace_enter(code, callp, args)) != 0)
282 		goto out;
283 
284 	rval[0] = 0;
285 	rval[1] = 0;
286 	error = sy_call(callp, l, args, rval);
287 out:
288 	switch (error) {
289 	case 0:
290 		framep->tf_regs[FRAME_V0] = rval[0];
291 		framep->tf_regs[FRAME_A4] = rval[1];
292 		framep->tf_regs[FRAME_A3] = 0;
293 		break;
294 	case ERESTART:
295 		framep->tf_regs[FRAME_PC] -= 4;
296 		break;
297 	case EJUSTRETURN:
298 		break;
299 	default:
300 	bad:
301 		error = native_to_linux_errno[error];
302 		framep->tf_regs[FRAME_V0] = error;
303 		framep->tf_regs[FRAME_A3] = 1;
304 		break;
305 	}
306 
307 	trace_exit(code, callp, args, rval, error);
308 
309 	userret(l);
310 }
311