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