1 /* $NetBSD: trap.c,v 1.128 2011/07/03 02:18:21 matt 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.128 2011/07/03 02:18:21 matt Exp $"); 37 38 #include "opt_ddb.h" 39 #include "opt_multiprocessor.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/cpu.h> 44 #include <sys/exec.h> 45 #include <sys/kauth.h> 46 #include <sys/proc.h> 47 #include <sys/sa.h> 48 #include <sys/savar.h> 49 #include <sys/signalvar.h> 50 51 #include <uvm/uvm_extern.h> 52 53 #include <machine/trap.h> 54 #include <machine/userret.h> 55 56 #ifdef DDB 57 #include <machine/db_machdep.h> 58 #endif 59 #include <vax/vax/db_disasm.h> 60 #include <kern/syscalls.c> 61 #include <sys/ktrace.h> 62 63 #ifdef TRAPDEBUG 64 volatile int faultdebug = 0; 65 #endif 66 67 int cpu_printfataltraps = 0; 68 69 void trap (struct trapframe *); 70 71 const char * const traptypes[]={ 72 "reserved addressing", 73 "privileged instruction", 74 "reserved operand", 75 "breakpoint instruction", 76 "XFC instruction", 77 "system call ", 78 "arithmetic trap", 79 "asynchronous system trap", 80 "page table length fault", 81 "translation violation fault", 82 "trace trap", 83 "compatibility mode fault", 84 "access violation fault", 85 "", 86 "", 87 "KSP invalid", 88 "", 89 "kernel debugger trap" 90 }; 91 int no_traps = 18; 92 93 #define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U) 94 95 void 96 trap(struct trapframe *tf) 97 { 98 u_int sig = 0, type = tf->tf_trap, code = 0; 99 u_int rv, addr; 100 bool trapsig = true; 101 const bool usermode = USERMODE_P(tf); 102 struct lwp * const l = curlwp; 103 struct proc * const p = l->l_proc; 104 struct pcb * const pcb = lwp_getpcb(l); 105 u_quad_t oticks = 0; 106 struct vmspace *vm; 107 struct vm_map *map; 108 vm_prot_t ftype; 109 void *onfault = pcb->pcb_onfault; 110 111 KASSERT(p != NULL); 112 curcpu()->ci_data.cpu_ntrap++; 113 if (usermode) { 114 type |= T_USER; 115 oticks = p->p_sticks; 116 l->l_md.md_utf = tf; 117 LWP_CACHE_CREDS(l, p); 118 } 119 120 type &= ~(T_WRITE|T_PTEFETCH); 121 122 123 #ifdef TRAPDEBUG 124 if(tf->tf_trap==7) goto fram; 125 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 126 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 127 fram: 128 #endif 129 switch (type) { 130 131 default: 132 #ifdef DDB 133 kdb_trap(tf); 134 #endif 135 panic("trap: type %x, code %x, pc %x, psl %x", 136 (u_int)tf->tf_trap, (u_int)tf->tf_code, 137 (u_int)tf->tf_pc, (u_int)tf->tf_psl); 138 139 case T_KSPNOTVAL: 140 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", 141 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", 142 mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, 143 (u_int)tf->tf_fp, (u_int)tf->tf_psl); 144 145 case T_TRANSFLT|T_USER: 146 case T_TRANSFLT: 147 /* 148 * BUG! BUG! BUG! BUG! BUG! 149 * Due to a hardware bug (at in least KA65x CPUs) a double 150 * page table fetch trap will cause a translation fault 151 * even if access in the SPT PTE entry specifies 'no access'. 152 * In for example section 6.4.2 in VAX Architecture 153 * Reference Manual it states that if a page both are invalid 154 * and have no access set, a 'access violation fault' occurs. 155 * Therefore, we must fall through here... 156 */ 157 #ifdef nohwbug 158 panic("translation fault"); 159 #endif 160 161 case T_PTELEN|T_USER: /* Page table length exceeded */ 162 case T_ACCFLT|T_USER: 163 if (tf->tf_code < 0) { /* Check for kernel space */ 164 sig = SIGSEGV; 165 code = SEGV_ACCERR; 166 break; 167 } 168 169 case T_PTELEN: 170 #ifndef MULTIPROCESSOR 171 /* 172 * If we referred to an address beyond the end of the system 173 * page table, it may be due to a failed CAS 174 * restartable-atomic-sequence. If it is, restart it at the 175 * beginning and restart. 176 */ 177 { 178 extern const uint8_t cas32_ras_start[], cas32_ras_end[]; 179 if (tf->tf_code == CASMAGIC 180 && tf->tf_pc >= (uintptr_t) cas32_ras_start 181 && tf->tf_pc < (uintptr_t) cas32_ras_end) { 182 tf->tf_pc = (uintptr_t) cas32_ras_start; 183 trapsig = false; 184 break; 185 } 186 } 187 /* FALLTHROUGH */ 188 #endif 189 case T_ACCFLT: 190 #ifdef TRAPDEBUG 191 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 192 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 193 #endif 194 #ifdef DIAGNOSTIC 195 if (p == 0) 196 panic("trap: access fault: addr %lx code %lx", 197 tf->tf_pc, tf->tf_code); 198 if (tf->tf_psl & PSL_IS) 199 panic("trap: pflt on IS"); 200 #endif 201 202 /* 203 * Page tables are allocated in pmap_enter(). We get 204 * info from below if it is a page table fault, but 205 * UVM may want to map in pages without faults, so 206 * because we must check for PTE pages anyway we don't 207 * bother doing it here. 208 */ 209 addr = trunc_page(tf->tf_code); 210 if (!usermode && (tf->tf_code < 0)) { 211 vm = NULL; 212 map = kernel_map; 213 214 } else { 215 vm = p->p_vmspace; 216 map = &vm->vm_map; 217 } 218 219 if (tf->tf_trap & T_WRITE) 220 ftype = VM_PROT_WRITE; 221 else 222 ftype = VM_PROT_READ; 223 224 if ((usermode) && (l->l_flag & LW_SA)) { 225 l->l_savp->savp_faultaddr = (vaddr_t)tf->tf_code; 226 l->l_pflag |= LP_SA_PAGEFAULT; 227 } 228 229 pcb->pcb_onfault = NULL; 230 rv = uvm_fault(map, addr, ftype); 231 pcb->pcb_onfault = onfault; 232 if (rv != 0) { 233 if (!usermode) { 234 if (onfault) { 235 pcb->pcb_onfault = NULL; 236 tf->tf_pc = (unsigned)onfault; 237 tf->tf_psl &= ~PSL_FPD; 238 tf->tf_r0 = rv; 239 return; 240 } 241 panic("Segv in kernel mode: pc %#lx addr %#lx", 242 tf->tf_pc, tf->tf_code); 243 } 244 code = SEGV_ACCERR; 245 if (rv == ENOMEM) { 246 printf("UVM: pid %d (%s), uid %d killed: " 247 "out of swap\n", 248 p->p_pid, p->p_comm, 249 l->l_cred ? 250 kauth_cred_geteuid(l->l_cred) : -1); 251 sig = SIGKILL; 252 } else { 253 sig = SIGSEGV; 254 if (rv != EACCES) 255 code = SEGV_MAPERR; 256 } 257 } else { 258 trapsig = false; 259 if (map != kernel_map && addr > 0 260 && (void *)addr >= vm->vm_maxsaddr) 261 uvm_grow(p, addr); 262 } 263 if (usermode) { 264 l->l_pflag &= ~LP_SA_PAGEFAULT; 265 } 266 break; 267 268 case T_BPTFLT|T_USER: 269 sig = SIGTRAP; 270 code = TRAP_BRKPT; 271 break; 272 case T_TRCTRAP|T_USER: 273 sig = SIGTRAP; 274 code = TRAP_TRACE; 275 tf->tf_psl &= ~PSL_T; 276 break; 277 278 case T_PRIVINFLT|T_USER: 279 sig = SIGILL; 280 code = ILL_PRVOPC; 281 break; 282 case T_RESADFLT|T_USER: 283 sig = SIGILL; 284 code = ILL_ILLADR; 285 break; 286 case T_RESOPFLT|T_USER: 287 sig = SIGILL; 288 code = ILL_ILLOPC; 289 break; 290 291 case T_XFCFLT|T_USER: 292 sig = SIGEMT; 293 break; 294 295 case T_ARITHFLT|T_USER: 296 sig = SIGFPE; 297 switch (tf->tf_code) { 298 case ATRP_INTOVF: code = FPE_INTOVF; break; 299 case ATRP_INTDIV: code = FPE_INTDIV; break; 300 case ATRP_FLTOVF: code = FPE_FLTOVF; break; 301 case ATRP_FLTDIV: code = FPE_FLTDIV; break; 302 case ATRP_FLTUND: code = FPE_FLTUND; break; 303 case ATRP_DECOVF: code = FPE_INTOVF; break; 304 case ATRP_FLTSUB: code = FPE_FLTSUB; break; 305 case AFLT_FLTDIV: code = FPE_FLTDIV; break; 306 case AFLT_FLTUND: code = FPE_FLTUND; break; 307 case AFLT_FLTOVF: code = FPE_FLTOVF; break; 308 default: code = FPE_FLTINV; break; 309 } 310 break; 311 312 case T_ASTFLT|T_USER: 313 mtpr(AST_NO,PR_ASTLVL); 314 trapsig = false; 315 if (curcpu()->ci_want_resched) 316 preempt(); 317 break; 318 319 #ifdef DDB 320 case T_BPTFLT: /* Kernel breakpoint */ 321 case T_KDBTRAP: 322 case T_KDBTRAP|T_USER: 323 case T_TRCTRAP: 324 kdb_trap(tf); 325 return; 326 #endif 327 } 328 if (trapsig) { 329 ksiginfo_t ksi; 330 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 331 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 332 p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, 333 tf->tf_code, tf->tf_pc, tf->tf_psl); 334 KSI_INIT_TRAP(&ksi); 335 ksi.ksi_signo = sig; 336 ksi.ksi_trap = tf->tf_trap; 337 ksi.ksi_addr = (void *)tf->tf_code; 338 ksi.ksi_code = code; 339 340 /* 341 * Arithmetic exceptions can be of two kinds: 342 * - traps (codes 1..7), where pc points to the 343 * next instruction to execute. 344 * - faults (codes 8..10), where pc points to the 345 * faulting instruction. 346 * In the latter case, we need to advance pc by ourselves 347 * to prevent a signal loop. 348 * 349 * XXX this is gross -- miod 350 */ 351 if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) 352 tf->tf_pc = skip_opcode(tf->tf_pc); 353 354 trapsignal(l, &ksi); 355 } 356 357 if (!usermode) 358 return; 359 360 userret(l, tf, oticks); 361 } 362 363 void 364 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 365 { 366 struct trapframe * const tf = l->l_md.md_utf; 367 368 tf->tf_pc = pack->ep_entry + 2; 369 tf->tf_sp = stack; 370 tf->tf_r6 = stack; /* for ELF */ 371 tf->tf_r7 = 0; /* for ELF */ 372 tf->tf_r8 = 0; /* for ELF */ 373 tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */ 374 } 375 376 377 /* 378 * Start a new LWP 379 */ 380 void 381 startlwp(void *arg) 382 { 383 ucontext_t * const uc = arg; 384 lwp_t * const l = curlwp; 385 int error; 386 387 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 388 KASSERT(error == 0); 389 390 kmem_free(uc, sizeof(ucontext_t)); 391 /* XXX - profiling spoiled here */ 392 userret(l, l->l_md.md_utf, l->l_proc->p_sticks); 393 } 394 395 void 396 upcallret(struct lwp *l) 397 { 398 399 /* XXX - profiling */ 400 userret(l, l->l_md.md_utf, l->l_proc->p_sticks); 401 } 402 403