1 /* $NetBSD: syscall.c,v 1.69 2023/10/05 19:41:03 ad 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.69 2023/10/05 19:41:03 ad 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 (*l->l_proc->p_md.md_syscall)(tf, l, insn);
171 }
172
173 void syscall(struct trapframe *, lwp_t *, uint32_t);
174
175 void
syscall_intern(struct proc * p)176 syscall_intern(struct proc *p)
177 {
178 p->p_md.md_syscall = syscall;
179 }
180
181 void
syscall(struct trapframe * tf,lwp_t * l,uint32_t insn)182 syscall(struct trapframe *tf, lwp_t *l, uint32_t insn)
183 {
184 struct proc * const p = l->l_proc;
185 const struct sysent *callp;
186 int error;
187 u_int nargs, off = 0;
188 register_t *args;
189 uint64_t copyargs64[sizeof(register_t) *
190 (2+SYS_MAXSYSARGS+1)/sizeof(uint64_t)];
191 register_t *copyargs = (register_t *)copyargs64;
192 register_t rval[2];
193 ksiginfo_t ksi;
194 const uint32_t os_mask = insn & SWI_OS_MASK;
195 uint32_t code = insn & 0x000fffff;
196
197 /* test new official and old unofficial NetBSD ranges */
198 if (__predict_false(os_mask != SWI_OS_NETBSD)
199 && __predict_false(os_mask != 0)) {
200
201 const uint32_t swi = __SHIFTOUT(insn, __BITS(23,0));
202 if (swi == SWI_IMB || swi == SWI_IMBrange) {
203 userret(l);
204 return;
205 }
206
207 /* Undefined so illegal instruction */
208 KSI_INIT_TRAP(&ksi);
209 ksi.ksi_signo = SIGILL;
210 ksi.ksi_code = ILL_ILLTRP;
211 #ifdef THUMB_CODE
212 if (tf->tf_spsr & PSR_T_bit)
213 ksi.ksi_addr = (void *)(tf->tf_pc - THUMB_INSN_SIZE);
214 else
215 #endif
216 ksi.ksi_addr = (void *)(tf->tf_pc - INSN_SIZE);
217 ksi.ksi_trap = insn;
218 trapsignal(l, &ksi);
219 userret(l);
220 return;
221 }
222
223 code &= (SYS_NSYSENT - 1);
224
225 if (__predict_false(code == SYS_syscall)) {
226 off = 1;
227 code = tf->tf_r0;
228 code &= (SYS_NSYSENT - 1);
229 if (__predict_false(code == SYS_syscall)) {
230 error = EINVAL;
231 goto bad;
232 }
233 }
234
235 callp = p->p_emul->e_sysent + code;
236 nargs = callp->sy_narg;
237
238 if ((nargs+off) > 4) {
239 args = copyargs;
240 memcpy(args, &tf->tf_r0+off, (4-off) * sizeof(register_t));
241 error = copyin((void *)tf->tf_usr_sp, args + 4 - off,
242 (nargs - 4 + off) * sizeof(register_t));
243 if (error)
244 goto bad;
245 } else {
246 args = &tf->tf_r0 + off;
247 }
248
249 error = sy_invoke(callp, l, args, rval, code);
250
251 switch (error) {
252 case 0:
253 tf->tf_r0 = rval[0];
254 tf->tf_r1 = rval[1];
255
256 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
257 break;
258
259 case ERESTART:
260 /*
261 * Reconstruct the pc to point at the swi.
262 */
263 #ifdef THUMB_CODE
264 if (tf->tf_spsr & PSR_T_bit)
265 tf->tf_pc -= THUMB_INSN_SIZE;
266 else
267 #endif
268 tf->tf_pc -= INSN_SIZE;
269 break;
270
271 case EJUSTRETURN:
272 /* nothing to do */
273 break;
274
275 default:
276 bad:
277 tf->tf_r0 = error;
278 tf->tf_spsr |= PSR_C_bit; /* carry bit */
279 break;
280 }
281
282 userret(l);
283 }
284
285 void
md_child_return(struct lwp * l)286 md_child_return(struct lwp *l)
287 {
288 struct trapframe * const tf = lwp_trapframe(l);
289
290 tf->tf_r0 = 0;
291 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
292
293 userret(l);
294 }
295
296 /*
297 * Process the tail end of a posix_spawn() for the child.
298 */
299 void
cpu_spawn_return(struct lwp * l)300 cpu_spawn_return(struct lwp *l)
301 {
302
303 userret(l);
304 }
305