1 /* $NetBSD: trap.c,v 1.23 2013/08/23 06:19:46 matt Exp $ */ 2 /*- 3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects 8 * Agency and which was developed by Matt Thomas of 3am Software Foundry. 9 * 10 * This material is based upon work supported by the Defense Advanced Research 11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under 12 * Contract No. N66001-09-C-2073. 13 * Approved for Public Release, Distribution Unlimited 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include "opt_ddb.h" 38 39 #include <sys/cdefs.h> 40 41 __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.23 2013/08/23 06:19:46 matt Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/siginfo.h> 46 #include <sys/lwp.h> 47 #include <sys/proc.h> 48 #include <sys/cpu.h> 49 #include <sys/kauth.h> 50 #include <sys/ras.h> 51 52 #include <uvm/uvm_extern.h> 53 54 #include <powerpc/pcb.h> 55 #include <powerpc/userret.h> 56 #include <powerpc/psl.h> 57 #include <powerpc/instr.h> 58 #include <powerpc/altivec.h> /* use same interface for SPE */ 59 60 #include <powerpc/spr.h> 61 #include <powerpc/booke/spr.h> 62 #include <powerpc/booke/cpuvar.h> 63 64 #include <powerpc/fpu/fpu_extern.h> 65 66 #include <powerpc/db_machdep.h> 67 #include <ddb/db_interface.h> 68 69 #include <powerpc/trap.h> 70 #include <powerpc/booke/trap.h> 71 #include <powerpc/booke/pte.h> 72 73 void trap(enum ppc_booke_exceptions, struct trapframe *); 74 75 static const char trap_names[][8] = { 76 [T_CRITIAL_INPUT] = "CRIT", 77 [T_EXTERNAL_INPUT] = "EXT", 78 [T_DECREMENTER] = "DECR", 79 [T_FIXED_INTERVAL] = "FIT", 80 [T_WATCHDOG] = "WDOG", 81 [T_SYSTEM_CALL] = "SC", 82 [T_MACHINE_CHECK] = "MCHK", 83 [T_DSI] = "DSI", 84 [T_ISI] = "ISI", 85 [T_ALIGNMENT] = "ALN", 86 [T_PROGRAM] = "PGM", 87 [T_FP_UNAVAILABLE] = "FP", 88 [T_AP_UNAVAILABLE] = "AP", 89 [T_DATA_TLB_ERROR] = "DTLB", 90 [T_INSTRUCTION_TLB_ERROR] = "ITLB", 91 [T_DEBUG] = "DEBUG", 92 [T_SPE_UNAVAILABLE] = "SPE", 93 [T_EMBEDDED_FP_DATA] = "FPDATA", 94 [T_EMBEDDED_FP_ROUND] = "FPROUND", 95 [T_EMBEDDED_PERF_MONITOR] = "PERFMON", 96 [T_AST] = "AST", 97 }; 98 99 static inline bool 100 usertrap_p(struct trapframe *tf) 101 { 102 return (tf->tf_srr1 & PSL_PR) != 0; 103 } 104 105 static int 106 mchk_exception(struct trapframe *tf, ksiginfo_t *ksi) 107 { 108 const bool usertrap = usertrap_p(tf); 109 const vaddr_t faultva = tf->tf_mcar; 110 struct cpu_info * const ci = curcpu(); 111 int rv = EFAULT; 112 113 if (usertrap) 114 ci->ci_ev_umchk.ev_count++; 115 116 if (rv != 0 && usertrap) { 117 KSI_INIT_TRAP(ksi); 118 ksi->ksi_signo = SIGSEGV; 119 ksi->ksi_trap = EXC_DSI; 120 ksi->ksi_code = SEGV_ACCERR; 121 ksi->ksi_addr = (void *)faultva; 122 } 123 124 return rv; 125 } 126 127 static inline vm_prot_t 128 get_faulttype(const struct trapframe * const tf) 129 { 130 return VM_PROT_READ | (tf->tf_esr & ESR_ST ? VM_PROT_WRITE : 0); 131 } 132 133 static inline struct vm_map * 134 get_faultmap(const struct trapframe * const tf, register_t psl_mask) 135 { 136 return (tf->tf_srr1 & psl_mask) 137 ? &curlwp->l_proc->p_vmspace->vm_map 138 : kernel_map; 139 } 140 141 /* 142 * We could use pmap_pte_lookup but this slightly faster since we already 143 * the segtab pointers in cpu_info. 144 */ 145 static inline pt_entry_t * 146 trap_pte_lookup(struct trapframe *tf, vaddr_t va, register_t psl_mask) 147 { 148 pmap_segtab_t ** const stps = &curcpu()->ci_pmap_kern_segtab; 149 pmap_segtab_t * const stp = stps[(tf->tf_srr1 / psl_mask) & 1]; 150 if (__predict_false(stp == NULL)) 151 return NULL; 152 pt_entry_t * const ptep = stp->seg_tab[va >> SEGSHIFT]; 153 if (__predict_false(ptep == NULL)) 154 return NULL; 155 return ptep + ((va & SEGOFSET) >> PAGE_SHIFT); 156 } 157 158 static int 159 pagefault(struct vm_map *map, vaddr_t va, vm_prot_t ftype, bool usertrap) 160 { 161 struct lwp * const l = curlwp; 162 int rv; 163 164 // printf("%s(%p,%#lx,%u,%u)\n", __func__, map, va, ftype, usertrap); 165 166 if (usertrap) { 167 rv = uvm_fault(map, trunc_page(va), ftype); 168 if (rv == 0) 169 uvm_grow(l->l_proc, trunc_page(va)); 170 if (rv == EACCES) 171 rv = EFAULT; 172 } else { 173 if (cpu_intr_p()) 174 return EFAULT; 175 176 struct pcb * const pcb = lwp_getpcb(l); 177 struct faultbuf * const fb = pcb->pcb_onfault; 178 pcb->pcb_onfault = NULL; 179 rv = uvm_fault(map, trunc_page(va), ftype); 180 pcb->pcb_onfault = fb; 181 if (map != kernel_map) { 182 if (rv == 0) 183 uvm_grow(l->l_proc, trunc_page(va)); 184 } 185 if (rv == EACCES) 186 rv = EFAULT; 187 } 188 return rv; 189 } 190 191 static int 192 dsi_exception(struct trapframe *tf, ksiginfo_t *ksi) 193 { 194 const vaddr_t faultva = tf->tf_dear; 195 const vm_prot_t ftype = get_faulttype(tf); 196 struct vm_map * const faultmap = get_faultmap(tf, PSL_DS); 197 const bool usertrap = usertrap_p(tf); 198 199 kpreempt_disable(); 200 struct cpu_info * const ci = curcpu(); 201 202 if (usertrap) 203 ci->ci_ev_udsi.ev_count++; 204 else 205 ci->ci_ev_kdsi.ev_count++; 206 207 /* 208 * If we had a TLB entry (which we must have had to get this exception), 209 * we certainly have a PTE. 210 */ 211 pt_entry_t * const ptep = trap_pte_lookup(tf, trunc_page(faultva), 212 PSL_DS); 213 KASSERT(ptep != NULL); 214 pt_entry_t pte = *ptep; 215 216 if ((ftype & VM_PROT_WRITE) 217 && ((pte & (PTE_xW|PTE_UNMODIFIED)) == (PTE_xW|PTE_UNMODIFIED))) { 218 const paddr_t pa = pte_to_paddr(pte); 219 struct vm_page * const pg = PHYS_TO_VM_PAGE(pa); 220 KASSERT(pg); 221 struct vm_page_md * const mdpg = VM_PAGE_TO_MD(pg); 222 223 if (!VM_PAGEMD_MODIFIED_P(mdpg)) { 224 pmap_page_set_attributes(mdpg, VM_PAGEMD_MODIFIED); 225 } 226 pte &= ~PTE_UNMODIFIED; 227 *ptep = pte; 228 pmap_tlb_update_addr(faultmap->pmap, trunc_page(faultva), 229 pte, 0); 230 kpreempt_enable(); 231 return 0; 232 } 233 kpreempt_enable(); 234 235 int rv = pagefault(faultmap, faultva, ftype, usertrap); 236 237 /* 238 * We can't get a MAPERR here since that's a different exception. 239 */ 240 if (__predict_false(rv != 0 && usertrap)) { 241 ci->ci_ev_udsi_fatal.ev_count++; 242 KSI_INIT_TRAP(ksi); 243 ksi->ksi_signo = SIGSEGV; 244 ksi->ksi_trap = EXC_DSI; 245 ksi->ksi_code = SEGV_ACCERR; 246 ksi->ksi_addr = (void *)faultva; 247 } 248 return rv; 249 } 250 251 static int 252 isi_exception(struct trapframe *tf, ksiginfo_t *ksi) 253 { 254 const vaddr_t faultva = trunc_page(tf->tf_srr0); 255 struct vm_map * const faultmap = get_faultmap(tf, PSL_IS); 256 const bool usertrap = usertrap_p(tf); 257 258 kpreempt_disable(); 259 struct cpu_info * const ci = curcpu(); 260 261 if (usertrap) 262 ci->ci_ev_isi.ev_count++; 263 else 264 ci->ci_ev_kisi.ev_count++; 265 266 /* 267 * If we had a TLB entry (which we must have had to get this exception), 268 * we certainly have a PTE. 269 */ 270 pt_entry_t * const ptep = trap_pte_lookup(tf, trunc_page(faultva), 271 PSL_IS); 272 if (ptep == NULL) 273 dump_trapframe(tf, NULL); 274 KASSERT(ptep != NULL); 275 pt_entry_t pte = *ptep; 276 277 UVMHIST_FUNC(__func__); UVMHIST_CALLED(pmapexechist); 278 279 if ((pte & PTE_UNSYNCED) == PTE_UNSYNCED) { 280 const paddr_t pa = pte_to_paddr(pte); 281 struct vm_page * const pg = PHYS_TO_VM_PAGE(pa); 282 KASSERT(pg); 283 struct vm_page_md * const mdpg = VM_PAGE_TO_MD(pg); 284 285 UVMHIST_LOG(pmapexechist, 286 "srr0=%#x pg=%p (pa %#"PRIxPADDR"): %s", 287 tf->tf_srr0, pg, pa, 288 (VM_PAGEMD_EXECPAGE_P(mdpg) 289 ? "no syncicache (already execpage)" 290 : "performed syncicache (now execpage)")); 291 292 if (!VM_PAGEMD_EXECPAGE_P(mdpg)) { 293 ci->ci_softc->cpu_ev_exec_trap_sync.ev_count++; 294 dcache_wb_page(pa); 295 icache_inv_page(pa); 296 pmap_page_set_attributes(mdpg, VM_PAGEMD_EXECPAGE); 297 } 298 pte &= ~PTE_UNSYNCED; 299 pte |= PTE_xX; 300 *ptep = pte; 301 302 pmap_tlb_update_addr(faultmap->pmap, trunc_page(faultva), 303 pte, 0); 304 kpreempt_enable(); 305 UVMHIST_LOG(pmapexechist, "<- 0", 0,0,0,0); 306 return 0; 307 } 308 kpreempt_enable(); 309 310 int rv = pagefault(faultmap, faultva, VM_PROT_READ|VM_PROT_EXECUTE, 311 usertrap); 312 313 if (__predict_false(rv != 0 && usertrap)) { 314 /* 315 * We can't get a MAPERR here since 316 * that's a different exception. 317 */ 318 ci->ci_ev_isi_fatal.ev_count++; 319 KSI_INIT_TRAP(ksi); 320 ksi->ksi_signo = SIGSEGV; 321 ksi->ksi_trap = EXC_ISI; 322 ksi->ksi_code = SEGV_ACCERR; 323 ksi->ksi_addr = (void *)tf->tf_srr0; /* not truncated */ 324 } 325 UVMHIST_LOG(pmapexechist, "<- %d", rv, 0,0,0); 326 return rv; 327 } 328 329 static int 330 dtlb_exception(struct trapframe *tf, ksiginfo_t *ksi) 331 { 332 const vaddr_t faultva = tf->tf_dear; 333 const vm_prot_t ftype = get_faulttype(tf); 334 struct vm_map * const faultmap = get_faultmap(tf, PSL_DS); 335 struct cpu_info * const ci = curcpu(); 336 const bool usertrap = usertrap_p(tf); 337 338 #if 0 339 /* 340 * This is what pte_load in trap_subr.S does for us. 341 */ 342 const pt_entry_t * const ptep = 343 trap_pte_lookup(tf, trunc_page(faultva), PSL_DS); 344 if (ptep != NULL && !usertrap && pte_valid_p(*ptep)) { 345 tlb_update_addr(trunc_page(faultva), KERNEL_PID, *ptep, true); 346 ci->ci_ev_tlbmiss_soft.ev_count++; 347 return 0; 348 } 349 #endif 350 351 ci->ci_ev_dtlbmiss_hard.ev_count++; 352 353 // printf("pagefault(%p,%#lx,%u,%u)", faultmap, faultva, ftype, usertrap); 354 int rv = pagefault(faultmap, faultva, ftype, usertrap); 355 // printf(": %d\n", rv); 356 357 if (__predict_false(rv != 0 && usertrap)) { 358 ci->ci_ev_udsi_fatal.ev_count++; 359 KSI_INIT_TRAP(ksi); 360 ksi->ksi_signo = SIGSEGV; 361 ksi->ksi_trap = EXC_DSI; 362 ksi->ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 363 ksi->ksi_addr = (void *)faultva; 364 } 365 return rv; 366 } 367 368 static int 369 itlb_exception(struct trapframe *tf, ksiginfo_t *ksi) 370 { 371 struct vm_map * const faultmap = get_faultmap(tf, PSL_IS); 372 const vaddr_t faultva = tf->tf_srr0; 373 struct cpu_info * const ci = curcpu(); 374 const bool usertrap = usertrap_p(tf); 375 376 ci->ci_ev_itlbmiss_hard.ev_count++; 377 378 int rv = pagefault(faultmap, faultva, VM_PROT_READ|VM_PROT_EXECUTE, 379 usertrap); 380 381 if (__predict_false(rv != 0 && usertrap)) { 382 ci->ci_ev_isi_fatal.ev_count++; 383 KSI_INIT_TRAP(ksi); 384 ksi->ksi_signo = SIGSEGV; 385 ksi->ksi_trap = EXC_ISI; 386 ksi->ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 387 ksi->ksi_addr = (void *)tf->tf_srr0; 388 } 389 return rv; 390 } 391 392 static int 393 spe_exception(struct trapframe *tf, ksiginfo_t *ksi) 394 { 395 struct cpu_info * const ci = curcpu(); 396 397 if (!usertrap_p(tf)) 398 return EPERM; 399 400 ci->ci_ev_vec.ev_count++; 401 402 #ifdef PPC_HAVE_SPE 403 vec_load(); 404 return 0; 405 #else 406 KSI_INIT_TRAP(ksi); 407 ksi->ksi_signo = SIGILL; 408 ksi->ksi_trap = EXC_PGM; 409 ksi->ksi_code = ILL_ILLOPC; 410 ksi->ksi_addr = (void *)tf->tf_srr0; 411 return EPERM; 412 #endif 413 } 414 415 static bool 416 emulate_opcode(struct trapframe *tf, ksiginfo_t *ksi) 417 { 418 uint32_t opcode; 419 if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0) 420 return false; 421 422 if (opcode == OPC_LWSYNC) 423 return true; 424 425 if (OPC_MFSPR_P(opcode, SPR_PVR)) { 426 __asm ("mfpvr %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)])); 427 return true; 428 } 429 430 if (OPC_MFSPR_P(opcode, SPR_PIR)) { 431 __asm ("mfpir %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)])); 432 return true; 433 } 434 435 if (OPC_MFSPR_P(opcode, SPR_SVR)) { 436 __asm ("mfspr %0,%1" 437 : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]) 438 : "n"(SPR_SVR)); 439 return true; 440 } 441 442 /* 443 * If we bothered to emulate FP, we would try to do so here. 444 */ 445 return false; 446 } 447 448 static int 449 pgm_exception(struct trapframe *tf, ksiginfo_t *ksi) 450 { 451 struct cpu_info * const ci = curcpu(); 452 int rv = EPERM; 453 454 if (!usertrap_p(tf)) 455 return rv; 456 457 UVMHIST_FUNC(__func__); UVMHIST_CALLED(pmapexechist); 458 459 UVMHIST_LOG(pmapexechist, " srr0/1=%#x/%#x esr=%#x pte=%#x", 460 tf->tf_srr0, tf->tf_srr1, tf->tf_esr, 461 *trap_pte_lookup(tf, trunc_page(tf->tf_srr0), PSL_IS)); 462 463 ci->ci_ev_pgm.ev_count++; 464 465 if (tf->tf_esr & ESR_PTR) { 466 struct proc *p = curlwp->l_proc; 467 if (p->p_raslist != NULL 468 && ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) { 469 tf->tf_srr0 += 4; 470 return 0; 471 } 472 } 473 474 if (tf->tf_esr & (ESR_PIL|ESR_PPR)) { 475 if (emulate_opcode(tf, ksi)) { 476 tf->tf_srr0 += 4; 477 return 0; 478 } 479 } 480 481 if (tf->tf_esr & ESR_PIL) { 482 struct pcb * const pcb = lwp_getpcb(curlwp); 483 if (__predict_false(!fpu_used_p(curlwp))) { 484 memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu)); 485 fpu_mark_used(curlwp); 486 } 487 if (fpu_emulate(tf, &pcb->pcb_fpu, ksi)) { 488 if (ksi->ksi_signo == 0) { 489 ci->ci_ev_fpu.ev_count++; 490 return 0; 491 } 492 return EFAULT; 493 } 494 } 495 496 KSI_INIT_TRAP(ksi); 497 ksi->ksi_signo = SIGILL; 498 ksi->ksi_trap = EXC_PGM; 499 if (tf->tf_esr & ESR_PIL) { 500 ksi->ksi_code = ILL_ILLOPC; 501 } else if (tf->tf_esr & ESR_PPR) { 502 ksi->ksi_code = ILL_PRVOPC; 503 } else if (tf->tf_esr & ESR_PTR) { 504 ksi->ksi_signo = SIGTRAP; 505 ksi->ksi_code = TRAP_BRKPT; 506 } else { 507 ksi->ksi_code = 0; 508 } 509 ksi->ksi_addr = (void *)tf->tf_srr0; 510 return rv; 511 } 512 513 static int 514 debug_exception(struct trapframe *tf, ksiginfo_t *ksi) 515 { 516 struct cpu_info * const ci = curcpu(); 517 int rv = EPERM; 518 519 if (!usertrap_p(tf)) 520 return rv; 521 522 ci->ci_ev_debug.ev_count++; 523 524 /* 525 * Ack the interrupt. 526 */ 527 mtspr(SPR_DBSR, tf->tf_esr); 528 KASSERT(tf->tf_esr & (DBSR_IAC1|DBSR_IAC2)); 529 KASSERT((tf->tf_srr1 & PSL_SE) == 0); 530 531 /* 532 * Disable debug events 533 */ 534 mtspr(SPR_DBCR1, 0); 535 mtspr(SPR_DBCR0, 0); 536 537 /* 538 * Tell the debugger ... 539 */ 540 KSI_INIT_TRAP(ksi); 541 ksi->ksi_signo = SIGTRAP; 542 ksi->ksi_trap = EXC_TRC; 543 ksi->ksi_addr = (void *)tf->tf_srr0; 544 ksi->ksi_code = TRAP_TRACE; 545 return rv; 546 } 547 548 static int 549 ali_exception(struct trapframe *tf, ksiginfo_t *ksi) 550 { 551 struct cpu_info * const ci = curcpu(); 552 int rv = EFAULT; 553 554 ci->ci_ev_ali.ev_count++; 555 556 if (rv != 0 && usertrap_p(tf)) { 557 ci->ci_ev_ali_fatal.ev_count++; 558 KSI_INIT_TRAP(ksi); 559 ksi->ksi_signo = SIGILL; 560 ksi->ksi_trap = EXC_PGM; 561 if (tf->tf_esr & ESR_PIL) 562 ksi->ksi_code = ILL_ILLOPC; 563 else if (tf->tf_esr & ESR_PPR) 564 ksi->ksi_code = ILL_PRVOPC; 565 else if (tf->tf_esr & ESR_PTR) 566 ksi->ksi_code = ILL_ILLTRP; 567 else 568 ksi->ksi_code = 0; 569 ksi->ksi_addr = (void *)tf->tf_srr0; 570 } 571 return rv; 572 } 573 574 static int 575 embedded_fp_data_exception(struct trapframe *tf, ksiginfo_t *ksi) 576 { 577 struct cpu_info * const ci = curcpu(); 578 int rv = EFAULT; 579 580 ci->ci_ev_fpu.ev_count++; 581 582 if (rv != 0 && usertrap_p(tf)) { 583 KSI_INIT_TRAP(ksi); 584 #ifdef PPC_HAVE_SPE 585 ksi->ksi_signo = SIGFPE; 586 ksi->ksi_trap = tf->tf_exc; 587 ksi->ksi_code = vec_siginfo_code(tf); 588 #else 589 ksi->ksi_signo = SIGILL; 590 ksi->ksi_trap = EXC_PGM; 591 ksi->ksi_code = ILL_ILLOPC; 592 #endif 593 ksi->ksi_addr = (void *)tf->tf_srr0; 594 } 595 return rv; 596 } 597 598 static int 599 embedded_fp_round_exception(struct trapframe *tf, ksiginfo_t *ksi) 600 { 601 struct cpu_info * const ci = curcpu(); 602 int rv = EDOM; 603 604 ci->ci_ev_fpu.ev_count++; 605 606 if (rv != 0 && usertrap_p(tf)) { 607 KSI_INIT_TRAP(ksi); 608 #ifdef PPC_HAVE_SPE 609 ksi->ksi_signo = SIGFPE; 610 ksi->ksi_trap = tf->tf_exc; 611 ksi->ksi_code = vec_siginfo_code(tf); 612 #else 613 ksi->ksi_signo = SIGILL; 614 ksi->ksi_trap = EXC_PGM; 615 ksi->ksi_code = ILL_ILLOPC; 616 #endif 617 ksi->ksi_addr = (void *)tf->tf_srr0; 618 } 619 return rv; 620 } 621 622 void 623 dump_trapframe(const struct trapframe *tf, void (*pr)(const char *, ...)) 624 { 625 if (pr == NULL) 626 pr = printf; 627 (*pr)("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n", 628 tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear); 629 (*pr)("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n", 630 tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer); 631 for (u_int r = 0; r < 32; r += 4) { 632 (*pr)("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n", 633 r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1], 634 r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]); 635 } 636 } 637 638 static bool 639 ddb_exception(struct trapframe *tf) 640 { 641 #if 0 642 const register_t ddb_trapfunc = (uintptr_t) cpu_Debugger; 643 if ((tf->tf_esr & ESR_PTR) == 0) 644 return false; 645 if (ddb_trapfunc <= tf->tf_srr0 && tf->tf_srr0 <= ddb_trapfunc+16) { 646 register_t srr0 = tf->tf_srr0; 647 if (kdb_trap(tf->tf_exc, tf)) { 648 if (srr0 == tf->tf_srr0) 649 tf->tf_srr0 += 4; 650 return true; 651 } 652 } 653 return false; 654 #else 655 #if 0 656 struct cpu_info * const ci = curcpu(); 657 struct cpu_softc * const cpu = ci->ci_softc; 658 printf("CPL stack:"); 659 if (ci->ci_idepth >= 0) { 660 for (u_int i = 0; i <= ci->ci_idepth; i++) { 661 printf(" [%u]=%u", i, cpu->cpu_pcpls[i]); 662 } 663 } 664 printf(" %u\n", ci->ci_cpl); 665 dump_trapframe(tf, NULL); 666 #endif 667 if (kdb_trap(tf->tf_exc, tf)) { 668 tf->tf_srr0 += 4; 669 return true; 670 } 671 return false; 672 #endif 673 } 674 675 static bool 676 onfaulted(struct trapframe *tf, register_t rv) 677 { 678 struct lwp * const l = curlwp; 679 struct pcb * const pcb = lwp_getpcb(l); 680 struct faultbuf * const fb = pcb->pcb_onfault; 681 if (fb == NULL) 682 return false; 683 tf->tf_srr0 = fb->fb_pc; 684 tf->tf_srr1 = fb->fb_msr; 685 tf->tf_cr = fb->fb_cr; 686 tf->tf_fixreg[1] = fb->fb_sp; 687 tf->tf_fixreg[2] = fb->fb_r2; 688 tf->tf_fixreg[3] = rv; 689 pcb->pcb_onfault = NULL; 690 return true; 691 } 692 693 void 694 trap(enum ppc_booke_exceptions trap_code, struct trapframe *tf) 695 { 696 const bool usertrap = usertrap_p(tf); 697 struct cpu_info * const ci = curcpu(); 698 struct lwp * const l = curlwp; 699 struct proc * const p = l->l_proc; 700 ksiginfo_t ksi; 701 int rv = EACCES; 702 703 ci->ci_ev_traps.ev_count++; 704 ci->ci_data.cpu_ntrap++; 705 706 KASSERTMSG(!usertrap || tf == trapframe(l), 707 "trap: tf=%p is invalid: trapframe(%p)=%p", tf, l, trapframe(l)); 708 709 #if 0 710 if (trap_code != T_PROGRAM || usertrap) 711 printf("trap(enter): %s (tf=%p, esr/dear=%#x/%#lx, srr0/1=%#lx/%#lx, lr=%#lx)\n", 712 trap_names[trap_code], tf, tf->tf_esr, tf->tf_dear, 713 tf->tf_srr0, tf->tf_srr1, tf->tf_lr); 714 #endif 715 #if 0 716 if ((register_t)tf >= (register_t)l->l_addr + USPACE 717 || (register_t)tf < (register_t)l->l_addr + PAGE_SIZE) { 718 printf("%s(entry): pid %d.%d (%s): invalid tf addr %p\n", 719 __func__, p->p_pid, l->l_lid, p->p_comm, tf); 720 dump_trapframe(tf, NULL); 721 Debugger(); 722 } 723 #endif 724 #if 0 725 if ((mfmsr() & PSL_CE) == 0) { 726 printf("%s(entry): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 727 __func__, p->p_pid, l->l_lid, p->p_comm, 728 trap_names[trap_code], mfmsr()); 729 dump_trapframe(tf, NULL); 730 } 731 #endif 732 733 if ((VM_MAX_ADDRESS & 0x80000000) == 0 734 && usertrap && (tf->tf_fixreg[1] & 0x80000000)) { 735 printf("%s(entry): pid %d.%d (%s): %s invalid sp %#lx (sprg1=%#lx)\n", 736 __func__, p->p_pid, l->l_lid, p->p_comm, 737 trap_names[trap_code], tf->tf_fixreg[1], mfspr(SPR_SPRG1)); 738 dump_trapframe(tf, NULL); 739 Debugger(); 740 } 741 742 if (usertrap && (tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 743 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 744 __func__, p->p_pid, l->l_lid, p->p_comm, 745 trap_names[trap_code], tf->tf_srr1); 746 dump_trapframe(tf, NULL); 747 Debugger(); 748 } 749 750 switch (trap_code) { 751 case T_CRITIAL_INPUT: 752 case T_EXTERNAL_INPUT: 753 case T_DECREMENTER: 754 case T_FIXED_INTERVAL: 755 case T_WATCHDOG: 756 case T_SYSTEM_CALL: 757 default: 758 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 759 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 760 case T_MACHINE_CHECK: 761 rv = mchk_exception(tf, &ksi); 762 break; 763 case T_DSI: 764 rv = dsi_exception(tf, &ksi); 765 break; 766 case T_ISI: 767 rv = isi_exception(tf, &ksi); 768 break; 769 case T_ALIGNMENT: 770 rv = ali_exception(tf, &ksi); 771 break; 772 case T_SPE_UNAVAILABLE: 773 rv = spe_exception(tf, &ksi); 774 break; 775 case T_PROGRAM: 776 #ifdef DDB 777 if (!usertrap && ddb_exception(tf)) 778 return; 779 #endif 780 rv = pgm_exception(tf, &ksi); 781 break; 782 case T_FP_UNAVAILABLE: 783 case T_AP_UNAVAILABLE: 784 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 785 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 786 case T_DATA_TLB_ERROR: 787 rv = dtlb_exception(tf, &ksi); 788 break; 789 case T_INSTRUCTION_TLB_ERROR: 790 rv = itlb_exception(tf, &ksi); 791 break; 792 case T_DEBUG: 793 #ifdef DDB 794 if (!usertrap && ddb_exception(tf)) 795 return; 796 #endif 797 rv = debug_exception(tf, &ksi); 798 break; 799 case T_EMBEDDED_FP_DATA: 800 rv = embedded_fp_data_exception(tf, &ksi); 801 break; 802 case T_EMBEDDED_FP_ROUND: 803 rv = embedded_fp_round_exception(tf, &ksi); 804 break; 805 case T_EMBEDDED_PERF_MONITOR: 806 //db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 807 dump_trapframe(tf, NULL); 808 rv = EPERM; 809 break; 810 case T_AST: 811 KASSERT(usertrap); 812 cpu_ast(l, ci); 813 if ((VM_MAX_ADDRESS & 0x80000000) == 0 814 && (tf->tf_fixreg[1] & 0x80000000)) { 815 printf("%s(ast-exit): pid %d.%d (%s): invalid sp %#lx\n", 816 __func__, p->p_pid, l->l_lid, p->p_comm, 817 tf->tf_fixreg[1]); 818 dump_trapframe(tf, NULL); 819 Debugger(); 820 } 821 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 822 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 823 __func__, p->p_pid, l->l_lid, p->p_comm, 824 trap_names[trap_code], tf->tf_srr1); 825 dump_trapframe(tf, NULL); 826 Debugger(); 827 } 828 #if 0 829 if ((mfmsr() & PSL_CE) == 0) { 830 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 831 __func__, p->p_pid, l->l_lid, p->p_comm, 832 trap_names[trap_code], mfmsr()); 833 dump_trapframe(tf, NULL); 834 } 835 #endif 836 userret(l, tf); 837 return; 838 } 839 if (!usertrap) { 840 if (rv != 0) { 841 if (!onfaulted(tf, rv)) { 842 db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 843 dump_trapframe(tf, NULL); 844 panic("%s: pid %d.%d (%s): %s exception in kernel mode" 845 " (tf=%p, dear=%#lx, esr=%#x," 846 " srr0/1=%#lx/%#lx)", 847 __func__, p->p_pid, l->l_lid, p->p_comm, 848 trap_names[trap_code], tf, tf->tf_dear, 849 tf->tf_esr, tf->tf_srr0, tf->tf_srr1); 850 } 851 } 852 #if 0 853 if (tf->tf_fixreg[1] >= (register_t)l->l_addr + USPACE 854 || tf->tf_fixreg[1] < (register_t)l->l_addr + PAGE_SIZE) { 855 printf("%s(exit): pid %d.%d (%s): invalid kern sp %#lx\n", 856 __func__, p->p_pid, l->l_lid, p->p_comm, 857 tf->tf_fixreg[1]); 858 dump_trapframe(tf, NULL); 859 Debugger(); 860 } 861 #endif 862 #if 0 863 if ((mfmsr() & PSL_CE) == 0) { 864 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 865 __func__, p->p_pid, l->l_lid, p->p_comm, 866 trap_names[trap_code], mfmsr()); 867 mtmsr(mfmsr()|PSL_CE); 868 dump_trapframe(tf, NULL); 869 } 870 #endif 871 } else { 872 if (rv == ENOMEM) { 873 printf("UVM: pid %d.%d (%s), uid %d killed: " 874 "out of swap\n", 875 p->p_pid, l->l_lid, p->p_comm, 876 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 877 ksi.ksi_signo = SIGKILL; 878 } 879 if (rv != 0) { 880 /* 881 * Only print a fatal trap if the signal will be 882 * uncaught. 883 */ 884 if (cpu_printfataltraps 885 && (p->p_slflag & PSL_TRACED) == 0 886 && !sigismember(&p->p_sigctx.ps_sigcatch, 887 ksi.ksi_signo)) { 888 printf("%s: pid %d.%d (%s):" 889 " %s exception in user mode\n", 890 __func__, p->p_pid, l->l_lid, p->p_comm, 891 trap_names[trap_code]); 892 if (cpu_printfataltraps > 1) 893 dump_trapframe(tf, NULL); 894 } 895 (*p->p_emul->e_trapsignal)(l, &ksi); 896 } 897 #ifdef DEBUG 898 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 899 printf("%s(exit): pid %d.%d (%s): %s invalid PSL %#lx\n", 900 __func__, p->p_pid, l->l_lid, p->p_comm, 901 trap_names[trap_code], tf->tf_srr1); 902 dump_trapframe(tf, NULL); 903 Debugger(); 904 } 905 #endif 906 #if 0 907 if ((mfmsr() & PSL_CE) == 0) { 908 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 909 __func__, p->p_pid, l->l_lid, p->p_comm, 910 trap_names[trap_code], mfmsr()); 911 dump_trapframe(tf, NULL); 912 } 913 #endif 914 userret(l, tf); 915 } 916 } 917