1 /* $NetBSD: trap.c,v 1.122 2010/01/05 13:20:30 mbalmer 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.122 2010/01/05 13:20:30 mbalmer 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/pool.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 #define FAULTCHK(pcb) \ 102 if (pcb->iftrap) { \ 103 frame->pc = (unsigned)pcb->iftrap; \ 104 frame->psl &= ~PSL_FPD; \ 105 frame->r0 = EFAULT;/* for copyin/out */ \ 106 frame->r1 = -1; /* for fetch/store */ \ 107 return; \ 108 } 109 110 111 void 112 trap(struct trapframe *frame) 113 { 114 u_int sig = 0, type = frame->trap, code = 0; 115 u_int rv, addr; 116 bool trapsig = true; 117 const bool usermode = USERMODE_P(frame); 118 struct lwp *l; 119 struct proc *p; 120 struct pcb *pcb; 121 u_quad_t oticks = 0; 122 struct vmspace *vm; 123 struct vm_map *map; 124 vm_prot_t ftype; 125 126 l = curlwp; 127 KASSERT(l != NULL); 128 p = l->l_proc; 129 KASSERT(p != NULL); 130 pcb = lwp_getpcb(l); 131 uvmexp.traps++; 132 if (usermode) { 133 type |= T_USER; 134 oticks = p->p_sticks; 135 pcb->framep = frame; 136 LWP_CACHE_CREDS(l, p); 137 } 138 139 type &= ~(T_WRITE|T_PTEFETCH); 140 141 142 #ifdef TRAPDEBUG 143 if(frame->trap==7) goto fram; 144 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 145 frame->trap, frame->code, frame->pc, frame->psl); 146 fram: 147 #endif 148 switch (type) { 149 150 default: 151 #ifdef DDB 152 kdb_trap(frame); 153 #endif 154 panic("trap: type %x, code %x, pc %x, psl %x", 155 (u_int)frame->trap, (u_int)frame->code, 156 (u_int)frame->pc, (u_int)frame->psl); 157 158 case T_KSPNOTVAL: 159 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", 160 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", 161 mfpr(PR_KSP), (u_int)frame->pc, lwp_getpcb(l), 162 (u_int)frame->fp, (u_int)frame->psl); 163 164 case T_TRANSFLT|T_USER: 165 case T_TRANSFLT: 166 /* 167 * BUG! BUG! BUG! BUG! BUG! 168 * Due to a hardware bug (at in least KA65x CPUs) a double 169 * page table fetch trap will cause a translation fault 170 * even if access in the SPT PTE entry specifies 'no access'. 171 * In for example section 6.4.2 in VAX Architecture 172 * Reference Manual it states that if a page both are invalid 173 * and have no access set, a 'access violation fault' occurs. 174 * Therefore, we must fall through here... 175 */ 176 #ifdef nohwbug 177 panic("translation fault"); 178 #endif 179 180 case T_PTELEN|T_USER: /* Page table length exceeded */ 181 case T_ACCFLT|T_USER: 182 if (frame->code < 0) { /* Check for kernel space */ 183 sig = SIGSEGV; 184 code = SEGV_ACCERR; 185 break; 186 } 187 188 case T_PTELEN: 189 case T_ACCFLT: 190 #ifdef TRAPDEBUG 191 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 192 frame->trap, frame->code, frame->pc, frame->psl); 193 #endif 194 #ifdef DIAGNOSTIC 195 if (p == 0) 196 panic("trap: access fault: addr %lx code %lx", 197 frame->pc, frame->code); 198 if (frame->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(frame->code); 210 if (!usermode && (frame->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 (frame->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)frame->code; 226 l->l_pflag |= LP_SA_PAGEFAULT; 227 } 228 229 rv = uvm_fault(map, addr, ftype); 230 if (rv != 0) { 231 if (!usermode) { 232 FAULTCHK(pcb); 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 int err; 379 ucontext_t *uc = arg; 380 struct lwp *l = curlwp; 381 struct pcb *pcb; 382 383 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 384 #if DIAGNOSTIC 385 if (err) { 386 printf("Error %d from cpu_setmcontext.", err); 387 } 388 #endif 389 pool_put(&lwp_uc_pool, uc); 390 391 /* XXX - profiling spoiled here */ 392 pcb = lwp_getpcb(l); 393 userret(l, pcb->framep, l->l_proc->p_sticks); 394 } 395 396 void 397 upcallret(struct lwp *l) 398 { 399 struct pcb *pcb; 400 401 /* XXX - profiling */ 402 pcb = lwp_getpcb(l); 403 userret(l, pcb->framep, l->l_proc->p_sticks); 404 } 405 406