trap.c revision 271113
1/*- 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/trap.c 271113 2014-09-04 18:24:47Z nwhitehorn $"); 36 37#include "opt_kdtrace.h" 38 39#include <sys/param.h> 40#include <sys/kdb.h> 41#include <sys/proc.h> 42#include <sys/ktr.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/pioctl.h> 46#include <sys/ptrace.h> 47#include <sys/reboot.h> 48#include <sys/syscall.h> 49#include <sys/sysent.h> 50#include <sys/systm.h> 51#include <sys/uio.h> 52#include <sys/signalvar.h> 53#include <sys/vmmeter.h> 54 55#include <security/audit/audit.h> 56 57#include <vm/vm.h> 58#include <vm/pmap.h> 59#include <vm/vm_extern.h> 60#include <vm/vm_param.h> 61#include <vm/vm_kern.h> 62#include <vm/vm_map.h> 63#include <vm/vm_page.h> 64 65#include <machine/_inttypes.h> 66#include <machine/altivec.h> 67#include <machine/cpu.h> 68#include <machine/db_machdep.h> 69#include <machine/fpu.h> 70#include <machine/frame.h> 71#include <machine/pcb.h> 72#include <machine/pmap.h> 73#include <machine/psl.h> 74#include <machine/trap.h> 75#include <machine/spr.h> 76#include <machine/sr.h> 77 78static void trap_fatal(struct trapframe *frame); 79static void printtrap(u_int vector, struct trapframe *frame, int isfatal, 80 int user); 81static int trap_pfault(struct trapframe *frame, int user); 82static int fix_unaligned(struct thread *td, struct trapframe *frame); 83static int handle_onfault(struct trapframe *frame); 84static void syscall(struct trapframe *frame); 85 86#ifdef __powerpc64__ 87 void handle_kernel_slb_spill(int, register_t, register_t); 88static int handle_user_slb_spill(pmap_t pm, vm_offset_t addr); 89extern int n_slbs; 90#endif 91 92struct powerpc_exception { 93 u_int vector; 94 char *name; 95}; 96 97#ifdef KDTRACE_HOOKS 98#include <sys/dtrace_bsd.h> 99 100int (*dtrace_invop_jump_addr)(struct trapframe *); 101#endif 102 103static struct powerpc_exception powerpc_exceptions[] = { 104 { 0x0100, "system reset" }, 105 { 0x0200, "machine check" }, 106 { 0x0300, "data storage interrupt" }, 107 { 0x0380, "data segment exception" }, 108 { 0x0400, "instruction storage interrupt" }, 109 { 0x0480, "instruction segment exception" }, 110 { 0x0500, "external interrupt" }, 111 { 0x0600, "alignment" }, 112 { 0x0700, "program" }, 113 { 0x0800, "floating-point unavailable" }, 114 { 0x0900, "decrementer" }, 115 { 0x0c00, "system call" }, 116 { 0x0d00, "trace" }, 117 { 0x0e00, "floating-point assist" }, 118 { 0x0f00, "performance monitoring" }, 119 { 0x0f20, "altivec unavailable" }, 120 { 0x1000, "instruction tlb miss" }, 121 { 0x1100, "data load tlb miss" }, 122 { 0x1200, "data store tlb miss" }, 123 { 0x1300, "instruction breakpoint" }, 124 { 0x1400, "system management" }, 125 { 0x1600, "altivec assist" }, 126 { 0x1700, "thermal management" }, 127 { 0x2000, "run mode/trace" }, 128 { 0x3000, NULL } 129}; 130 131static const char * 132trapname(u_int vector) 133{ 134 struct powerpc_exception *pe; 135 136 for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) { 137 if (pe->vector == vector) 138 return (pe->name); 139 } 140 141 return ("unknown"); 142} 143 144void 145trap(struct trapframe *frame) 146{ 147 struct thread *td; 148 struct proc *p; 149#ifdef KDTRACE_HOOKS 150 uint32_t inst; 151#endif 152 int sig, type, user; 153 u_int ucode; 154 ksiginfo_t ksi; 155 156 PCPU_INC(cnt.v_trap); 157 158 td = curthread; 159 p = td->td_proc; 160 161 type = ucode = frame->exc; 162 sig = 0; 163 user = frame->srr1 & PSL_PR; 164 165 CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name, 166 trapname(type), user ? "user" : "kernel"); 167 168#ifdef KDTRACE_HOOKS 169 /* 170 * A trap can occur while DTrace executes a probe. Before 171 * executing the probe, DTrace blocks re-scheduling and sets 172 * a flag in it's per-cpu flags to indicate that it doesn't 173 * want to fault. On returning from the probe, the no-fault 174 * flag is cleared and finally re-scheduling is enabled. 175 * 176 * If the DTrace kernel module has registered a trap handler, 177 * call it and if it returns non-zero, assume that it has 178 * handled the trap and modified the trap frame so that this 179 * function can return normally. 180 */ 181 /* 182 * XXXDTRACE: add pid probe handler here (if ever) 183 */ 184 if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type)) 185 return; 186#endif 187 188 if (user) { 189 td->td_pticks = 0; 190 td->td_frame = frame; 191 if (td->td_ucred != p->p_ucred) 192 cred_update_thread(td); 193 194 /* User Mode Traps */ 195 switch (type) { 196 case EXC_RUNMODETRC: 197 case EXC_TRC: 198 frame->srr1 &= ~PSL_SE; 199 sig = SIGTRAP; 200 break; 201 202#ifdef __powerpc64__ 203 case EXC_ISE: 204 case EXC_DSE: 205 if (handle_user_slb_spill(&p->p_vmspace->vm_pmap, 206 (type == EXC_ISE) ? frame->srr0 : 207 frame->cpu.aim.dar) != 0) 208 sig = SIGSEGV; 209 break; 210#endif 211 case EXC_DSI: 212 case EXC_ISI: 213 sig = trap_pfault(frame, 1); 214 break; 215 216 case EXC_SC: 217 syscall(frame); 218 break; 219 220 case EXC_FPU: 221 KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU, 222 ("FPU already enabled for thread")); 223 enable_fpu(td); 224 break; 225 226 case EXC_VEC: 227 KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC, 228 ("Altivec already enabled for thread")); 229 enable_vec(td); 230 break; 231 232 case EXC_VECAST_G4: 233 case EXC_VECAST_G5: 234 /* 235 * We get a VPU assist exception for IEEE mode 236 * vector operations on denormalized floats. 237 * Emulating this is a giant pain, so for now, 238 * just switch off IEEE mode and treat them as 239 * zero. 240 */ 241 242 save_vec(td); 243 td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ; 244 enable_vec(td); 245 break; 246 247 case EXC_ALI: 248 if (fix_unaligned(td, frame) != 0) 249 sig = SIGBUS; 250 else 251 frame->srr0 += 4; 252 break; 253 254 case EXC_PGM: 255 /* Identify the trap reason */ 256 if (frame->srr1 & EXC_PGM_TRAP) { 257#ifdef KDTRACE_HOOKS 258 inst = fuword32((const void *)frame->srr0); 259 if (inst == 0x0FFFDDDD && dtrace_pid_probe_ptr != NULL) { 260 struct reg regs; 261 fill_regs(td, ®s); 262 (*dtrace_pid_probe_ptr)(®s); 263 break; 264 } 265#endif 266 sig = SIGTRAP; 267 } else { 268 sig = ppc_instr_emulate(frame, td->td_pcb); 269 } 270 break; 271 272 case EXC_MCHK: 273 /* 274 * Note that this may not be recoverable for the user 275 * process, depending on the type of machine check, 276 * but it at least prevents the kernel from dying. 277 */ 278 sig = SIGBUS; 279 break; 280 281 default: 282 trap_fatal(frame); 283 } 284 } else { 285 /* Kernel Mode Traps */ 286 287 KASSERT(cold || td->td_ucred != NULL, 288 ("kernel trap doesn't have ucred")); 289 switch (type) { 290#ifdef KDTRACE_HOOKS 291 case EXC_PGM: 292 if (frame->srr1 & EXC_PGM_TRAP) { 293 if (*(uint32_t *)frame->srr0 == 0x7c810808) { 294 if (dtrace_invop_jump_addr != NULL) { 295 dtrace_invop_jump_addr(frame); 296 return; 297 } 298 } 299 } 300 break; 301#endif 302#ifdef __powerpc64__ 303 case EXC_DSE: 304 if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) { 305 __asm __volatile ("slbmte %0, %1" :: 306 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), 307 "r"(USER_SLB_SLBE)); 308 return; 309 } 310 break; 311#endif 312 case EXC_DSI: 313 if (trap_pfault(frame, 0) == 0) 314 return; 315 break; 316 case EXC_MCHK: 317 if (handle_onfault(frame)) 318 return; 319 break; 320 default: 321 break; 322 } 323 trap_fatal(frame); 324 } 325 326 if (sig != 0) { 327 if (p->p_sysent->sv_transtrap != NULL) 328 sig = (p->p_sysent->sv_transtrap)(sig, type); 329 ksiginfo_init_trap(&ksi); 330 ksi.ksi_signo = sig; 331 ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ 332 /* ksi.ksi_addr = ? */ 333 ksi.ksi_trapno = type; 334 trapsignal(td, &ksi); 335 } 336 337 userret(td, frame); 338} 339 340static void 341trap_fatal(struct trapframe *frame) 342{ 343 344 printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); 345#ifdef KDB 346 if ((debugger_on_panic || kdb_active) && 347 kdb_trap(frame->exc, 0, frame)) 348 return; 349#endif 350 panic("%s trap", trapname(frame->exc)); 351} 352 353static void 354printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) 355{ 356 357 printf("\n"); 358 printf("%s %s trap:\n", isfatal ? "fatal" : "handled", 359 user ? "user" : "kernel"); 360 printf("\n"); 361 printf(" exception = 0x%x (%s)\n", vector, trapname(vector)); 362 switch (vector) { 363 case EXC_DSE: 364 case EXC_DSI: 365 printf(" virtual address = 0x%" PRIxPTR "\n", 366 frame->cpu.aim.dar); 367 printf(" dsisr = 0x%" PRIxPTR "\n", 368 frame->cpu.aim.dsisr); 369 break; 370 case EXC_ISE: 371 case EXC_ISI: 372 printf(" virtual address = 0x%" PRIxPTR "\n", frame->srr0); 373 break; 374 } 375 printf(" srr0 = 0x%" PRIxPTR "\n", frame->srr0); 376 printf(" srr1 = 0x%" PRIxPTR "\n", frame->srr1); 377 printf(" lr = 0x%" PRIxPTR "\n", frame->lr); 378 printf(" curthread = %p\n", curthread); 379 if (curthread != NULL) 380 printf(" pid = %d, comm = %s\n", 381 curthread->td_proc->p_pid, curthread->td_name); 382 printf("\n"); 383} 384 385/* 386 * Handles a fatal fault when we have onfault state to recover. Returns 387 * non-zero if there was onfault recovery state available. 388 */ 389static int 390handle_onfault(struct trapframe *frame) 391{ 392 struct thread *td; 393 faultbuf *fb; 394 395 td = curthread; 396 fb = td->td_pcb->pcb_onfault; 397 if (fb != NULL) { 398 frame->srr0 = (*fb)[0]; 399 frame->fixreg[1] = (*fb)[1]; 400 frame->fixreg[2] = (*fb)[2]; 401 frame->fixreg[3] = 1; 402 frame->cr = (*fb)[3]; 403 bcopy(&(*fb)[4], &frame->fixreg[13], 404 19 * sizeof(register_t)); 405 return (1); 406 } 407 return (0); 408} 409 410int 411cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) 412{ 413 struct proc *p; 414 struct trapframe *frame; 415 caddr_t params; 416 size_t argsz; 417 int error, n, i; 418 419 p = td->td_proc; 420 frame = td->td_frame; 421 422 sa->code = frame->fixreg[0]; 423 params = (caddr_t)(frame->fixreg + FIRSTARG); 424 n = NARGREG; 425 426 if (sa->code == SYS_syscall) { 427 /* 428 * code is first argument, 429 * followed by actual args. 430 */ 431 sa->code = *(register_t *) params; 432 params += sizeof(register_t); 433 n -= 1; 434 } else if (sa->code == SYS___syscall) { 435 /* 436 * Like syscall, but code is a quad, 437 * so as to maintain quad alignment 438 * for the rest of the args. 439 */ 440 if (SV_PROC_FLAG(p, SV_ILP32)) { 441 params += sizeof(register_t); 442 sa->code = *(register_t *) params; 443 params += sizeof(register_t); 444 n -= 2; 445 } else { 446 sa->code = *(register_t *) params; 447 params += sizeof(register_t); 448 n -= 1; 449 } 450 } 451 452 if (p->p_sysent->sv_mask) 453 sa->code &= p->p_sysent->sv_mask; 454 if (sa->code >= p->p_sysent->sv_size) 455 sa->callp = &p->p_sysent->sv_table[0]; 456 else 457 sa->callp = &p->p_sysent->sv_table[sa->code]; 458 459 sa->narg = sa->callp->sy_narg; 460 461 if (SV_PROC_FLAG(p, SV_ILP32)) { 462 argsz = sizeof(uint32_t); 463 464 for (i = 0; i < n; i++) 465 sa->args[i] = ((u_register_t *)(params))[i] & 466 0xffffffff; 467 } else { 468 argsz = sizeof(uint64_t); 469 470 for (i = 0; i < n; i++) 471 sa->args[i] = ((u_register_t *)(params))[i]; 472 } 473 474 if (sa->narg > n) 475 error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n, 476 (sa->narg - n) * argsz); 477 else 478 error = 0; 479 480#ifdef __powerpc64__ 481 if (SV_PROC_FLAG(p, SV_ILP32) && sa->narg > n) { 482 /* Expand the size of arguments copied from the stack */ 483 484 for (i = sa->narg; i >= n; i--) 485 sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n]; 486 } 487#endif 488 489 if (error == 0) { 490 td->td_retval[0] = 0; 491 td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; 492 } 493 return (error); 494} 495 496#include "../../kern/subr_syscall.c" 497 498void 499syscall(struct trapframe *frame) 500{ 501 struct thread *td; 502 struct syscall_args sa; 503 int error; 504 505 td = curthread; 506 td->td_frame = frame; 507 508#ifdef __powerpc64__ 509 /* 510 * Speculatively restore last user SLB segment, which we know is 511 * invalid already, since we are likely to do copyin()/copyout(). 512 */ 513 __asm __volatile ("slbmte %0, %1; isync" :: 514 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE)); 515#endif 516 517 error = syscallenter(td, &sa); 518 syscallret(td, error, &sa); 519} 520 521#ifdef __powerpc64__ 522/* Handle kernel SLB faults -- runs in real mode, all seat belts off */ 523void 524handle_kernel_slb_spill(int type, register_t dar, register_t srr0) 525{ 526 struct slb *slbcache; 527 uint64_t slbe, slbv; 528 uint64_t esid, addr; 529 int i; 530 531 addr = (type == EXC_ISE) ? srr0 : dar; 532 slbcache = PCPU_GET(slb); 533 esid = (uintptr_t)addr >> ADDR_SR_SHFT; 534 slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID; 535 536 /* See if the hardware flushed this somehow (can happen in LPARs) */ 537 for (i = 0; i < n_slbs; i++) 538 if (slbcache[i].slbe == (slbe | (uint64_t)i)) 539 return; 540 541 /* Not in the map, needs to actually be added */ 542 slbv = kernel_va_to_slbv(addr); 543 if (slbcache[USER_SLB_SLOT].slbe == 0) { 544 for (i = 0; i < n_slbs; i++) { 545 if (i == USER_SLB_SLOT) 546 continue; 547 if (!(slbcache[i].slbe & SLBE_VALID)) 548 goto fillkernslb; 549 } 550 551 if (i == n_slbs) 552 slbcache[USER_SLB_SLOT].slbe = 1; 553 } 554 555 /* Sacrifice a random SLB entry that is not the user entry */ 556 i = mftb() % n_slbs; 557 if (i == USER_SLB_SLOT) 558 i = (i+1) % n_slbs; 559 560fillkernslb: 561 /* Write new entry */ 562 slbcache[i].slbv = slbv; 563 slbcache[i].slbe = slbe | (uint64_t)i; 564 565 /* Trap handler will restore from cache on exit */ 566} 567 568static int 569handle_user_slb_spill(pmap_t pm, vm_offset_t addr) 570{ 571 struct slb *user_entry; 572 uint64_t esid; 573 int i; 574 575 esid = (uintptr_t)addr >> ADDR_SR_SHFT; 576 577 PMAP_LOCK(pm); 578 user_entry = user_va_to_slb_entry(pm, addr); 579 580 if (user_entry == NULL) { 581 /* allocate_vsid auto-spills it */ 582 (void)allocate_user_vsid(pm, esid, 0); 583 } else { 584 /* 585 * Check that another CPU has not already mapped this. 586 * XXX: Per-thread SLB caches would be better. 587 */ 588 for (i = 0; i < pm->pm_slb_len; i++) 589 if (pm->pm_slb[i] == user_entry) 590 break; 591 592 if (i == pm->pm_slb_len) 593 slb_insert_user(pm, user_entry); 594 } 595 PMAP_UNLOCK(pm); 596 597 return (0); 598} 599#endif 600 601static int 602trap_pfault(struct trapframe *frame, int user) 603{ 604 vm_offset_t eva, va; 605 struct thread *td; 606 struct proc *p; 607 vm_map_t map; 608 vm_prot_t ftype; 609 int rv; 610 register_t user_sr; 611 612 td = curthread; 613 p = td->td_proc; 614 if (frame->exc == EXC_ISI) { 615 eva = frame->srr0; 616 ftype = VM_PROT_EXECUTE; 617 if (frame->srr1 & SRR1_ISI_PFAULT) 618 ftype |= VM_PROT_READ; 619 } else { 620 eva = frame->cpu.aim.dar; 621 if (frame->cpu.aim.dsisr & DSISR_STORE) 622 ftype = VM_PROT_WRITE; 623 else 624 ftype = VM_PROT_READ; 625 } 626 627 if (user) { 628 map = &p->p_vmspace->vm_map; 629 } else { 630 if ((eva >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) { 631 if (p->p_vmspace == NULL) 632 return (SIGSEGV); 633 634 map = &p->p_vmspace->vm_map; 635 636 user_sr = td->td_pcb->pcb_cpu.aim.usr_segm; 637 eva &= ADDR_PIDX | ADDR_POFF; 638 eva |= user_sr << ADDR_SR_SHFT; 639 } else { 640 map = kernel_map; 641 } 642 } 643 va = trunc_page(eva); 644 645 if (map != kernel_map) { 646 /* 647 * Keep swapout from messing with us during this 648 * critical time. 649 */ 650 PROC_LOCK(p); 651 ++p->p_lock; 652 PROC_UNLOCK(p); 653 654 /* Fault in the user page: */ 655 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); 656 657 PROC_LOCK(p); 658 --p->p_lock; 659 PROC_UNLOCK(p); 660 /* 661 * XXXDTRACE: add dtrace_doubletrap_func here? 662 */ 663 } else { 664 /* 665 * Don't have to worry about process locking or stacks in the 666 * kernel. 667 */ 668 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); 669 } 670 671 if (rv == KERN_SUCCESS) 672 return (0); 673 674 if (!user && handle_onfault(frame)) 675 return (0); 676 677 return (SIGSEGV); 678} 679 680/* 681 * For now, this only deals with the particular unaligned access case 682 * that gcc tends to generate. Eventually it should handle all of the 683 * possibilities that can happen on a 32-bit PowerPC in big-endian mode. 684 */ 685 686static int 687fix_unaligned(struct thread *td, struct trapframe *frame) 688{ 689 struct thread *fputhread; 690 int indicator, reg; 691 double *fpr; 692 693 indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr); 694 695 switch (indicator) { 696 case EXC_ALI_LFD: 697 case EXC_ALI_STFD: 698 reg = EXC_ALI_RST(frame->cpu.aim.dsisr); 699 fpr = &td->td_pcb->pcb_fpu.fpr[reg]; 700 fputhread = PCPU_GET(fputhread); 701 702 /* Juggle the FPU to ensure that we've initialized 703 * the FPRs, and that their current state is in 704 * the PCB. 705 */ 706 if (fputhread != td) { 707 if (fputhread) 708 save_fpu(fputhread); 709 enable_fpu(td); 710 } 711 save_fpu(td); 712 713 if (indicator == EXC_ALI_LFD) { 714 if (copyin((void *)frame->cpu.aim.dar, fpr, 715 sizeof(double)) != 0) 716 return -1; 717 enable_fpu(td); 718 } else { 719 if (copyout(fpr, (void *)frame->cpu.aim.dar, 720 sizeof(double)) != 0) 721 return -1; 722 } 723 return 0; 724 break; 725 } 726 727 return -1; 728} 729 730