1 /* $NetBSD: trap.c,v 1.2 2011/01/18 01:02:52 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.2 2011/01/18 01:02:52 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 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 static void dump_trapframe(const struct trapframe *); 77 78 static 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 102 static inline bool 103 usertrap_p(struct trapframe *tf) 104 { 105 return (tf->tf_srr1 & PSL_PR) != 0; 106 } 107 108 static int 109 mchk_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 130 static inline vm_prot_t 131 get_faulttype(const struct trapframe * const tf) 132 { 133 return VM_PROT_READ | (tf->tf_esr & ESR_ST ? VM_PROT_WRITE : 0); 134 } 135 136 static inline struct vm_map * 137 get_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 */ 148 static inline pt_entry_t * 149 trap_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 161 static int 162 pagefault(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 #ifdef KERN_SA 180 l->l_pflag &= ~LP_SA_PAGEFAULT; 181 #endif 182 } else { 183 if (cpu_intr_p()) 184 return EFAULT; 185 186 struct pcb * const pcb = lwp_getpcb(l); 187 struct faultbuf * const fb = pcb->pcb_onfault; 188 pcb->pcb_onfault = NULL; 189 rv = uvm_fault(map, trunc_page(va), ftype); 190 pcb->pcb_onfault = fb; 191 if (map != kernel_map) { 192 if (rv == 0) 193 uvm_grow(l->l_proc, trunc_page(va)); 194 #ifdef KERN_SA 195 l->l_pflag &= ~LP_SA_PAGEFAULT; 196 #endif 197 } 198 if (rv == EACCES) 199 rv = EFAULT; 200 } 201 return rv; 202 } 203 204 static int 205 dsi_exception(struct trapframe *tf, ksiginfo_t *ksi) 206 { 207 const vaddr_t faultva = tf->tf_dear; 208 const vm_prot_t ftype = get_faulttype(tf); 209 struct vm_map * const faultmap = get_faultmap(tf, PSL_DS); 210 const bool usertrap = usertrap_p(tf); 211 212 kpreempt_disable(); 213 struct cpu_info * const ci = curcpu(); 214 215 if (usertrap) 216 ci->ci_ev_udsi.ev_count++; 217 else 218 ci->ci_ev_kdsi.ev_count++; 219 220 /* 221 * If we had a TLB entry (which we must have had to get this exception), 222 * we certainly have a PTE. 223 */ 224 pt_entry_t * const ptep = trap_pte_lookup(tf, trunc_page(faultva), 225 PSL_DS); 226 KASSERT(ptep != NULL); 227 pt_entry_t pte = *ptep; 228 229 if ((ftype & VM_PROT_WRITE) 230 && ((pte & (PTE_xW|PTE_UNMODIFIED)) == (PTE_xW|PTE_UNMODIFIED))) { 231 const paddr_t pa = pte_to_paddr(pte); 232 struct vm_page * const pg = PHYS_TO_VM_PAGE(pa); 233 KASSERT(pg); 234 235 if (!VM_PAGE_MD_MODIFIED_P(pg)) { 236 pmap_page_set_attributes(pg, VM_PAGE_MD_MODIFIED); 237 } 238 pte &= ~PTE_UNMODIFIED; 239 *ptep = pte; 240 pmap_tlb_update_addr(faultmap->pmap, trunc_page(faultva), 241 pte, 0); 242 kpreempt_enable(); 243 return 0; 244 } 245 kpreempt_enable(); 246 247 int rv = pagefault(faultmap, faultva, ftype, usertrap); 248 249 /* 250 * We can't get a MAPERR here since that's a different exception. 251 */ 252 if (__predict_false(rv != 0 && usertrap)) { 253 ci->ci_ev_udsi_fatal.ev_count++; 254 KSI_INIT_TRAP(ksi); 255 ksi->ksi_signo = SIGSEGV; 256 ksi->ksi_trap = EXC_DSI; 257 ksi->ksi_code = SEGV_ACCERR; 258 ksi->ksi_addr = (void *)faultva; 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); 286 KASSERT(ptep != NULL); 287 pt_entry_t pte = *ptep; 288 289 if ((pte & PTE_UNSYNCED) == PTE_UNSYNCED) { 290 const paddr_t pa = pte_to_paddr(pte); 291 struct vm_page * const pg = PHYS_TO_VM_PAGE(pa); 292 KASSERT(pg); 293 294 if (!VM_PAGE_MD_EXECPAGE_P(pg)) { 295 ci->ci_softc->cpu_ev_exec_trap_sync.ev_count++; 296 dcache_wb_page(pa); 297 icache_inv_page(pa); 298 pmap_page_set_attributes(pg, VM_PAGE_MD_EXECPAGE); 299 } 300 pte &= ~PTE_UNSYNCED; 301 pte |= PTE_xX; 302 *ptep = pte; 303 pmap_tlb_update_addr(faultmap->pmap, trunc_page(faultva), 304 pte, 0); 305 kpreempt_enable(); 306 return false; 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 return rv; 326 } 327 328 static int 329 dtlb_exception(struct trapframe *tf, ksiginfo_t *ksi) 330 { 331 const vaddr_t faultva = tf->tf_dear; 332 const vm_prot_t ftype = get_faulttype(tf); 333 struct vm_map * const faultmap = get_faultmap(tf, PSL_DS); 334 struct cpu_info * const ci = curcpu(); 335 const bool usertrap = usertrap_p(tf); 336 337 #if 0 338 /* 339 * This is what pte_load in trap_subr.S does for us. 340 */ 341 const pt_entry_t * const ptep = 342 trap_pte_lookup(tf, trunc_page(faultva), PSL_DS); 343 if (ptep != NULL && !usertrap && pte_valid_p(*ptep)) { 344 tlb_update_addr(trunc_page(faultva), KERNEL_PID, *ptep, true); 345 ci->ci_ev_tlbmiss_soft.ev_count++; 346 return 0; 347 } 348 #endif 349 350 ci->ci_ev_dtlbmiss_hard.ev_count++; 351 352 // printf("pagefault(%p,%#lx,%u,%u)", faultmap, faultva, ftype, usertrap); 353 int rv = pagefault(faultmap, faultva, ftype, usertrap); 354 // printf(": %d\n", rv); 355 356 if (__predict_false(rv != 0 && usertrap)) { 357 ci->ci_ev_udsi_fatal.ev_count++; 358 KSI_INIT_TRAP(ksi); 359 ksi->ksi_signo = SIGSEGV; 360 ksi->ksi_trap = EXC_DSI; 361 ksi->ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 362 ksi->ksi_addr = (void *)faultva; 363 } 364 return rv; 365 } 366 367 static int 368 itlb_exception(struct trapframe *tf, ksiginfo_t *ksi) 369 { 370 struct vm_map * const faultmap = get_faultmap(tf, PSL_IS); 371 const vaddr_t faultva = tf->tf_srr0; 372 struct cpu_info * const ci = curcpu(); 373 const bool usertrap = usertrap_p(tf); 374 375 ci->ci_ev_itlbmiss_hard.ev_count++; 376 377 int rv = pagefault(faultmap, faultva, VM_PROT_READ|VM_PROT_EXECUTE, 378 usertrap); 379 380 if (__predict_false(rv != 0 && usertrap)) { 381 ci->ci_ev_isi_fatal.ev_count++; 382 KSI_INIT_TRAP(ksi); 383 ksi->ksi_signo = SIGSEGV; 384 ksi->ksi_trap = EXC_ISI; 385 ksi->ksi_code = (rv == EACCES ? SEGV_ACCERR : SEGV_MAPERR); 386 ksi->ksi_addr = (void *)tf->tf_srr0; 387 } 388 return rv; 389 } 390 391 static int 392 spe_exception(struct trapframe *tf, ksiginfo_t *ksi) 393 { 394 struct cpu_info * const ci = curcpu(); 395 396 if (!usertrap_p(tf)) 397 return EPERM; 398 399 ci->ci_ev_vec.ev_count++; 400 401 #ifdef PPC_HAVE_SPE 402 vec_enable(); 403 return 0; 404 #else 405 KSI_INIT_TRAP(ksi); 406 ksi->ksi_signo = SIGILL; 407 ksi->ksi_trap = EXC_PGM; 408 ksi->ksi_code = ILL_ILLOPC; 409 ksi->ksi_addr = (void *)tf->tf_srr0; 410 return EPERM; 411 #endif 412 } 413 414 static bool 415 emulate_opcode(struct trapframe *tf, ksiginfo_t *ksi) 416 { 417 uint32_t opcode; 418 if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0) 419 return false; 420 421 if (opcode == OPC_LWSYNC) 422 return true; 423 424 if (OPC_MFSPR_P(opcode, SPR_PVR)) { 425 __asm ("mfpvr %0" : "=r"(tf->tf_fixreg[OPC_MFSPR_REG(opcode)])); 426 return true; 427 } 428 429 /* 430 * If we bothered to emulate FP, we would try to do so here. 431 */ 432 return false; 433 } 434 435 static int 436 pgm_exception(struct trapframe *tf, ksiginfo_t *ksi) 437 { 438 struct cpu_info * const ci = curcpu(); 439 int rv = EPERM; 440 441 if (!usertrap_p(tf)) 442 return rv; 443 444 ci->ci_ev_pgm.ev_count++; 445 446 if (tf->tf_esr & ESR_PTR) { 447 struct proc *p = curlwp->l_proc; 448 if (p->p_raslist != NULL 449 && ras_lookup(p, (void *)tf->tf_srr0) != (void *) -1) { 450 tf->tf_srr0 += 4; 451 return 0; 452 } 453 } else if (tf->tf_esr & (ESR_PIL|ESR_PPR)) { 454 if (emulate_opcode(tf, ksi)) { 455 tf->tf_srr0 += 4; 456 return 0; 457 } 458 } 459 460 KSI_INIT_TRAP(ksi); 461 ksi->ksi_signo = SIGILL; 462 ksi->ksi_trap = EXC_PGM; 463 if (tf->tf_esr & ESR_PIL) 464 ksi->ksi_code = ILL_ILLOPC; 465 else if (tf->tf_esr & ESR_PPR) 466 ksi->ksi_code = ILL_PRVOPC; 467 else if (tf->tf_esr & ESR_PTR) 468 ksi->ksi_code = ILL_ILLTRP; 469 else 470 ksi->ksi_code = 0; 471 ksi->ksi_addr = (void *)tf->tf_srr0; 472 return rv; 473 } 474 475 static int 476 ali_exception(struct trapframe *tf, ksiginfo_t *ksi) 477 { 478 struct cpu_info * const ci = curcpu(); 479 int rv = EFAULT; 480 481 ci->ci_ev_ali.ev_count++; 482 483 if (rv != 0 && usertrap_p(tf)) { 484 ci->ci_ev_ali_fatal.ev_count++; 485 KSI_INIT_TRAP(ksi); 486 ksi->ksi_signo = SIGILL; 487 ksi->ksi_trap = EXC_PGM; 488 if (tf->tf_esr & ESR_PIL) 489 ksi->ksi_code = ILL_ILLOPC; 490 else if (tf->tf_esr & ESR_PPR) 491 ksi->ksi_code = ILL_PRVOPC; 492 else if (tf->tf_esr & ESR_PTR) 493 ksi->ksi_code = ILL_ILLTRP; 494 else 495 ksi->ksi_code = 0; 496 ksi->ksi_addr = (void *)tf->tf_srr0; 497 } 498 return rv; 499 } 500 501 static int 502 embedded_fp_data_exception(struct trapframe *tf, ksiginfo_t *ksi) 503 { 504 struct cpu_info * const ci = curcpu(); 505 int rv = EFAULT; 506 507 ci->ci_ev_fpu.ev_count++; 508 509 if (rv != 0 && usertrap_p(tf)) { 510 KSI_INIT_TRAP(ksi); 511 #ifdef PPC_HAVE_SPE 512 ksi->ksi_signo = SIGFPE; 513 ksi->ksi_trap = tf->tf_exc; 514 ksi->ksi_code = vec_siginfo_code(tf); 515 #else 516 ksi->ksi_signo = SIGILL; 517 ksi->ksi_trap = EXC_PGM; 518 ksi->ksi_code = ILL_ILLOPC; 519 #endif 520 ksi->ksi_addr = (void *)tf->tf_srr0; 521 } 522 return rv; 523 } 524 525 static int 526 embedded_fp_round_exception(struct trapframe *tf, ksiginfo_t *ksi) 527 { 528 struct cpu_info * const ci = curcpu(); 529 int rv = EDOM; 530 531 ci->ci_ev_fpu.ev_count++; 532 533 if (rv != 0 && usertrap_p(tf)) { 534 KSI_INIT_TRAP(ksi); 535 #ifdef PPC_HAVE_SPE 536 ksi->ksi_signo = SIGFPE; 537 ksi->ksi_trap = tf->tf_exc; 538 ksi->ksi_code = vec_siginfo_code(tf); 539 #else 540 ksi->ksi_signo = SIGILL; 541 ksi->ksi_trap = EXC_PGM; 542 ksi->ksi_code = ILL_ILLOPC; 543 #endif 544 ksi->ksi_addr = (void *)tf->tf_srr0; 545 } 546 return rv; 547 } 548 549 static void 550 dump_trapframe(const struct trapframe *tf) 551 { 552 printf("trapframe %p (exc=%x srr0/1=%#lx/%#lx esr/dear=%#x/%#lx)\n", 553 tf, tf->tf_exc, tf->tf_srr0, tf->tf_srr1, tf->tf_esr, tf->tf_dear); 554 printf("lr =%08lx ctr=%08lx cr =%08x xer=%08x\n", 555 tf->tf_lr, tf->tf_ctr, tf->tf_cr, tf->tf_xer); 556 for (u_int r = 0; r < 32; r += 4) { 557 printf("r%02u=%08lx r%02u=%08lx r%02u=%08lx r%02u=%08lx\n", 558 r+0, tf->tf_fixreg[r+0], r+1, tf->tf_fixreg[r+1], 559 r+2, tf->tf_fixreg[r+2], r+3, tf->tf_fixreg[r+3]); 560 } 561 } 562 static bool 563 ddb_exception(struct trapframe *tf) 564 { 565 #if 0 566 const register_t ddb_trapfunc = (uintptr_t) cpu_Debugger; 567 if ((tf->tf_esr & ESR_PTR) == 0) 568 return false; 569 if (ddb_trapfunc <= tf->tf_srr0 && tf->tf_srr0 <= ddb_trapfunc+16) { 570 register_t srr0 = tf->tf_srr0; 571 if (kdb_trap(tf->tf_exc, tf)) { 572 if (srr0 == tf->tf_srr0) 573 tf->tf_srr0 += 4; 574 return true; 575 } 576 } 577 return false; 578 #else 579 struct cpu_info * const ci = curcpu(); 580 struct cpu_softc * const cpu = ci->ci_softc; 581 printf("CPL stack:"); 582 if (ci->ci_idepth >= 0) { 583 for (u_int i = 0; i <= ci->ci_idepth; i++) { 584 printf(" [%u]=%u", i, cpu->cpu_pcpls[i]); 585 } 586 } 587 printf(" %u\n", ci->ci_cpl); 588 dump_trapframe(tf); 589 if (kdb_trap(tf->tf_exc, tf)) { 590 tf->tf_srr0 += 4; 591 return true; 592 } 593 return false; 594 #endif 595 } 596 597 static bool 598 onfaulted(struct trapframe *tf, register_t rv) 599 { 600 struct lwp * const l = curlwp; 601 struct pcb * const pcb = lwp_getpcb(l); 602 struct faultbuf * const fb = pcb->pcb_onfault; 603 if (fb == NULL) 604 return false; 605 tf->tf_srr0 = fb->fb_pc; 606 tf->tf_srr1 = fb->fb_msr; 607 tf->tf_cr = fb->fb_cr; 608 tf->tf_fixreg[1] = fb->fb_sp; 609 tf->tf_fixreg[2] = fb->fb_r2; 610 tf->tf_fixreg[3] = rv; 611 pcb->pcb_onfault = NULL; 612 return true; 613 } 614 615 void 616 trap(enum ppc_booke_exceptions trap_code, struct trapframe *tf) 617 { 618 const bool usertrap = usertrap_p(tf); 619 struct cpu_info * const ci = curcpu(); 620 struct lwp * const l = curlwp; 621 struct proc * const p = l->l_proc; 622 ksiginfo_t ksi; 623 int rv = EACCES; 624 625 ci->ci_ev_traps.ev_count++; 626 ci->ci_data.cpu_ntrap++; 627 628 KASSERTMSG(!usertrap || tf == trapframe(l), 629 ("trap: tf=%p is invalid: trapframe(%p)=%p", tf, l, trapframe(l))); 630 631 #if 0 632 if (trap_code != T_PROGRAM || usertrap) 633 printf("trap(enter): %s (tf=%p, esr/dear=%#x/%#lx, srr0/1=%#lx/%#lx, lr=%#lx)\n", 634 trap_names[trap_code], tf, tf->tf_esr, tf->tf_dear, 635 tf->tf_srr0, tf->tf_srr1, tf->tf_lr); 636 #endif 637 #if 0 638 if ((register_t)tf >= (register_t)l->l_addr + USPACE 639 || (register_t)tf < (register_t)l->l_addr + PAGE_SIZE) { 640 printf("%s(entry): pid %d.%d (%s): invalid tf addr %p\n", 641 __func__, p->p_pid, l->l_lid, p->p_comm, tf); 642 dump_trapframe(tf); 643 Debugger(); 644 } 645 #endif 646 #if 0 647 if ((mfmsr() & PSL_CE) == 0) { 648 printf("%s(entry): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 649 __func__, p->p_pid, l->l_lid, p->p_comm, 650 trap_names[trap_code], mfmsr()); 651 dump_trapframe(tf); 652 } 653 #endif 654 655 if (usertrap && (tf->tf_fixreg[1] & 0x80000000)) { 656 printf("%s(entry): pid %d.%d (%s): %s invalid sp %#lx (sprg1=%#lx)\n", 657 __func__, p->p_pid, l->l_lid, p->p_comm, 658 trap_names[trap_code], tf->tf_fixreg[1], mfspr(SPR_SPRG1)); 659 dump_trapframe(tf); 660 Debugger(); 661 } 662 663 if (usertrap && (tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 664 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 665 __func__, p->p_pid, l->l_lid, p->p_comm, 666 trap_names[trap_code], tf->tf_srr1); 667 dump_trapframe(tf); 668 Debugger(); 669 } 670 671 switch (trap_code) { 672 case T_CRITIAL_INPUT: 673 case T_EXTERNAL_INPUT: 674 case T_DECREMENTER: 675 case T_FIXED_INTERVAL: 676 case T_WATCHDOG: 677 case T_SYSTEM_CALL: 678 default: 679 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 680 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 681 case T_MACHINE_CHECK: 682 rv = mchk_exception(tf, &ksi); 683 break; 684 case T_DSI: 685 rv = dsi_exception(tf, &ksi); 686 break; 687 case T_ISI: 688 rv = isi_exception(tf, &ksi); 689 break; 690 case T_ALIGNMENT: 691 rv = ali_exception(tf, &ksi); 692 break; 693 case T_SPE_UNAVAILABLE: 694 rv = spe_exception(tf, &ksi); 695 break; 696 case T_PROGRAM: 697 #ifdef DDB 698 if (!usertrap && ddb_exception(tf)) 699 return; 700 #endif 701 rv = pgm_exception(tf, &ksi); 702 break; 703 case T_FP_UNAVAILABLE: 704 case T_AP_UNAVAILABLE: 705 panic("trap: unexcepted trap code %d! (tf=%p, srr0/1=%#lx/%#lx)", 706 trap_code, tf, tf->tf_srr0, tf->tf_srr1); 707 case T_DATA_TLB_ERROR: 708 rv = dtlb_exception(tf, &ksi); 709 break; 710 case T_INSTRUCTION_TLB_ERROR: 711 rv = itlb_exception(tf, &ksi); 712 break; 713 case T_DEBUG: 714 case T_EMBEDDED_FP_DATA: 715 rv = embedded_fp_data_exception(tf, &ksi); 716 break; 717 case T_EMBEDDED_FP_ROUND: 718 rv = embedded_fp_round_exception(tf, &ksi); 719 break; 720 case T_EMBEDDED_PERF_MONITOR: 721 //db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 722 dump_trapframe(tf); 723 rv = EPERM; 724 break; 725 case T_AST: 726 KASSERT(usertrap); 727 ci->ci_astpending = 0; /* we are about to do it */ 728 ci->ci_data.cpu_nsoft++; 729 if (l->l_pflag & LP_OWEUPC) { 730 l->l_pflag &= ~LP_OWEUPC; 731 ADDUPROF(l); 732 } 733 /* Check whether we are being preempted. */ 734 if (ci->ci_want_resched) 735 preempt(); 736 if (tf->tf_fixreg[1] & 0x80000000) { 737 printf("%s(ast-exit): pid %d.%d (%s): invalid sp %#lx\n", 738 __func__, p->p_pid, l->l_lid, p->p_comm, 739 tf->tf_fixreg[1]); 740 dump_trapframe(tf); 741 Debugger(); 742 } 743 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 744 printf("%s(entry): pid %d.%d (%s): %s invalid PSL %#lx\n", 745 __func__, p->p_pid, l->l_lid, p->p_comm, 746 trap_names[trap_code], tf->tf_srr1); 747 dump_trapframe(tf); 748 Debugger(); 749 } 750 #if 0 751 if ((mfmsr() & PSL_CE) == 0) { 752 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 753 __func__, p->p_pid, l->l_lid, p->p_comm, 754 trap_names[trap_code], mfmsr()); 755 dump_trapframe(tf); 756 } 757 #endif 758 userret(l, tf); 759 return; 760 } 761 if (!usertrap) { 762 if (rv != 0) { 763 if (!onfaulted(tf, rv)) { 764 db_stack_trace_print(tf->tf_fixreg[1], true, 40, "", printf); 765 dump_trapframe(tf); 766 panic("%s: pid %d.%d (%s): %s exception in kernel mode" 767 " (tf=%p, dear=%#lx, esr=%#x," 768 " srr0/1=%#lx/%#lx)", 769 __func__, p->p_pid, l->l_lid, p->p_comm, 770 trap_names[trap_code], tf, tf->tf_dear, 771 tf->tf_esr, tf->tf_srr0, tf->tf_srr1); 772 } 773 } 774 #if 0 775 if (tf->tf_fixreg[1] >= (register_t)l->l_addr + USPACE 776 || tf->tf_fixreg[1] < (register_t)l->l_addr + PAGE_SIZE) { 777 printf("%s(exit): pid %d.%d (%s): invalid kern sp %#lx\n", 778 __func__, p->p_pid, l->l_lid, p->p_comm, 779 tf->tf_fixreg[1]); 780 dump_trapframe(tf); 781 Debugger(); 782 } 783 #endif 784 #if 0 785 if ((mfmsr() & PSL_CE) == 0) { 786 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 787 __func__, p->p_pid, l->l_lid, p->p_comm, 788 trap_names[trap_code], mfmsr()); 789 mtmsr(mfmsr()|PSL_CE); 790 dump_trapframe(tf); 791 } 792 #endif 793 } else { 794 if (rv == ENOMEM) { 795 printf("UVM: pid %d.%d (%s), uid %d killed: " 796 "out of swap\n", 797 p->p_pid, l->l_lid, p->p_comm, 798 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 799 ksi.ksi_signo = SIGKILL; 800 } 801 if (rv != 0) { 802 if (cpu_printfataltraps) { 803 printf("%s: pid %d.%d (%s):" 804 " %s exception in user mode\n", 805 __func__, p->p_pid, l->l_lid, p->p_comm, 806 trap_names[trap_code]); 807 if (cpu_printfataltraps > 1) 808 dump_trapframe(tf); 809 } 810 (*p->p_emul->e_trapsignal)(l, &ksi); 811 } 812 #ifdef DEBUG 813 if ((tf->tf_srr1 & (PSL_DS|PSL_IS)) != (PSL_DS|PSL_IS)) { 814 printf("%s(exit): pid %d.%d (%s): %s invalid PSL %#lx\n", 815 __func__, p->p_pid, l->l_lid, p->p_comm, 816 trap_names[trap_code], tf->tf_srr1); 817 dump_trapframe(tf); 818 Debugger(); 819 } 820 #endif 821 #if 0 822 if ((mfmsr() & PSL_CE) == 0) { 823 printf("%s(exit): pid %d.%d (%s): %s: PSL_CE (%#lx) not set\n", 824 __func__, p->p_pid, l->l_lid, p->p_comm, 825 trap_names[trap_code], mfmsr()); 826 dump_trapframe(tf); 827 } 828 #endif 829 userret(l, tf); 830 } 831 } 832 833 void 834 upcallret(struct lwp *l) 835 { 836 837 mi_userret(l); /* Invoke MI userret code */ 838 } 839 840 /* 841 * Start a new LWP 842 */ 843 void 844 startlwp(void *arg) 845 { 846 ucontext_t * const uc = arg; 847 struct lwp * const l = curlwp; 848 849 int error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 850 KASSERT(error); 851 (void)error; 852 kmem_free(uc, sizeof(ucontext_t)); 853 upcallret(l); 854 } 855