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