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