1 /* $NetBSD: syscall.c,v 1.9 2002/03/24 15:49:39 bjh21 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_syscall_debug.h" 81 82 #include <sys/param.h> 83 84 __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.9 2002/03/24 15:49:39 bjh21 Exp $"); 85 86 #include <sys/device.h> 87 #include <sys/errno.h> 88 #include <sys/kernel.h> 89 #include <sys/reboot.h> 90 #include <sys/signalvar.h> 91 #include <sys/syscall.h> 92 #include <sys/systm.h> 93 #include <sys/user.h> 94 #ifdef KTRACE 95 #include <sys/ktrace.h> 96 #endif 97 98 #include <uvm/uvm_extern.h> 99 100 #include <machine/cpu.h> 101 #include <machine/frame.h> 102 #include <machine/pcb.h> 103 #include <arm/swi.h> 104 105 #ifdef acorn26 106 #include <machine/machdep.h> 107 #endif 108 109 void 110 swi_handler(trapframe_t *frame) 111 { 112 struct proc *p; 113 u_int32_t insn; 114 115 /* 116 * Enable interrupts if they were enabled before the exception. 117 * Since all syscalls *should* come from user mode it will always 118 * be safe to enable them, but check anyway. 119 */ 120 #ifdef acorn26 121 if ((frame->tf_r15 & R15_IRQ_DISABLE) == 0) 122 int_on(); 123 #else 124 if (!(frame->tf_spsr & I32_bit)) 125 enable_interrupts(I32_bit); 126 #endif 127 128 #ifdef acorn26 129 frame->tf_pc += INSN_SIZE; 130 #endif 131 132 /* XXX fuword? */ 133 #ifdef __PROG32 134 insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE); 135 #else 136 insn = *(u_int32_t *)((frame->tf_r15 & R15_PC) - INSN_SIZE); 137 #endif 138 139 p = curproc; 140 p->p_addr->u_pcb.pcb_tf = frame; 141 142 #ifdef CPU_ARM7 143 /* 144 * This code is only needed if we are including support for the ARM7 145 * core. Other CPUs do not need it but it does not hurt. 146 */ 147 148 /* 149 * ARM700/ARM710 match sticks and sellotape job ... 150 * 151 * I know this affects GPS/VLSI ARM700/ARM710 + various ARM7500. 152 * 153 * On occasion data aborts are mishandled and end up calling 154 * the swi vector. 155 * 156 * If the instruction that caused the exception is not a SWI 157 * then we hit the bug. 158 */ 159 if ((insn & 0x0f000000) != 0x0f000000) { 160 frame->tf_pc -= INSN_SIZE; 161 curcpu()->ci_arm700bugcount.ev_count++; 162 userret(p); 163 return; 164 } 165 #endif /* CPU_ARM7 */ 166 167 uvmexp.syscalls++; 168 169 (*(void(*)(struct trapframe *, struct proc *, u_int32_t)) 170 (p->p_emul->e_syscall))(frame, p, insn); 171 } 172 173 #define MAXARGS 8 174 175 /* XXX */ 176 void syscall(struct trapframe *frame, struct proc *p, u_int32_t insn); 177 178 void 179 syscall(struct trapframe *frame, struct proc *p, u_int32_t insn) 180 { 181 const struct sysent *callp; 182 int code, error; 183 u_int nap, nargs; 184 register_t *ap, *args, copyargs[MAXARGS], rval[2]; 185 186 switch (insn & SWI_OS_MASK) { /* Which OS is the SWI from? */ 187 case SWI_OS_ARM: /* ARM-defined SWIs */ 188 code = insn & 0x00ffffff; 189 switch (code) { 190 case SWI_IMB: 191 case SWI_IMBrange: 192 /* 193 * Do nothing as there is no prefetch unit that needs 194 * flushing 195 */ 196 break; 197 default: 198 /* Undefined so illegal instruction */ 199 trapsignal(p, SIGILL, insn); 200 break; 201 } 202 203 userret(p); 204 return; 205 case 0x000000: /* Old unofficial NetBSD range. */ 206 case SWI_OS_NETBSD: /* New official NetBSD range. */ 207 nap = 4; 208 break; 209 default: 210 /* Undefined so illegal instruction */ 211 trapsignal(p, SIGILL, insn); 212 userret(p); 213 return; 214 } 215 216 code = insn & 0x000fffff; 217 218 ap = &frame->tf_r0; 219 callp = p->p_emul->e_sysent; 220 221 switch (code) { 222 case SYS_syscall: 223 code = *ap++; 224 nap--; 225 break; 226 case SYS___syscall: 227 code = ap[_QUAD_LOWWORD]; 228 ap += 2; 229 nap -= 2; 230 break; 231 } 232 233 code &= (SYS_NSYSENT - 1); 234 callp += code; 235 nargs = callp->sy_argsize / sizeof(register_t); 236 if (nargs <= nap) 237 args = ap; 238 else { 239 KASSERT(nargs <= MAXARGS); 240 memcpy(copyargs, ap, nap * sizeof(register_t)); 241 error = copyin((void *)frame->tf_usr_sp, copyargs + nap, 242 (nargs - nap) * sizeof(register_t)); 243 if (error) 244 goto bad; 245 args = copyargs; 246 } 247 248 #ifdef SYSCALL_DEBUG 249 scdebug_call(p, code, args); 250 #endif 251 #ifdef KTRACE 252 if (KTRPOINT(p, KTR_SYSCALL)) 253 ktrsyscall(p, code, nargs * sizeof(register_t), args); 254 #endif 255 256 rval[0] = 0; 257 rval[1] = 0; 258 error = (*callp->sy_call)(p, args, rval); 259 260 switch (error) { 261 case 0: 262 frame->tf_r0 = rval[0]; 263 frame->tf_r1 = rval[1]; 264 265 #ifdef __PROG32 266 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ 267 #else 268 frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ 269 #endif 270 break; 271 272 case ERESTART: 273 /* 274 * Reconstruct the pc to point at the swi. 275 */ 276 frame->tf_pc -= INSN_SIZE; 277 break; 278 279 case EJUSTRETURN: 280 /* nothing to do */ 281 break; 282 283 default: 284 bad: 285 frame->tf_r0 = error; 286 #ifdef __PROG32 287 frame->tf_spsr |= PSR_C_bit; /* carry bit */ 288 #else 289 frame->tf_r15 |= R15_FLAG_C; /* carry bit */ 290 #endif 291 break; 292 } 293 294 #ifdef SYSCALL_DEBUG 295 scdebug_ret(p, code, error, rval); 296 #endif 297 userret(p); 298 #ifdef KTRACE 299 if (KTRPOINT(p, KTR_SYSRET)) 300 ktrsysret(p, code, error, rval[0]); 301 #endif 302 } 303 304 void 305 child_return(arg) 306 void *arg; 307 { 308 struct proc *p = arg; 309 struct trapframe *frame = p->p_addr->u_pcb.pcb_tf; 310 311 frame->tf_r0 = 0; 312 #ifdef __PROG32 313 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ 314 #else 315 frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ 316 #endif 317 318 userret(p); 319 #ifdef KTRACE 320 if (KTRPOINT(p, KTR_SYSRET)) 321 ktrsysret(p, SYS_fork, 0, 0); 322 #endif 323 } 324 325 /* End of syscall.c */ 326