1 /* $NetBSD: trap.c,v 1.27 2018/01/27 10:07:41 flxd 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.27 2018/01/27 10:07:41 flxd 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 ("mfspr %0, %1" 432 : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]) 433 : "n"(SPR_PIR)); 434 return true; 435 } 436 437 if (OPC_MFSPR_P(opcode, SPR_SVR)) { 438 __asm ("mfspr %0,%1" 439 : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)]) 440 : "n"(SPR_SVR)); 441 return true; 442 } 443 444 /* 445 * If we bothered to emulate FP, we would try to do so here. 446 */ 447 return false; 448 } 449 450 static int 451 pgm_exception(struct trapframe *tf, ksiginfo_t *ksi) 452 { 453 struct cpu_info * const ci = curcpu(); 454 int rv = EPERM; 455 456 if (!usertrap_p(tf)) 457 return rv; 458 459 UVMHIST_FUNC(__func__); UVMHIST_CALLED(pmapexechist); 460 461 UVMHIST_LOG(pmapexechist, " srr0/1=%#x/%#x esr=%#x pte=%#x", 462 tf->tf_srr0, tf->tf_srr1, tf->tf_esr, 463 *trap_pte_lookup(tf, trunc_page(tf->tf_srr0), PSL_IS)); 464 465 ci->ci_ev_pgm.ev_count++; 466 467 if (tf->tf_esr & ESR_PTR) { 468 struct proc *p = curlwp->l_proc; 469 if (p->p_raslist != NULL 470 && ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) { 471 tf->tf_srr0 += 4; 472 return 0; 473 } 474 } 475 476 if (tf->tf_esr & (ESR_PIL|ESR_PPR)) { 477 if (emulate_opcode(tf, ksi)) { 478 tf->tf_srr0 += 4; 479 return 0; 480 } 481 } 482 483 if (tf->tf_esr & ESR_PIL) { 484 struct pcb * const pcb = lwp_getpcb(curlwp); 485 if (__predict_false(!fpu_used_p(curlwp))) { 486 memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu)); 487 fpu_mark_used(curlwp); 488 } 489 if (fpu_emulate(tf, &pcb->pcb_fpu, ksi)) { 490 if (ksi->ksi_signo == 0) { 491 ci->ci_ev_fpu.ev_count++; 492 return 0; 493 } 494 return EFAULT; 495 } 496 } 497 498 KSI_INIT_TRAP(ksi); 499 ksi->ksi_signo = SIGILL; 500 ksi->ksi_trap = EXC_PGM; 501 if (tf->tf_esr & ESR_PIL) { 502 ksi->ksi_code = ILL_ILLOPC; 503 } else if (tf->tf_esr & ESR_PPR) { 504 ksi->ksi_code = ILL_PRVOPC; 505 } else if (tf->tf_esr & ESR_PTR) { 506 ksi->ksi_signo = SIGTRAP; 507 ksi->ksi_code = TRAP_BRKPT; 508 } else { 509 ksi->ksi_code = 0; 510 } 511 ksi->ksi_addr = (void *)tf->tf_srr0; 512 return rv; 513 } 514 515 static int 516 debug_exception(struct trapframe *tf, ksiginfo_t *ksi) 517 { 518 struct cpu_info * const ci = curcpu(); 519 int rv = EPERM; 520 521 if (!usertrap_p(tf)) 522 return rv; 523 524 ci->ci_ev_debug.ev_count++; 525 526 /* 527 * Ack the interrupt. 528 */ 529 mtspr(SPR_DBSR, tf->tf_esr); 530 KASSERT(tf->tf_esr & (DBSR_IAC1|DBSR_IAC2|DBSR_BRT)); 531 KASSERT((tf->tf_srr1 & PSL_SE) == 0); 532 533 /* 534 * Disable debug events 535 */ 536 mtspr(SPR_DBCR1, 0); 537 mtspr(SPR_DBCR0, 0); 538 539 /* 540 * Tell the debugger ... 541 */ 542 KSI_INIT_TRAP(ksi); 543 ksi->ksi_signo = SIGTRAP; 544 ksi->ksi_trap = EXC_TRC; 545 ksi->ksi_addr = (void *)tf->tf_srr0; 546 ksi->ksi_code = TRAP_TRACE; 547 return rv; 548 } 549 550 static int 551 ali_exception(struct trapframe *tf, ksiginfo_t *ksi) 552 { 553 struct cpu_info * const ci = curcpu(); 554 int rv = EFAULT; 555 556 ci->ci_ev_ali.ev_count++; 557 558 if (rv != 0 && usertrap_p(tf)) { 559 ci->ci_ev_ali_fatal.ev_count++; 560 KSI_INIT_TRAP(ksi); 561 ksi->ksi_signo = SIGILL; 562 ksi->ksi_trap = EXC_PGM; 563 if (tf->tf_esr & ESR_PIL) 564 ksi->ksi_code = ILL_ILLOPC; 565 else if (tf->tf_esr & ESR_PPR) 566 ksi->ksi_code = ILL_PRVOPC; 567 else if (tf->tf_esr & ESR_PTR) 568 ksi->ksi_code = ILL_ILLTRP; 569 else 570 ksi->ksi_code = 0; 571 ksi->ksi_addr = (void *)tf->tf_srr0; 572 } 573 return rv; 574 } 575 576 static int 577 embedded_fp_data_exception(struct trapframe *tf, ksiginfo_t *ksi) 578 { 579 struct cpu_info * const ci = curcpu(); 580 int rv = EFAULT; 581 582 ci->ci_ev_fpu.ev_count++; 583 584 if (rv != 0 && usertrap_p(tf)) { 585 KSI_INIT_TRAP(ksi); 586 #ifdef PPC_HAVE_SPE 587 ksi->ksi_signo = SIGFPE; 588 ksi->ksi_trap = tf->tf_exc; 589 ksi->ksi_code = vec_siginfo_code(tf); 590 #else 591 ksi->ksi_signo = SIGILL; 592 ksi->ksi_trap = EXC_PGM; 593 ksi->ksi_code = ILL_ILLOPC; 594 #endif 595 ksi->ksi_addr = (void *)tf->tf_srr0; 596 } 597 return rv; 598 } 599 600 static int 601 embedded_fp_round_exception(struct trapframe *tf, ksiginfo_t *ksi) 602 { 603 struct cpu_info * const ci = curcpu(); 604 int rv = EDOM; 605 606 ci->ci_ev_fpu.ev_count++; 607 608 if (rv != 0 && usertrap_p(tf)) { 609 KSI_INIT_TRAP(ksi); 610 #ifdef PPC_HAVE_SPE 611 ksi->ksi_signo = SIGFPE; 612 ksi->ksi_trap = tf->tf_exc; 613 ksi->ksi_code = vec_siginfo_code(tf); 614 #else 615 ksi->ksi_signo = SIGILL; 616 ksi->ksi_trap = EXC_PGM; 617 ksi->ksi_code = ILL_ILLOPC; 618 #endif 619 ksi->ksi_addr = (void *)tf->tf_srr0; 620 } 621 return rv; 622 } 623 624 void 625 dump_trapframe(const struct trapframe *tf, void (*pr)(const char *, ...)) 626 { 627 if (pr == NULL) 628 pr = printf; 629 (*pr)("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n", 630 tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear); 631 (*pr)("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n", 632 tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer); 633 for (u_int r = 0; r < 32; r += 4) { 634 (*pr)("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n", 635 r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1], 636 r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]); 637 } 638 } 639 640 static bool 641 ddb_exception(struct trapframe *tf) 642 { 643 #if 0 644 const register_t ddb_trapfunc = (uintptr_t) cpu_Debugger; 645 if ((tf->tf_esr & ESR_PTR) == 0) 646 return false; 647 if (ddb_trapfunc <= tf->tf_srr0 && tf->tf_srr0 <= ddb_trapfunc+16) { 648 register_t srr0 = tf->tf_srr0; 649 if (kdb_trap(tf->tf_exc, tf)) { 650 if (srr0 == tf->tf_srr0) 651 tf->tf_srr0 += 4; 652 return true; 653 } 654 } 655 return false; 656 #else 657 #if 0 658 struct cpu_info * const ci = curcpu(); 659 struct cpu_softc * const cpu = ci->ci_softc; 660 printf("CPL stack:"); 661 if (ci->ci_idepth >= 0) { 662 for (u_int i = 0; i <= ci->ci_idepth; i++) { 663 printf(" [%u]=%u", i, cpu->cpu_pcpls[i]); 664 } 665 } 666 printf(" %u\n", ci->ci_cpl); 667 dump_trapframe(tf, NULL); 668 #endif 669 if (kdb_trap(tf->tf_exc, tf)) { 670 tf->tf_srr0 += 4; 671 return true; 672 } 673 return false; 674 #endif 675 } 676 677 static bool 678 onfaulted(struct trapframe *tf, register_t rv) 679 { 680 struct lwp * const l = curlwp; 681 struct pcb * const pcb = lwp_getpcb(l); 682 struct faultbuf * const fb = pcb->pcb_onfault; 683 if (fb == NULL) 684 return false; 685 tf->tf_srr0 = fb->fb_pc; 686 tf->tf_srr1 = fb->fb_msr; 687 tf->tf_cr = fb->fb_cr; 688 tf->tf_fixreg[1] = fb->fb_sp; 689 tf->tf_fixreg[2] = fb->fb_r2; 690 tf->tf_fixreg[3] = rv; 691 pcb->pcb_onfault = NULL; 692 return true; 693 } 694 695 void 696 trap(enum ppc_booke_exceptions trap_code, struct trapframe *tf) 697 { 698 const bool usertrap = usertrap_p(tf); 699 struct cpu_info * const ci = curcpu(); 700 struct lwp * const l = curlwp; 701 struct proc * const p = l->l_proc; 702 ksiginfo_t ksi; 703 int rv = EACCES; 704 705 ci->ci_ev_traps.ev_count++; 706 ci->ci_data.cpu_ntrap++; 707 708 KASSERTMSG(!usertrap || tf == trapframe(l), 709 "trap: tf=%p is invalid: trapframe(%p)=%p", tf, l, trapframe(l)); 710 711 #if 0 712 if (trap_code != T_PROGRAM || usertrap) 713 printf("trap(enter): %s (tf=%p, esr/dear=%#x/%#lx, srr0/1=%#lx/%#lx, lr=%#lx)\n", 714 trap_names[trap_code], tf, tf->tf_esr, tf->tf_dear, 715 tf->tf_srr0, tf->tf_srr1, tf->tf_lr); 716 #endif 717 #if 0 718 if ((register_t)tf >= (register_t)l->l_addr + USPACE 719 || (register_t)tf < (register_t)l->l_addr + PAGE_SIZE) { 720 printf("%s(entry): pid %d.%d (%s): invalid tf addr %p\n", 721 __func__, p->p_pid, l->l_lid, p->p_comm, tf); 722 dump_trapframe(tf, NULL); 723 Debugger(); 724 } 725 #endif 726 #if 0 727 if ((mfmsr() & PSL_CE) == 0) { 728 printf("%s(entry): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 729 __func__, p->p_pid, l->l_lid, p->p_comm, 730 trap_names[trap_code], mfmsr()); 731 dump_trapframe(tf, NULL); 732 } 733 #endif 734 735 if ((VM_MAX_ADDRESS & 0x80000000) == 0 736 && usertrap && (tf->tf_fixreg[1] & 0x80000000)) { 737 printf("%s(entry): pid %d.%d (%s): %s invalid sp %#lx " 738 "(sprg1=%#jx)\n", __func__, p->p_pid, l->l_lid, p->p_comm, 739 trap_names[trap_code], tf->tf_fixreg[1], 740 (uintmax_t)mfspr(SPR_SPRG1)); 741 dump_trapframe(tf, NULL); 742 Debugger(); 743 } 744 745 if (usertrap && (tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 746 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 747 __func__, p->p_pid, l->l_lid, p->p_comm, 748 trap_names[trap_code], tf->tf_srr1); 749 dump_trapframe(tf, NULL); 750 Debugger(); 751 } 752 753 switch (trap_code) { 754 case T_CRITIAL_INPUT: 755 case T_EXTERNAL_INPUT: 756 case T_DECREMENTER: 757 case T_FIXED_INTERVAL: 758 case T_WATCHDOG: 759 case T_SYSTEM_CALL: 760 default: 761 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 762 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 763 case T_MACHINE_CHECK: 764 rv = mchk_exception(tf, &ksi); 765 break; 766 case T_DSI: 767 rv = dsi_exception(tf, &ksi); 768 break; 769 case T_ISI: 770 rv = isi_exception(tf, &ksi); 771 break; 772 case T_ALIGNMENT: 773 rv = ali_exception(tf, &ksi); 774 break; 775 case T_SPE_UNAVAILABLE: 776 rv = spe_exception(tf, &ksi); 777 break; 778 case T_PROGRAM: 779 #ifdef DDB 780 if (!usertrap && ddb_exception(tf)) 781 return; 782 #endif 783 rv = pgm_exception(tf, &ksi); 784 break; 785 case T_FP_UNAVAILABLE: 786 case T_AP_UNAVAILABLE: 787 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 788 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 789 case T_DATA_TLB_ERROR: 790 rv = dtlb_exception(tf, &ksi); 791 break; 792 case T_INSTRUCTION_TLB_ERROR: 793 rv = itlb_exception(tf, &ksi); 794 break; 795 case T_DEBUG: 796 #ifdef DDB 797 if (!usertrap && ddb_exception(tf)) 798 return; 799 #endif 800 rv = debug_exception(tf, &ksi); 801 break; 802 case T_EMBEDDED_FP_DATA: 803 rv = embedded_fp_data_exception(tf, &ksi); 804 break; 805 case T_EMBEDDED_FP_ROUND: 806 rv = embedded_fp_round_exception(tf, &ksi); 807 break; 808 case T_EMBEDDED_PERF_MONITOR: 809 //db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 810 dump_trapframe(tf, NULL); 811 rv = EPERM; 812 break; 813 case T_AST: 814 KASSERT(usertrap); 815 cpu_ast(l, ci); 816 if ((VM_MAX_ADDRESS & 0x80000000) == 0 817 && (tf->tf_fixreg[1] & 0x80000000)) { 818 printf("%s(ast-exit): pid %d.%d (%s): invalid sp %#lx\n", 819 __func__, p->p_pid, l->l_lid, p->p_comm, 820 tf->tf_fixreg[1]); 821 dump_trapframe(tf, NULL); 822 Debugger(); 823 } 824 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 825 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 826 __func__, p->p_pid, l->l_lid, p->p_comm, 827 trap_names[trap_code], tf->tf_srr1); 828 dump_trapframe(tf, NULL); 829 Debugger(); 830 } 831 #if 0 832 if ((mfmsr() & PSL_CE) == 0) { 833 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 834 __func__, p->p_pid, l->l_lid, p->p_comm, 835 trap_names[trap_code], mfmsr()); 836 dump_trapframe(tf, NULL); 837 } 838 #endif 839 userret(l, tf); 840 return; 841 } 842 if (!usertrap) { 843 if (rv != 0) { 844 if (!onfaulted(tf, rv)) { 845 db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 846 dump_trapframe(tf, NULL); 847 panic("%s: pid %d.%d (%s): %s exception in kernel mode" 848 " (tf=%p, dear=%#lx, esr=%#x," 849 " srr0/1=%#lx/%#lx)", 850 __func__, p->p_pid, l->l_lid, p->p_comm, 851 trap_names[trap_code], tf, tf->tf_dear, 852 tf->tf_esr, tf->tf_srr0, tf->tf_srr1); 853 } 854 } 855 #if 0 856 if (tf->tf_fixreg[1] >= (register_t)l->l_addr + USPACE 857 || tf->tf_fixreg[1] < (register_t)l->l_addr + PAGE_SIZE) { 858 printf("%s(exit): pid %d.%d (%s): invalid kern sp %#lx\n", 859 __func__, p->p_pid, l->l_lid, p->p_comm, 860 tf->tf_fixreg[1]); 861 dump_trapframe(tf, NULL); 862 Debugger(); 863 } 864 #endif 865 #if 0 866 if ((mfmsr() & PSL_CE) == 0) { 867 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 868 __func__, p->p_pid, l->l_lid, p->p_comm, 869 trap_names[trap_code], mfmsr()); 870 mtmsr(mfmsr()|PSL_CE); 871 dump_trapframe(tf, NULL); 872 } 873 #endif 874 } else { 875 if (rv == ENOMEM) { 876 printf("UVM: pid %d.%d (%s), uid %d killed: " 877 "out of swap\n", 878 p->p_pid, l->l_lid, p->p_comm, 879 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 880 ksi.ksi_signo = SIGKILL; 881 } 882 if (rv != 0) { 883 /* 884 * Only print a fatal trap if the signal will be 885 * uncaught. 886 */ 887 if (cpu_printfataltraps 888 && (p->p_slflag & PSL_TRACED) == 0 889 && !sigismember(&p->p_sigctx.ps_sigcatch, 890 ksi.ksi_signo)) { 891 printf("%s: pid %d.%d (%s):" 892 " %s exception in user mode\n", 893 __func__, p->p_pid, l->l_lid, p->p_comm, 894 trap_names[trap_code]); 895 if (cpu_printfataltraps > 1) 896 dump_trapframe(tf, NULL); 897 } 898 (*p->p_emul->e_trapsignal)(l, &ksi); 899 } 900 #ifdef DEBUG 901 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 902 printf("%s(exit): pid %d.%d (%s): %s invalid PSL %#lx\n", 903 __func__, p->p_pid, l->l_lid, p->p_comm, 904 trap_names[trap_code], tf->tf_srr1); 905 dump_trapframe(tf, NULL); 906 Debugger(); 907 } 908 #endif 909 #if 0 910 if ((mfmsr() & PSL_CE) == 0) { 911 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 912 __func__, p->p_pid, l->l_lid, p->p_comm, 913 trap_names[trap_code], mfmsr()); 914 dump_trapframe(tf, NULL); 915 } 916 #endif 917 userret(l, tf); 918 } 919 } 920