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