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