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