1 /* $NetBSD: syscall.c,v 1.68 2021/02/01 19:31:34 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2000, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1994-1998 Mark Brinicombe.
34 * Copyright (c) 1994 Brini.
35 * All rights reserved.
36 *
37 * This code is derived from software written for Brini by Mark Brinicombe
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by Mark Brinicombe
50 * for the NetBSD Project.
51 * 4. The name of the company nor the name of the author may be used to
52 * endorse or promote products derived from this software without specific
53 * prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
56 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
57 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
58 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
59 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
60 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * syscall entry handling
68 *
69 * Created : 09/11/94
70 */
71
72 #include <sys/param.h>
73
74 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.68 2021/02/01 19:31:34 skrll Exp $");
75
76 #include <sys/cpu.h>
77 #include <sys/device.h>
78 #include <sys/errno.h>
79 #include <sys/kernel.h>
80 #include <sys/reboot.h>
81 #include <sys/signalvar.h>
82 #include <sys/syscall.h>
83 #include <sys/syscallvar.h>
84 #include <sys/systm.h>
85 #include <sys/ktrace.h>
86
87 #include <uvm/uvm_extern.h>
88
89 #include <machine/frame.h>
90 #include <arm/swi.h>
91 #include <arm/locore.h>
92
93 void
swi_handler(trapframe_t * tf)94 swi_handler(trapframe_t *tf)
95 {
96 lwp_t * const l = curlwp;
97 uint32_t insn;
98
99 /*
100 * Enable interrupts if they were enabled before the exception.
101 * Since all syscalls *should* come from user mode it will always
102 * be safe to enable them, but check anyway.
103 */
104 KASSERT(VALID_PSR(tf->tf_spsr));
105 restore_interrupts(tf->tf_spsr & IF32_bits);
106
107 #ifndef THUMB_CODE
108 /*
109 * Make sure the program counter is correctly aligned so we
110 * don't take an alignment fault trying to read the opcode.
111 */
112 if (__predict_false(((tf->tf_pc - INSN_SIZE) & 3) != 0)) {
113 ksiginfo_t ksi;
114 /* Give the user an illegal instruction signal. */
115 KSI_INIT_TRAP(&ksi);
116 ksi.ksi_signo = SIGILL;
117 ksi.ksi_code = ILL_ILLOPC;
118 ksi.ksi_addr = (uint32_t *)(intptr_t) (tf->tf_pc-INSN_SIZE);
119 #if 0
120 /* maybe one day we'll do emulations */
121 (*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
122 #else
123 trapsignal(l, &ksi);
124 #endif
125 userret(l);
126 return;
127 }
128 #endif
129
130 #ifdef THUMB_CODE
131 if (tf->tf_spsr & PSR_T_bit) {
132 insn = 0xef000000 | SWI_OS_NETBSD | tf->tf_r0;
133 tf->tf_r0 = tf->tf_ip;
134 }
135 else
136 #endif
137 {
138 insn = read_insn(tf->tf_pc - INSN_SIZE, true);
139 }
140
141 KASSERTMSG(tf == lwp_trapframe(l), "tf %p vs %p", tf, lwp_trapframe(l));
142
143 #ifdef CPU_ARM7
144 /*
145 * This code is only needed if we are including support for the ARM7
146 * core. Other CPUs do not need it but it does not hurt.
147 */
148
149 /*
150 * ARM700/ARM710 match sticks and sellotape job ...
151 *
152 * I know this affects GPS/VLSI ARM700/ARM710 + various ARM7500.
153 *
154 * On occasion data aborts are mishandled and end up calling
155 * the swi vector.
156 *
157 * If the instruction that caused the exception is not a SWI
158 * then we hit the bug.
159 */
160 if ((insn & 0x0f000000) != 0x0f000000) {
161 tf->tf_pc -= INSN_SIZE;
162 curcpu()->ci_arm700bugcount.ev_count++;
163 userret(l);
164 return;
165 }
166 #endif /* CPU_ARM7 */
167
168 curcpu()->ci_data.cpu_nsyscall++;
169
170 LWP_CACHE_CREDS(l, l->l_proc);
171 (*l->l_proc->p_md.md_syscall)(tf, l, insn);
172 }
173
174 void syscall(struct trapframe *, lwp_t *, uint32_t);
175
176 void
syscall_intern(struct proc * p)177 syscall_intern(struct proc *p)
178 {
179 p->p_md.md_syscall = syscall;
180 }
181
182 void
syscall(struct trapframe * tf,lwp_t * l,uint32_t insn)183 syscall(struct trapframe *tf, lwp_t *l, uint32_t insn)
184 {
185 struct proc * const p = l->l_proc;
186 const struct sysent *callp;
187 int error;
188 u_int nargs, off = 0;
189 register_t *args;
190 uint64_t copyargs64[sizeof(register_t) *
191 (2+SYS_MAXSYSARGS+1)/sizeof(uint64_t)];
192 register_t *copyargs = (register_t *)copyargs64;
193 register_t rval[2];
194 ksiginfo_t ksi;
195 const uint32_t os_mask = insn & SWI_OS_MASK;
196 uint32_t code = insn & 0x000fffff;
197
198 /* test new official and old unofficial NetBSD ranges */
199 if (__predict_false(os_mask != SWI_OS_NETBSD)
200 && __predict_false(os_mask != 0)) {
201
202 const uint32_t swi = __SHIFTOUT(insn, __BITS(23,0));
203 if (swi == SWI_IMB || swi == SWI_IMBrange) {
204 userret(l);
205 return;
206 }
207
208 /* Undefined so illegal instruction */
209 KSI_INIT_TRAP(&ksi);
210 ksi.ksi_signo = SIGILL;
211 ksi.ksi_code = ILL_ILLTRP;
212 #ifdef THUMB_CODE
213 if (tf->tf_spsr & PSR_T_bit)
214 ksi.ksi_addr = (void *)(tf->tf_pc - THUMB_INSN_SIZE);
215 else
216 #endif
217 ksi.ksi_addr = (void *)(tf->tf_pc - INSN_SIZE);
218 ksi.ksi_trap = insn;
219 trapsignal(l, &ksi);
220 userret(l);
221 return;
222 }
223
224 code &= (SYS_NSYSENT - 1);
225
226 if (__predict_false(code == SYS_syscall)) {
227 off = 1;
228 code = tf->tf_r0;
229 code &= (SYS_NSYSENT - 1);
230 if (__predict_false(code == SYS_syscall)) {
231 error = EINVAL;
232 goto bad;
233 }
234 }
235
236 callp = p->p_emul->e_sysent + code;
237 nargs = callp->sy_narg;
238
239 if ((nargs+off) > 4) {
240 args = copyargs;
241 memcpy(args, &tf->tf_r0+off, (4-off) * sizeof(register_t));
242 error = copyin((void *)tf->tf_usr_sp, args + 4 - off,
243 (nargs - 4 + off) * sizeof(register_t));
244 if (error)
245 goto bad;
246 } else {
247 args = &tf->tf_r0 + off;
248 }
249
250 error = sy_invoke(callp, l, args, rval, code);
251
252 switch (error) {
253 case 0:
254 tf->tf_r0 = rval[0];
255 tf->tf_r1 = rval[1];
256
257 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
258 break;
259
260 case ERESTART:
261 /*
262 * Reconstruct the pc to point at the swi.
263 */
264 #ifdef THUMB_CODE
265 if (tf->tf_spsr & PSR_T_bit)
266 tf->tf_pc -= THUMB_INSN_SIZE;
267 else
268 #endif
269 tf->tf_pc -= INSN_SIZE;
270 break;
271
272 case EJUSTRETURN:
273 /* nothing to do */
274 break;
275
276 default:
277 bad:
278 tf->tf_r0 = error;
279 tf->tf_spsr |= PSR_C_bit; /* carry bit */
280 break;
281 }
282
283 userret(l);
284 }
285
286 void
md_child_return(struct lwp * l)287 md_child_return(struct lwp *l)
288 {
289 struct trapframe * const tf = lwp_trapframe(l);
290
291 tf->tf_r0 = 0;
292 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
293
294 userret(l);
295 }
296
297 /*
298 * Process the tail end of a posix_spawn() for the child.
299 */
300 void
cpu_spawn_return(struct lwp * l)301 cpu_spawn_return(struct lwp *l)
302 {
303
304 userret(l);
305 }
306