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