1 /* $NetBSD: syscall.c,v 1.60 2014/08/13 21:41:32 matt 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.60 2014/08/13 21:41:32 matt 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 #ifdef acorn26
94 #include <machine/machdep.h>
95 #endif
96
97 void
swi_handler(trapframe_t * tf)98 swi_handler(trapframe_t *tf)
99 {
100 lwp_t * const l = curlwp;
101 uint32_t insn;
102
103 /*
104 * Enable interrupts if they were enabled before the exception.
105 * Since all syscalls *should* come from user mode it will always
106 * be safe to enable them, but check anyway.
107 */
108 #ifdef acorn26
109 if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0)
110 int_on();
111 #else
112 KASSERT(VALID_R15_PSR(tf->tf_pc, tf->tf_spsr));
113 restore_interrupts(tf->tf_spsr & IF32_bits);
114 #endif
115
116 #ifdef acorn26
117 tf->tf_pc += INSN_SIZE;
118 #endif
119
120 #ifndef THUMB_CODE
121 /*
122 * Make sure the program counter is correctly aligned so we
123 * don't take an alignment fault trying to read the opcode.
124 */
125 if (__predict_false(((tf->tf_pc - INSN_SIZE) & 3) != 0)) {
126 ksiginfo_t ksi;
127 /* Give the user an illegal instruction signal. */
128 KSI_INIT_TRAP(&ksi);
129 ksi.ksi_signo = SIGILL;
130 ksi.ksi_code = ILL_ILLOPC;
131 ksi.ksi_addr = (uint32_t *)(intptr_t) (tf->tf_pc-INSN_SIZE);
132 #if 0
133 /* maybe one day we'll do emulations */
134 (*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
135 #else
136 trapsignal(l, &ksi);
137 #endif
138 userret(l);
139 return;
140 }
141 #endif
142
143 #ifdef THUMB_CODE
144 if (tf->tf_spsr & PSR_T_bit) {
145 insn = 0xef000000 | SWI_OS_NETBSD | tf->tf_r0;
146 tf->tf_r0 = tf->tf_ip;
147 }
148 else
149 #endif
150 {
151 #ifdef __PROG32
152 insn = read_insn(tf->tf_pc - INSN_SIZE, true);
153 #else
154 insn = read_insn((tf->tf_r15 & R15_PC) - INSN_SIZE, true);
155 #endif
156 }
157
158 lwp_settrapframe(l, tf);
159
160 #ifdef CPU_ARM7
161 /*
162 * This code is only needed if we are including support for the ARM7
163 * core. Other CPUs do not need it but it does not hurt.
164 */
165
166 /*
167 * ARM700/ARM710 match sticks and sellotape job ...
168 *
169 * I know this affects GPS/VLSI ARM700/ARM710 + various ARM7500.
170 *
171 * On occasion data aborts are mishandled and end up calling
172 * the swi vector.
173 *
174 * If the instruction that caused the exception is not a SWI
175 * then we hit the bug.
176 */
177 if ((insn & 0x0f000000) != 0x0f000000) {
178 tf->tf_pc -= INSN_SIZE;
179 curcpu()->ci_arm700bugcount.ev_count++;
180 userret(l);
181 return;
182 }
183 #endif /* CPU_ARM7 */
184
185 curcpu()->ci_data.cpu_nsyscall++;
186
187 LWP_CACHE_CREDS(l, l->l_proc);
188 (*l->l_proc->p_md.md_syscall)(tf, l, insn);
189 }
190
191 void syscall(struct trapframe *, lwp_t *, uint32_t);
192
193 void
syscall_intern(struct proc * p)194 syscall_intern(struct proc *p)
195 {
196 p->p_md.md_syscall = syscall;
197 }
198
199 void
syscall(struct trapframe * tf,lwp_t * l,uint32_t insn)200 syscall(struct trapframe *tf, lwp_t *l, uint32_t insn)
201 {
202 struct proc * const p = l->l_proc;
203 const struct sysent *callp;
204 int error;
205 u_int nargs;
206 register_t *args;
207 uint64_t copyargs64[sizeof(register_t)*(2+SYS_MAXSYSARGS+1)/sizeof(uint64_t)];
208 register_t *copyargs = (register_t *)copyargs64;
209 register_t rval[2];
210 ksiginfo_t ksi;
211 const uint32_t os_mask = insn & SWI_OS_MASK;
212 uint32_t code = insn & 0x000fffff;
213
214 /* test new official and old unofficial NetBSD ranges */
215 if (__predict_false(os_mask != SWI_OS_NETBSD)
216 && __predict_false(os_mask != 0)) {
217 if (os_mask == SWI_OS_ARM
218 && (code == SWI_IMB || code == SWI_IMBrange)) {
219 userret(l);
220 return;
221 }
222
223 /* Undefined so illegal instruction */
224 KSI_INIT_TRAP(&ksi);
225 ksi.ksi_signo = SIGILL;
226 ksi.ksi_code = ILL_ILLTRP;
227 #ifdef THUMB_CODE
228 if (tf->tf_spsr & PSR_T_bit)
229 ksi.ksi_addr = (void *)(tf->tf_pc - THUMB_INSN_SIZE);
230 else
231 #endif
232 ksi.ksi_addr = (void *)(tf->tf_pc - INSN_SIZE);
233 ksi.ksi_trap = insn;
234 trapsignal(l, &ksi);
235 userret(l);
236 return;
237 }
238
239 code &= (SYS_NSYSENT - 1);
240 callp = p->p_emul->e_sysent + code;
241 nargs = callp->sy_narg;
242 if (nargs > 4) {
243 args = copyargs;
244 memcpy(args, &tf->tf_r0, 4 * sizeof(register_t));
245 error = copyin((void *)tf->tf_usr_sp, args + 4,
246 (nargs - 4) * sizeof(register_t));
247 if (error)
248 goto bad;
249 } else {
250 args = &tf->tf_r0;
251 }
252
253 error = sy_invoke(callp, l, args, rval, code);
254
255 switch (error) {
256 case 0:
257 tf->tf_r0 = rval[0];
258 tf->tf_r1 = rval[1];
259
260 #ifdef __PROG32
261 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
262 #else
263 tf->tf_r15 &= ~R15_FLAG_C; /* carry bit */
264 #endif
265 break;
266
267 case ERESTART:
268 /*
269 * Reconstruct the pc to point at the swi.
270 */
271 #ifdef THUMB_CODE
272 if (tf->tf_spsr & PSR_T_bit)
273 tf->tf_pc -= THUMB_INSN_SIZE;
274 else
275 #endif
276 tf->tf_pc -= INSN_SIZE;
277 break;
278
279 case EJUSTRETURN:
280 /* nothing to do */
281 break;
282
283 default:
284 bad:
285 tf->tf_r0 = error;
286 #ifdef __PROG32
287 tf->tf_spsr |= PSR_C_bit; /* carry bit */
288 #else
289 tf->tf_r15 |= R15_FLAG_C; /* carry bit */
290 #endif
291 break;
292 }
293
294 userret(l);
295 }
296
297 void
child_return(void * arg)298 child_return(void *arg)
299 {
300 lwp_t * const l = arg;
301 struct trapframe * const tf = lwp_trapframe(l);
302
303 tf->tf_r0 = 0;
304 #ifdef __PROG32
305 tf->tf_spsr &= ~PSR_C_bit; /* carry bit */
306 #else
307 tf->tf_r15 &= ~R15_FLAG_C; /* carry bit */
308 #endif
309
310 userret(l);
311 ktrsysret(SYS_fork, 0, 0);
312 }
313
314 /*
315 * Process the tail end of a posix_spawn() for the child.
316 */
317 void
cpu_spawn_return(struct lwp * l)318 cpu_spawn_return(struct lwp *l)
319 {
320
321 userret(l);
322 }
323
324