1 /* $NetBSD: trap.c,v 1.136 2019/11/21 19:24:02 ad 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* All bugs are subject to removal without further notice */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.136 2019/11/21 19:24:02 ad Exp $"); 32 33 #include "opt_ddb.h" 34 #include "opt_multiprocessor.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/cpu.h> 39 #include <sys/exec.h> 40 #include <sys/kauth.h> 41 #include <sys/proc.h> 42 #include <sys/signalvar.h> 43 44 #include <uvm/uvm_extern.h> 45 46 #include <machine/trap.h> 47 #include <machine/userret.h> 48 49 #ifdef DDB 50 #include <machine/db_machdep.h> 51 #endif 52 #include <vax/vax/db_disasm.h> 53 #include <kern/syscalls.c> 54 #include <sys/ktrace.h> 55 56 #ifdef TRAPDEBUG 57 volatile int faultdebug = 0; 58 #endif 59 60 int cpu_printfataltraps = 0; 61 62 void trap (struct trapframe *); 63 64 const char * const traptypes[]={ 65 "reserved addressing", 66 "privileged instruction", 67 "reserved operand", 68 "breakpoint instruction", 69 "XFC instruction", 70 "system call ", 71 "arithmetic trap", 72 "asynchronous system trap", 73 "page table length fault", 74 "translation violation fault", 75 "trace trap", 76 "compatibility mode fault", 77 "access violation fault", 78 "", 79 "", 80 "KSP invalid", 81 "", 82 "kernel debugger trap" 83 }; 84 int no_traps = 18; 85 86 #define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U) 87 88 void 89 trap(struct trapframe *tf) 90 { 91 u_int sig = 0, type = tf->tf_trap, code = 0; 92 u_int rv, addr; 93 bool trapsig = true; 94 const bool usermode = USERMODE_P(tf); 95 struct lwp * const l = curlwp; 96 struct proc * const p = l->l_proc; 97 struct pcb * const pcb = lwp_getpcb(l); 98 u_quad_t oticks = 0; 99 struct vmspace *vm; 100 struct vm_map *map; 101 vm_prot_t ftype; 102 void *onfault = pcb->pcb_onfault; 103 104 KASSERT(p != NULL); 105 curcpu()->ci_data.cpu_ntrap++; 106 if (usermode) { 107 type |= T_USER; 108 oticks = p->p_sticks; 109 l->l_md.md_utf = tf; 110 LWP_CACHE_CREDS(l, p); 111 } 112 113 type &= ~(T_WRITE|T_PTEFETCH); 114 115 116 #ifdef TRAPDEBUG 117 if(tf->tf_trap==7) goto fram; 118 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 119 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 120 fram: 121 #endif 122 switch (type) { 123 124 default: 125 #ifdef DDB 126 kdb_trap(tf); 127 #endif 128 panic("trap: type %x, code %x, pc %x, psl %x", 129 (u_int)tf->tf_trap, (u_int)tf->tf_code, 130 (u_int)tf->tf_pc, (u_int)tf->tf_psl); 131 132 case T_KSPNOTVAL: 133 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", 134 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", 135 mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, 136 (u_int)tf->tf_fp, (u_int)tf->tf_psl); 137 138 case T_TRANSFLT|T_USER: 139 case T_TRANSFLT: 140 /* 141 * BUG! BUG! BUG! BUG! BUG! 142 * Due to a hardware bug (at in least KA65x CPUs) a double 143 * page table fetch trap will cause a translation fault 144 * even if access in the SPT PTE entry specifies 'no access'. 145 * In for example section 6.4.2 in VAX Architecture 146 * Reference Manual it states that if a page both are invalid 147 * and have no access set, a 'access violation fault' occurs. 148 * Therefore, we must fall through here... 149 */ 150 #ifdef nohwbug 151 panic("translation fault"); 152 #endif 153 154 case T_PTELEN|T_USER: /* Page table length exceeded */ 155 case T_ACCFLT|T_USER: 156 if (tf->tf_code < 0) { /* Check for kernel space */ 157 sig = SIGSEGV; 158 code = SEGV_ACCERR; 159 break; 160 } 161 162 case T_PTELEN: 163 #ifndef MULTIPROCESSOR 164 /* 165 * If we referred to an address beyond the end of the system 166 * page table, it may be due to a failed CAS 167 * restartable-atomic-sequence. If it is, restart it at the 168 * beginning and restart. 169 */ 170 { 171 extern const uint8_t cas32_ras_start[], cas32_ras_end[]; 172 if (tf->tf_code == CASMAGIC 173 && tf->tf_pc >= (uintptr_t) cas32_ras_start 174 && tf->tf_pc < (uintptr_t) cas32_ras_end) { 175 tf->tf_pc = (uintptr_t) cas32_ras_start; 176 trapsig = false; 177 break; 178 } 179 } 180 /* FALLTHROUGH */ 181 #endif 182 case T_ACCFLT: 183 #ifdef TRAPDEBUG 184 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 185 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 186 #endif 187 #ifdef DIAGNOSTIC 188 if (p == 0) 189 panic("trap: access fault: addr %lx code %lx", 190 tf->tf_pc, tf->tf_code); 191 if (tf->tf_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(tf->tf_code); 203 if (!usermode && (tf->tf_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 (tf->tf_trap & T_WRITE) 213 ftype = VM_PROT_WRITE; 214 else 215 ftype = VM_PROT_READ; 216 217 pcb->pcb_onfault = NULL; 218 rv = uvm_fault(map, addr, ftype); 219 pcb->pcb_onfault = onfault; 220 if (rv != 0) { 221 if (!usermode) { 222 if (onfault) { 223 pcb->pcb_onfault = NULL; 224 tf->tf_pc = (unsigned)onfault; 225 tf->tf_psl &= ~PSL_FPD; 226 tf->tf_r0 = rv; 227 return; 228 } 229 printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ", 230 tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3); 231 printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", 232 tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7); 233 printf( 234 "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", 235 tf->tf_r8, tf->tf_r9, tf->tf_r10, 236 tf->tf_r11); 237 printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n", 238 tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc); 239 panic("SEGV in kernel mode: pc %#lx addr %#lx", 240 tf->tf_pc, tf->tf_code); 241 } 242 switch (rv) { 243 case ENOMEM: 244 printf("UVM: pid %d (%s), uid %d killed: " 245 "out of swap\n", 246 p->p_pid, p->p_comm, 247 l->l_cred ? 248 kauth_cred_geteuid(l->l_cred) : -1); 249 sig = SIGKILL; 250 code = SI_NOINFO; 251 break; 252 case EINVAL: 253 code = BUS_ADRERR; 254 sig = SIGBUS; 255 break; 256 case EACCES: 257 code = SEGV_ACCERR; 258 sig = SIGSEGV; 259 break; 260 default: 261 code = SEGV_MAPERR; 262 sig = SIGSEGV; 263 break; 264 } 265 } else { 266 trapsig = false; 267 if (map != kernel_map && addr > 0 268 && (void *)addr >= vm->vm_maxsaddr) 269 uvm_grow(p, addr); 270 } 271 break; 272 273 case T_BPTFLT|T_USER: 274 sig = SIGTRAP; 275 code = TRAP_BRKPT; 276 break; 277 case T_TRCTRAP|T_USER: 278 sig = SIGTRAP; 279 code = TRAP_TRACE; 280 tf->tf_psl &= ~PSL_T; 281 break; 282 283 case T_PRIVINFLT|T_USER: 284 sig = SIGILL; 285 code = ILL_PRVOPC; 286 break; 287 case T_RESADFLT|T_USER: 288 sig = SIGILL; 289 code = ILL_ILLADR; 290 break; 291 case T_RESOPFLT|T_USER: 292 sig = SIGILL; 293 code = ILL_ILLOPC; 294 break; 295 296 case T_XFCFLT|T_USER: 297 sig = SIGEMT; 298 break; 299 300 case T_ARITHFLT|T_USER: 301 sig = SIGFPE; 302 switch (tf->tf_code) { 303 case ATRP_INTOVF: code = FPE_INTOVF; break; 304 case ATRP_INTDIV: code = FPE_INTDIV; break; 305 case ATRP_FLTOVF: code = FPE_FLTOVF; break; 306 case ATRP_FLTDIV: code = FPE_FLTDIV; break; 307 case ATRP_FLTUND: code = FPE_FLTUND; break; 308 case ATRP_DECOVF: code = FPE_INTOVF; break; 309 case ATRP_FLTSUB: code = FPE_FLTSUB; break; 310 case AFLT_FLTDIV: code = FPE_FLTDIV; break; 311 case AFLT_FLTUND: code = FPE_FLTUND; break; 312 case AFLT_FLTOVF: code = FPE_FLTOVF; break; 313 default: code = FPE_FLTINV; break; 314 } 315 break; 316 317 case T_ASTFLT|T_USER: 318 mtpr(AST_NO,PR_ASTLVL); 319 trapsig = false; 320 break; 321 322 #ifdef DDB 323 case T_BPTFLT: /* Kernel breakpoint */ 324 case T_KDBTRAP: 325 case T_KDBTRAP|T_USER: 326 case T_TRCTRAP: 327 kdb_trap(tf); 328 return; 329 #endif 330 } 331 if (trapsig) { 332 ksiginfo_t ksi; 333 if ((sig == SIGSEGV || sig == SIGILL) 334 && cpu_printfataltraps 335 && (p->p_slflag & PSL_TRACED) == 0 336 && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) 337 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 338 p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, 339 tf->tf_code, tf->tf_pc, tf->tf_psl); 340 KSI_INIT_TRAP(&ksi); 341 ksi.ksi_signo = sig; 342 ksi.ksi_trap = tf->tf_trap; 343 ksi.ksi_addr = (void *)tf->tf_code; 344 ksi.ksi_code = code; 345 346 /* 347 * Arithmetic exceptions can be of two kinds: 348 * - traps (codes 1..7), where pc points to the 349 * next instruction to execute. 350 * - faults (codes 8..10), where pc points to the 351 * faulting instruction. 352 * In the latter case, we need to advance pc by ourselves 353 * to prevent a signal loop. 354 * 355 * XXX this is gross -- miod 356 */ 357 if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) 358 tf->tf_pc = skip_opcode(tf->tf_pc); 359 360 trapsignal(l, &ksi); 361 } 362 363 if (!usermode) 364 return; 365 366 userret(l, tf, oticks); 367 } 368 369 void 370 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 371 { 372 struct trapframe * const tf = l->l_md.md_utf; 373 374 tf->tf_pc = pack->ep_entry + 2; 375 tf->tf_sp = stack; 376 tf->tf_r6 = stack; /* for ELF */ 377 tf->tf_r7 = 0; /* for ELF */ 378 tf->tf_r8 = 0; /* for ELF */ 379 tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */ 380 } 381 382 383 /* 384 * Start a new LWP 385 */ 386 void 387 startlwp(void *arg) 388 { 389 ucontext_t * const uc = arg; 390 lwp_t * const l = curlwp; 391 int error __diagused; 392 393 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 394 KASSERT(error == 0); 395 396 kmem_free(uc, sizeof(ucontext_t)); 397 /* XXX - profiling spoiled here */ 398 userret(l, l->l_md.md_utf, l->l_proc->p_sticks); 399 } 400