1 /* $NetBSD: syscall.c,v 1.13 2002/11/16 07:40:38 uebayasi 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 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1994-1998 Mark Brinicombe. 41 * Copyright (c) 1994 Brini. 42 * All rights reserved. 43 * 44 * This code is derived from software written for Brini by Mark Brinicombe 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by Mark Brinicombe 57 * for the NetBSD Project. 58 * 4. The name of the company nor the name of the author may be used to 59 * endorse or promote products derived from this software without specific 60 * prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 63 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 64 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 65 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 66 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 67 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 68 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * syscall entry handling 75 * 76 * Created : 09/11/94 77 */ 78 79 #include "opt_ktrace.h" 80 #include "opt_systrace.h" 81 #include "opt_syscall_debug.h" 82 83 #include <sys/param.h> 84 85 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.13 2002/11/16 07:40:38 uebayasi Exp $"); 86 87 #include <sys/device.h> 88 #include <sys/errno.h> 89 #include <sys/kernel.h> 90 #include <sys/reboot.h> 91 #include <sys/signalvar.h> 92 #include <sys/syscall.h> 93 #include <sys/systm.h> 94 #include <sys/user.h> 95 #ifdef KTRACE 96 #include <sys/ktrace.h> 97 #endif 98 #ifdef SYSTRACE 99 #include <sys/systrace.h> 100 #endif 101 102 #include <uvm/uvm_extern.h> 103 104 #include <machine/cpu.h> 105 #include <machine/frame.h> 106 #include <machine/pcb.h> 107 #include <arm/swi.h> 108 109 #ifdef acorn26 110 #include <machine/machdep.h> 111 #endif 112 113 void 114 swi_handler(trapframe_t *frame) 115 { 116 struct proc *p; 117 u_int32_t insn; 118 119 /* 120 * Enable interrupts if they were enabled before the exception. 121 * Since all syscalls *should* come from user mode it will always 122 * be safe to enable them, but check anyway. 123 */ 124 #ifdef acorn26 125 if ((frame->tf_r15 & R15_IRQ_DISABLE) == 0) 126 int_on(); 127 #else 128 if (!(frame->tf_spsr & I32_bit)) 129 enable_interrupts(I32_bit); 130 #endif 131 132 #ifdef acorn26 133 frame->tf_pc += INSN_SIZE; 134 #endif 135 136 /* XXX fuword? */ 137 #ifdef __PROG32 138 insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE); 139 #else 140 insn = *(u_int32_t *)((frame->tf_r15 & R15_PC) - INSN_SIZE); 141 #endif 142 143 p = curproc; 144 p->p_addr->u_pcb.pcb_tf = frame; 145 146 #ifdef CPU_ARM7 147 /* 148 * This code is only needed if we are including support for the ARM7 149 * core. Other CPUs do not need it but it does not hurt. 150 */ 151 152 /* 153 * ARM700/ARM710 match sticks and sellotape job ... 154 * 155 * I know this affects GPS/VLSI ARM700/ARM710 + various ARM7500. 156 * 157 * On occasion data aborts are mishandled and end up calling 158 * the swi vector. 159 * 160 * If the instruction that caused the exception is not a SWI 161 * then we hit the bug. 162 */ 163 if ((insn & 0x0f000000) != 0x0f000000) { 164 frame->tf_pc -= INSN_SIZE; 165 curcpu()->ci_arm700bugcount.ev_count++; 166 userret(p); 167 return; 168 } 169 #endif /* CPU_ARM7 */ 170 171 uvmexp.syscalls++; 172 173 (*(void(*)(struct trapframe *, struct proc *, u_int32_t)) 174 (p->p_emul->e_syscall))(frame, p, insn); 175 } 176 177 #define MAXARGS 8 178 179 /* XXX */ 180 void syscall(struct trapframe *frame, struct proc *p, u_int32_t insn); 181 182 void 183 syscall(struct trapframe *frame, struct proc *p, u_int32_t insn) 184 { 185 const struct sysent *callp; 186 int code, error; 187 u_int nap, nargs; 188 register_t *ap, *args, copyargs[MAXARGS], rval[2]; 189 190 KERNEL_PROC_LOCK(p); 191 192 switch (insn & SWI_OS_MASK) { /* Which OS is the SWI from? */ 193 case SWI_OS_ARM: /* ARM-defined SWIs */ 194 code = insn & 0x00ffffff; 195 switch (code) { 196 case SWI_IMB: 197 case SWI_IMBrange: 198 /* 199 * Do nothing as there is no prefetch unit that needs 200 * flushing 201 */ 202 break; 203 default: 204 /* Undefined so illegal instruction */ 205 trapsignal(p, SIGILL, insn); 206 break; 207 } 208 209 userret(p); 210 return; 211 case 0x000000: /* Old unofficial NetBSD range. */ 212 case SWI_OS_NETBSD: /* New official NetBSD range. */ 213 nap = 4; 214 break; 215 default: 216 /* Undefined so illegal instruction */ 217 trapsignal(p, SIGILL, insn); 218 userret(p); 219 return; 220 } 221 222 code = insn & 0x000fffff; 223 224 ap = &frame->tf_r0; 225 callp = p->p_emul->e_sysent; 226 227 switch (code) { 228 case SYS_syscall: 229 code = *ap++; 230 nap--; 231 break; 232 case SYS___syscall: 233 code = ap[_QUAD_LOWWORD]; 234 ap += 2; 235 nap -= 2; 236 break; 237 } 238 239 code &= (SYS_NSYSENT - 1); 240 callp += code; 241 nargs = callp->sy_argsize / sizeof(register_t); 242 if (nargs <= nap) 243 args = ap; 244 else { 245 KASSERT(nargs <= MAXARGS); 246 memcpy(copyargs, ap, nap * sizeof(register_t)); 247 error = copyin((void *)frame->tf_usr_sp, copyargs + nap, 248 (nargs - nap) * sizeof(register_t)); 249 if (error) 250 goto bad; 251 args = copyargs; 252 } 253 254 if ((error = trace_enter(p, code, code, args, rval)) != 0) 255 goto bad; 256 257 rval[0] = 0; 258 rval[1] = 0; 259 error = (*callp->sy_call)(p, args, rval); 260 261 switch (error) { 262 case 0: 263 frame->tf_r0 = rval[0]; 264 frame->tf_r1 = rval[1]; 265 266 #ifdef __PROG32 267 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ 268 #else 269 frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ 270 #endif 271 break; 272 273 case ERESTART: 274 /* 275 * Reconstruct the pc to point at the swi. 276 */ 277 frame->tf_pc -= INSN_SIZE; 278 break; 279 280 case EJUSTRETURN: 281 /* nothing to do */ 282 break; 283 284 default: 285 bad: 286 frame->tf_r0 = error; 287 #ifdef __PROG32 288 frame->tf_spsr |= PSR_C_bit; /* carry bit */ 289 #else 290 frame->tf_r15 |= R15_FLAG_C; /* carry bit */ 291 #endif 292 break; 293 } 294 295 trace_exit(p, code, args, rval, error); 296 KERNEL_PROC_UNLOCK(p); 297 userret(p); 298 } 299 300 void 301 child_return(arg) 302 void *arg; 303 { 304 struct proc *p = arg; 305 struct trapframe *frame = p->p_addr->u_pcb.pcb_tf; 306 307 frame->tf_r0 = 0; 308 #ifdef __PROG32 309 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ 310 #else 311 frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ 312 #endif 313 314 KERNEL_PROC_UNLOCK(p); 315 userret(p); 316 #ifdef KTRACE 317 if (KTRPOINT(p, KTR_SYSRET)) { 318 KERNEL_PROC_LOCK(p); 319 ktrsysret(p, SYS_fork, 0, 0); 320 KERNEL_PROC_UNLOCK(p); 321 } 322 #endif 323 } 324 325 /* End of syscall.c */ 326