1 /* $NetBSD: trap.c,v 1.110 2007/10/17 19:58:00 garbled Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Ludd, University of Lule}, Sweden. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed at Ludd, University of Lule}. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* All bugs are subject to removal without further notice */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.110 2007/10/17 19:58:00 garbled Exp $"); 37 38 #include "opt_ddb.h" 39 #include "opt_multiprocessor.h" 40 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/proc.h> 44 #include <sys/user.h> 45 #include <sys/syscall.h> 46 #include <sys/systm.h> 47 #include <sys/signalvar.h> 48 #include <sys/exec.h> 49 #include <sys/pool.h> 50 #include <sys/kauth.h> 51 52 #include <uvm/uvm_extern.h> 53 54 #include <machine/mtpr.h> 55 #include <machine/pte.h> 56 #include <machine/pcb.h> 57 #include <machine/trap.h> 58 #include <machine/pmap.h> 59 #include <machine/cpu.h> 60 #include <machine/userret.h> 61 62 #ifdef DDB 63 #include <machine/db_machdep.h> 64 #endif 65 #include <kern/syscalls.c> 66 #include <sys/ktrace.h> 67 68 #ifdef TRAPDEBUG 69 volatile int faultdebug = 0; 70 #endif 71 72 int cpu_printfataltraps = 0; 73 74 void trap (struct trapframe *); 75 76 const char * const traptypes[]={ 77 "reserved addressing", 78 "privileged instruction", 79 "reserved operand", 80 "breakpoint instruction", 81 "XFC instruction", 82 "system call ", 83 "arithmetic trap", 84 "asynchronous system trap", 85 "page table length fault", 86 "translation violation fault", 87 "trace trap", 88 "compatibility mode fault", 89 "access violation fault", 90 "", 91 "", 92 "KSP invalid", 93 "", 94 "kernel debugger trap" 95 }; 96 int no_traps = 18; 97 98 #define USERMODE(framep) ((((framep)->psl) & (PSL_U)) == PSL_U) 99 #define FAULTCHK \ 100 if (l->l_addr->u_pcb.iftrap) { \ 101 frame->pc = (unsigned)l->l_addr->u_pcb.iftrap; \ 102 frame->psl &= ~PSL_FPD; \ 103 frame->r0 = EFAULT;/* for copyin/out */ \ 104 frame->r1 = -1; /* for fetch/store */ \ 105 return; \ 106 } 107 108 109 void 110 trap(struct trapframe *frame) 111 { 112 u_int sig = 0, type = frame->trap, trapsig = 1, code = 0; 113 u_int rv, addr, umode; 114 struct lwp *l; 115 struct proc *p = NULL; 116 u_quad_t oticks = 0; 117 struct vmspace *vm; 118 struct vm_map *map; 119 vm_prot_t ftype; 120 121 if ((l = curlwp) != NULL) 122 p = l->l_proc; 123 uvmexp.traps++; 124 if ((umode = USERMODE(frame))) { 125 type |= T_USER; 126 oticks = p->p_sticks; 127 l->l_addr->u_pcb.framep = frame; 128 LWP_CACHE_CREDS(l, p); 129 } 130 131 type&=~(T_WRITE|T_PTEFETCH); 132 133 134 #ifdef TRAPDEBUG 135 if(frame->trap==7) goto fram; 136 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 137 frame->trap, frame->code, frame->pc, frame->psl); 138 fram: 139 #endif 140 switch(type){ 141 142 default: 143 #ifdef DDB 144 kdb_trap(frame); 145 #endif 146 printf("Trap: type %x, code %x, pc %x, psl %x\n", 147 (u_int)frame->trap, (u_int)frame->code, 148 (u_int)frame->pc, (u_int)frame->psl); 149 panic("trap"); 150 151 case T_KSPNOTVAL: 152 panic("kernel stack invalid"); 153 154 case T_TRANSFLT|T_USER: 155 case T_TRANSFLT: 156 /* 157 * BUG! BUG! BUG! BUG! BUG! 158 * Due to a hardware bug (at in least KA65x CPUs) a double 159 * page table fetch trap will cause a translation fault 160 * even if access in the SPT PTE entry specifies 'no access'. 161 * In for example section 6.4.2 in VAX Architecture 162 * Reference Manual it states that if a page both are invalid 163 * and have no access set, a 'access violation fault' occurs. 164 * Therefore, we must fall through here... 165 */ 166 #ifdef nohwbug 167 panic("translation fault"); 168 #endif 169 170 case T_PTELEN|T_USER: /* Page table length exceeded */ 171 case T_ACCFLT|T_USER: 172 if (frame->code < 0) { /* Check for kernel space */ 173 sig = SIGSEGV; 174 code = SEGV_ACCERR; 175 break; 176 } 177 178 case T_PTELEN: 179 case T_ACCFLT: 180 #ifdef TRAPDEBUG 181 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 182 frame->trap, frame->code, frame->pc, frame->psl); 183 #endif 184 #ifdef DIAGNOSTIC 185 if (p == 0) 186 panic("trap: access fault: addr %lx code %lx", 187 frame->pc, frame->code); 188 if (frame->psl & PSL_IS) 189 panic("trap: pflt on IS"); 190 #endif 191 192 /* 193 * Page tables are allocated in pmap_enter(). We get 194 * info from below if it is a page table fault, but 195 * UVM may want to map in pages without faults, so 196 * because we must check for PTE pages anyway we don't 197 * bother doing it here. 198 */ 199 addr = trunc_page(frame->code); 200 if ((umode == 0) && (frame->code < 0)) { 201 vm = NULL; 202 map = kernel_map; 203 } else { 204 vm = p->p_vmspace; 205 map = &vm->vm_map; 206 } 207 208 if (frame->trap & T_WRITE) 209 ftype = VM_PROT_WRITE; 210 else 211 ftype = VM_PROT_READ; 212 213 if (umode) 214 KERNEL_LOCK(1, l); 215 else 216 KERNEL_LOCK(1, NULL); 217 218 rv = uvm_fault(map, addr, ftype); 219 if (rv != 0) { 220 if (umode == 0) { 221 KERNEL_UNLOCK_ONE(NULL); 222 FAULTCHK; 223 panic("Segv in kernel mode: pc %x addr %x", 224 (u_int)frame->pc, (u_int)frame->code); 225 } 226 code = SEGV_ACCERR; 227 if (rv == ENOMEM) { 228 printf("UVM: pid %d (%s), uid %d killed: " 229 "out of swap\n", 230 p->p_pid, p->p_comm, 231 l->l_cred ? 232 kauth_cred_geteuid(l->l_cred) : -1); 233 sig = SIGKILL; 234 } else { 235 sig = SIGSEGV; 236 if (rv != EACCES) 237 code = SEGV_MAPERR; 238 } 239 } else { 240 trapsig = 0; 241 if (map != kernel_map && (void *)addr >= vm->vm_maxsaddr) 242 uvm_grow(p, addr); 243 } 244 if (umode) 245 KERNEL_UNLOCK_LAST(l); 246 else 247 KERNEL_UNLOCK_ONE(NULL); 248 break; 249 250 case T_BPTFLT|T_USER: 251 sig = SIGTRAP; 252 code = TRAP_BRKPT; 253 break; 254 case T_TRCTRAP|T_USER: 255 sig = SIGTRAP; 256 code = TRAP_TRACE; 257 frame->psl &= ~PSL_T; 258 break; 259 260 case T_PRIVINFLT|T_USER: 261 sig = SIGILL; 262 code = ILL_PRVOPC; 263 break; 264 case T_RESADFLT|T_USER: 265 sig = SIGILL; 266 code = ILL_ILLADR; 267 break; 268 case T_RESOPFLT|T_USER: 269 sig = SIGILL; 270 code = ILL_ILLOPC; 271 break; 272 273 case T_XFCFLT|T_USER: 274 sig = SIGEMT; 275 break; 276 277 case T_ARITHFLT|T_USER: 278 sig = SIGFPE; 279 break; 280 281 case T_ASTFLT|T_USER: 282 mtpr(AST_NO,PR_ASTLVL); 283 trapsig = 0; 284 break; 285 286 #ifdef DDB 287 case T_BPTFLT: /* Kernel breakpoint */ 288 case T_KDBTRAP: 289 case T_KDBTRAP|T_USER: 290 case T_TRCTRAP: 291 kdb_trap(frame); 292 return; 293 #endif 294 } 295 if (trapsig) { 296 ksiginfo_t ksi; 297 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 298 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 299 p->p_pid, l->l_lid, p->p_comm, sig, frame->trap, 300 frame->code, frame->pc, frame->psl); 301 KERNEL_LOCK(1, l); 302 KSI_INIT_TRAP(&ksi); 303 ksi.ksi_signo = sig; 304 ksi.ksi_trap = frame->trap; 305 ksi.ksi_addr = (void *)frame->code; 306 ksi.ksi_code = code; 307 trapsignal(l, &ksi); 308 KERNEL_UNLOCK_LAST(l); 309 } 310 311 if (umode == 0) 312 return; 313 314 userret(l, frame, oticks); 315 } 316 317 void 318 setregs(struct lwp *l, struct exec_package *pack, u_long stack) 319 { 320 struct trapframe *exptr; 321 322 exptr = l->l_addr->u_pcb.framep; 323 exptr->pc = pack->ep_entry + 2; 324 exptr->sp = stack; 325 exptr->r6 = stack; /* for ELF */ 326 exptr->r7 = 0; /* for ELF */ 327 exptr->r8 = 0; /* for ELF */ 328 exptr->r9 = (u_long) l->l_proc->p_psstr; /* for ELF */ 329 } 330 331 332 /* 333 * Start a new LWP 334 */ 335 void 336 startlwp(arg) 337 void *arg; 338 { 339 int err; 340 ucontext_t *uc = arg; 341 struct lwp *l = curlwp; 342 343 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 344 #if DIAGNOSTIC 345 if (err) { 346 printf("Error %d from cpu_setmcontext.", err); 347 } 348 #endif 349 pool_put(&lwp_uc_pool, uc); 350 351 /* XXX - profiling spoiled here */ 352 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 353 } 354