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/param.h> 35 #include <sys/kdb.h> 36 #include <sys/proc.h> 37 #include <sys/ktr.h> 38 #include <sys/lock.h> 39 #include <sys/mutex.h> 40 #include <sys/ptrace.h> 41 #include <sys/reboot.h> 42 #include <sys/syscall.h> 43 #include <sys/sysent.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/uio.h> 47 #include <sys/signalvar.h> 48 #include <sys/vmmeter.h> 49 50 #include <security/audit/audit.h> 51 52 #include <vm/vm.h> 53 #include <vm/pmap.h> 54 #include <vm/vm_extern.h> 55 #include <vm/vm_param.h> 56 #include <vm/vm_kern.h> 57 #include <vm/vm_map.h> 58 #include <vm/vm_page.h> 59 60 #include <machine/_inttypes.h> 61 #include <machine/altivec.h> 62 #include <machine/cpu.h> 63 #include <machine/db_machdep.h> 64 #include <machine/fpu.h> 65 #include <machine/frame.h> 66 #include <machine/pcb.h> 67 #include <machine/psl.h> 68 #include <machine/slb.h> 69 #include <machine/spr.h> 70 #include <machine/sr.h> 71 #include <machine/trap.h> 72 73 /* Below matches setjmp.S */ 74 #define FAULTBUF_LR 21 75 #define FAULTBUF_R1 1 76 #define FAULTBUF_R2 2 77 #define FAULTBUF_CR 22 78 #define FAULTBUF_R14 3 79 80 #define MOREARGS(sp) ((caddr_t)((uintptr_t)(sp) + \ 81 sizeof(struct callframe) - 3*sizeof(register_t))) /* more args go here */ 82 83 static void trap_fatal(struct trapframe *frame); 84 static void printtrap(u_int vector, struct trapframe *frame, int isfatal, 85 int user); 86 static bool trap_pfault(struct trapframe *frame, bool user, int *signo, 87 int *ucode); 88 static int fix_unaligned(struct thread *td, struct trapframe *frame); 89 static int handle_onfault(struct trapframe *frame); 90 static void syscall(struct trapframe *frame); 91 92 #if defined(__powerpc64__) && defined(AIM) 93 static void normalize_inputs(void); 94 #endif 95 96 extern vm_offset_t __startkernel; 97 98 extern int copy_fault(void); 99 extern int fusufault(void); 100 101 #ifdef KDB 102 int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */ 103 #endif 104 105 struct powerpc_exception { 106 u_int vector; 107 char *name; 108 }; 109 110 #ifdef KDTRACE_HOOKS 111 #include <sys/dtrace_bsd.h> 112 113 int (*dtrace_invop_jump_addr)(struct trapframe *); 114 #endif 115 116 static struct powerpc_exception powerpc_exceptions[] = { 117 { EXC_CRIT, "critical input" }, 118 { EXC_RST, "system reset" }, 119 { EXC_MCHK, "machine check" }, 120 { EXC_DSI, "data storage interrupt" }, 121 { EXC_DSE, "data segment exception" }, 122 { EXC_ISI, "instruction storage interrupt" }, 123 { EXC_ISE, "instruction segment exception" }, 124 { EXC_EXI, "external interrupt" }, 125 { EXC_ALI, "alignment" }, 126 { EXC_PGM, "program" }, 127 { EXC_HEA, "hypervisor emulation assistance" }, 128 { EXC_FPU, "floating-point unavailable" }, 129 { EXC_APU, "auxiliary proc unavailable" }, 130 { EXC_DECR, "decrementer" }, 131 { EXC_FIT, "fixed-interval timer" }, 132 { EXC_WDOG, "watchdog timer" }, 133 { EXC_SC, "system call" }, 134 { EXC_TRC, "trace" }, 135 { EXC_FPA, "floating-point assist" }, 136 { EXC_DEBUG, "debug" }, 137 { EXC_PERF, "performance monitoring" }, 138 { EXC_VEC, "altivec unavailable" }, 139 { EXC_VSX, "vsx unavailable" }, 140 { EXC_FAC, "facility unavailable" }, 141 { EXC_HFAC, "hypervisor facility unavailable" }, 142 { EXC_ITMISS, "instruction tlb miss" }, 143 { EXC_DLMISS, "data load tlb miss" }, 144 { EXC_DSMISS, "data store tlb miss" }, 145 { EXC_BPT, "instruction breakpoint" }, 146 { EXC_SMI, "system management" }, 147 { EXC_VECAST_G4, "altivec assist" }, 148 { EXC_THRM, "thermal management" }, 149 { EXC_RUNMODETRC, "run mode/trace" }, 150 { EXC_SOFT_PATCH, "soft patch exception" }, 151 { EXC_HVI, "hypervisor virtualization" }, 152 { EXC_LAST, NULL } 153 }; 154 155 static int uprintf_signal; 156 SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RWTUN, 157 &uprintf_signal, 0, 158 "Print debugging information on trap signal to ctty"); 159 160 #define ESR_BITMASK \ 161 "\20" \ 162 "\040b0\037b1\036b2\035b3\034PIL\033PRR\032PTR\031FP" \ 163 "\030ST\027b9\026DLK\025ILK\024b12\023b13\022BO\021PIE" \ 164 "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23" \ 165 "\010SPE\007EPID\006b26\005b27\004b28\003b29\002b30\001b31" 166 #define MCSR_BITMASK \ 167 "\20" \ 168 "\040MCP\037ICERR\036DCERR\035TLBPERR\034L2MMU_MHIT\033b5\032b6\031b7" \ 169 "\030b8\027b9\026b10\025NMI\024MAV\023MEA\022b14\021IF" \ 170 "\020LD\017ST\016LDG\015b19\014b20\013b21\012b22\011b23" \ 171 "\010b24\007b25\006b26\005b27\004b28\003b29\002TLBSYNC\001BSL2_ERR" 172 #define MSSSR_BITMASK \ 173 "\20" \ 174 "\040b0\037b1\036b2\035b3\034b4\033b5\032b6\031b7" \ 175 "\030b8\027b9\026b10\025b11\024b12\023L2TAG\022L2DAT\021L3TAG" \ 176 "\020L3DAT\017APE\016DPE\015TEA\014b20\013b21\012b22\011b23" \ 177 "\010b24\007b25\006b26\005b27\004b28\003b29\002b30\001b31" 178 179 static const char * 180 trapname(u_int vector) 181 { 182 struct powerpc_exception *pe; 183 184 for (pe = powerpc_exceptions; pe->vector != EXC_LAST; pe++) { 185 if (pe->vector == vector) 186 return (pe->name); 187 } 188 189 return ("unknown"); 190 } 191 192 static inline bool 193 frame_is_trap_inst(struct trapframe *frame) 194 { 195 #ifdef AIM 196 return (frame->exc == EXC_PGM && frame->srr1 & EXC_PGM_TRAP); 197 #else 198 return ((frame->cpu.booke.esr & ESR_PTR) != 0); 199 #endif 200 } 201 202 void 203 trap(struct trapframe *frame) 204 { 205 struct thread *td; 206 struct proc *p; 207 #ifdef KDTRACE_HOOKS 208 uint32_t inst; 209 #endif 210 int sig, type, user; 211 u_int ucode; 212 ksiginfo_t ksi; 213 register_t addr, fscr; 214 215 VM_CNT_INC(v_trap); 216 217 #ifdef KDB 218 if (kdb_active) { 219 kdb_reenter(); 220 return; 221 } 222 #endif 223 224 td = curthread; 225 p = td->td_proc; 226 227 type = ucode = frame->exc; 228 sig = 0; 229 user = frame->srr1 & PSL_PR; 230 addr = 0; 231 232 CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name, 233 trapname(type), user ? "user" : "kernel"); 234 235 #ifdef KDTRACE_HOOKS 236 /* 237 * A trap can occur while DTrace executes a probe. Before 238 * executing the probe, DTrace blocks re-scheduling and sets 239 * a flag in its per-cpu flags to indicate that it doesn't 240 * want to fault. On returning from the probe, the no-fault 241 * flag is cleared and finally re-scheduling is enabled. 242 * 243 * If the DTrace kernel module has registered a trap handler, 244 * call it and if it returns non-zero, assume that it has 245 * handled the trap and modified the trap frame so that this 246 * function can return normally. 247 */ 248 if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type) != 0) 249 return; 250 #endif 251 252 if (user) { 253 td->td_pticks = 0; 254 td->td_frame = frame; 255 addr = frame->srr0; 256 if (td->td_cowgen != atomic_load_int(&p->p_cowgen)) 257 thread_cow_update(td); 258 259 /* User Mode Traps */ 260 switch (type) { 261 case EXC_RUNMODETRC: 262 case EXC_TRC: 263 frame->srr1 &= ~PSL_SE; 264 sig = SIGTRAP; 265 ucode = TRAP_TRACE; 266 break; 267 268 #if defined(__powerpc64__) && defined(AIM) 269 case EXC_DSE: 270 addr = frame->dar; 271 /* FALLTHROUGH */ 272 case EXC_ISE: 273 /* DSE/ISE are automatically fatal with radix pmap. */ 274 if (radix_mmu || 275 handle_user_slb_spill(&p->p_vmspace->vm_pmap, 276 addr) != 0){ 277 sig = SIGSEGV; 278 ucode = SEGV_MAPERR; 279 } 280 break; 281 #endif 282 case EXC_DSI: 283 addr = frame->dar; 284 /* FALLTHROUGH */ 285 case EXC_ISI: 286 if (trap_pfault(frame, true, &sig, &ucode)) 287 sig = 0; 288 break; 289 290 case EXC_SC: 291 syscall(frame); 292 break; 293 294 case EXC_FPU: 295 KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU, 296 ("FPU already enabled for thread")); 297 enable_fpu(td); 298 break; 299 300 case EXC_VEC: 301 KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC, 302 ("Altivec already enabled for thread")); 303 enable_vec(td); 304 break; 305 306 case EXC_VSX: 307 KASSERT((td->td_pcb->pcb_flags & PCB_VSX) != PCB_VSX, 308 ("VSX already enabled for thread")); 309 if (!(td->td_pcb->pcb_flags & PCB_VEC)) 310 enable_vec(td); 311 if (td->td_pcb->pcb_flags & PCB_FPU) 312 save_fpu(td); 313 td->td_pcb->pcb_flags |= PCB_VSX; 314 enable_fpu(td); 315 break; 316 317 case EXC_FAC: 318 fscr = mfspr(SPR_FSCR); 319 switch (fscr & FSCR_IC_MASK) { 320 case FSCR_IC_HTM: 321 CTR0(KTR_TRAP, 322 "Hardware Transactional Memory subsystem disabled"); 323 sig = SIGILL; 324 ucode = ILL_ILLOPC; 325 break; 326 case FSCR_IC_DSCR: 327 td->td_pcb->pcb_flags |= PCB_CFSCR | PCB_CDSCR; 328 fscr |= FSCR_DSCR; 329 mtspr(SPR_DSCR, 0); 330 break; 331 case FSCR_IC_EBB: 332 td->td_pcb->pcb_flags |= PCB_CFSCR; 333 fscr |= FSCR_EBB; 334 mtspr(SPR_EBBHR, 0); 335 mtspr(SPR_EBBRR, 0); 336 mtspr(SPR_BESCR, 0); 337 break; 338 case FSCR_IC_TAR: 339 td->td_pcb->pcb_flags |= PCB_CFSCR; 340 fscr |= FSCR_TAR; 341 mtspr(SPR_TAR, 0); 342 break; 343 case FSCR_IC_LM: 344 td->td_pcb->pcb_flags |= PCB_CFSCR; 345 fscr |= FSCR_LM; 346 mtspr(SPR_LMRR, 0); 347 mtspr(SPR_LMSER, 0); 348 break; 349 default: 350 sig = SIGILL; 351 ucode = ILL_ILLOPC; 352 } 353 mtspr(SPR_FSCR, fscr & ~FSCR_IC_MASK); 354 break; 355 case EXC_HEA: 356 case EXC_HFAC: 357 sig = SIGILL; 358 ucode = ILL_ILLOPC; 359 break; 360 361 case EXC_VECAST_E: 362 case EXC_VECAST_G4: 363 case EXC_VECAST_G5: 364 /* 365 * We get a VPU assist exception for IEEE mode 366 * vector operations on denormalized floats. 367 * Emulating this is a giant pain, so for now, 368 * just switch off IEEE mode and treat them as 369 * zero. 370 */ 371 372 save_vec(td); 373 td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ; 374 enable_vec(td); 375 break; 376 377 case EXC_ALI: 378 if (fix_unaligned(td, frame) != 0) { 379 sig = SIGBUS; 380 ucode = BUS_ADRALN; 381 addr = frame->dar; 382 } 383 else 384 frame->srr0 += 4; 385 break; 386 387 case EXC_DEBUG: /* Single stepping */ 388 mtspr(SPR_DBSR, mfspr(SPR_DBSR)); 389 frame->srr1 &= ~PSL_DE; 390 frame->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); 391 sig = SIGTRAP; 392 ucode = TRAP_TRACE; 393 break; 394 395 case EXC_PGM: 396 /* Identify the trap reason */ 397 if (frame_is_trap_inst(frame)) { 398 #ifdef KDTRACE_HOOKS 399 inst = fuword32((const void *)frame->srr0); 400 if (inst == 0x0FFFDDDD && 401 dtrace_pid_probe_ptr != NULL) { 402 (*dtrace_pid_probe_ptr)(frame); 403 break; 404 } 405 #endif 406 sig = SIGTRAP; 407 ucode = TRAP_BRKPT; 408 break; 409 } 410 411 if ((frame->srr1 & EXC_PGM_FPENABLED) && 412 (td->td_pcb->pcb_flags & PCB_FPU)) 413 sig = SIGFPE; 414 else 415 sig = ppc_instr_emulate(frame, td); 416 417 if (sig == SIGILL) { 418 if (frame->srr1 & EXC_PGM_PRIV) 419 ucode = ILL_PRVOPC; 420 else if (frame->srr1 & EXC_PGM_ILLEGAL) 421 ucode = ILL_ILLOPC; 422 } else if (sig == SIGFPE) { 423 ucode = get_fpu_exception(td); 424 } 425 426 break; 427 428 case EXC_MCHK: 429 sig = cpu_machine_check(td, frame, &ucode); 430 printtrap(frame->exc, frame, 0, (frame->srr1 & PSL_PR)); 431 break; 432 433 #if defined(__powerpc64__) && defined(AIM) 434 case EXC_SOFT_PATCH: 435 /* 436 * Point to the instruction that generated the exception to execute it again, 437 * and normalize the register values. 438 */ 439 frame->srr0 -= 4; 440 normalize_inputs(); 441 break; 442 #endif 443 444 default: 445 trap_fatal(frame); 446 } 447 } else { 448 /* Kernel Mode Traps */ 449 450 KASSERT(cold || td->td_ucred != NULL, 451 ("kernel trap doesn't have ucred")); 452 switch (type) { 453 case EXC_PGM: 454 #ifdef KDTRACE_HOOKS 455 if (frame_is_trap_inst(frame)) { 456 if (*(uint32_t *)frame->srr0 == EXC_DTRACE) { 457 if (dtrace_invop_jump_addr != NULL) { 458 dtrace_invop_jump_addr(frame); 459 return; 460 } 461 } 462 } 463 #endif 464 #ifdef KDB 465 if (db_trap_glue(frame)) 466 return; 467 #endif 468 break; 469 #if defined(__powerpc64__) && defined(AIM) 470 case EXC_DSE: 471 /* DSE on radix mmu is automatically fatal. */ 472 if (radix_mmu) 473 break; 474 if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0 && 475 (frame->dar & SEGMENT_MASK) == USER_ADDR) { 476 __asm __volatile ("slbmte %0, %1" :: 477 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), 478 "r"(USER_SLB_SLBE)); 479 return; 480 } 481 break; 482 #endif 483 case EXC_DSI: 484 if (trap_pfault(frame, false, NULL, NULL)) 485 return; 486 break; 487 case EXC_MCHK: 488 if (handle_onfault(frame)) 489 return; 490 break; 491 default: 492 break; 493 } 494 trap_fatal(frame); 495 } 496 497 if (sig != 0) { 498 ksiginfo_init_trap(&ksi); 499 ksi.ksi_signo = sig; 500 ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ 501 ksi.ksi_addr = (void *)addr; 502 ksi.ksi_trapno = type; 503 if (uprintf_signal) { 504 uprintf("pid %d comm %s: signal %d code %d type 0x%x " 505 "addr 0x%lx r1 0x%lx srr0 0x%lx srr1 0x%lx\n", 506 p->p_pid, p->p_comm, sig, ucode, type, 507 (u_long)addr, (u_long)frame->fixreg[1], 508 (u_long)frame->srr0, (u_long)frame->srr1); 509 } 510 511 trapsignal(td, &ksi); 512 } 513 514 userret(td, frame); 515 } 516 517 static void 518 trap_fatal(struct trapframe *frame) 519 { 520 #ifdef KDB 521 bool handled; 522 #endif 523 524 printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); 525 #ifdef KDB 526 if (debugger_on_trap) { 527 kdb_why = KDB_WHY_TRAP; 528 handled = kdb_trap(frame->exc, 0, frame); 529 kdb_why = KDB_WHY_UNSET; 530 if (handled) 531 return; 532 } 533 #endif 534 panic("%s trap", trapname(frame->exc)); 535 } 536 537 static void 538 cpu_printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) 539 { 540 #ifdef AIM 541 uint16_t ver; 542 543 switch (vector) { 544 case EXC_MCHK: 545 ver = mfpvr() >> 16; 546 if (MPC745X_P(ver)) 547 printf(" msssr0 = 0x%b\n", 548 (int)mfspr(SPR_MSSSR0), MSSSR_BITMASK); 549 case EXC_DSE: 550 case EXC_DSI: 551 case EXC_DTMISS: 552 printf(" dsisr = 0x%lx\n", 553 (u_long)frame->cpu.aim.dsisr); 554 break; 555 } 556 #elif defined(BOOKE) 557 vm_paddr_t pa; 558 559 switch (vector) { 560 case EXC_MCHK: 561 pa = mfspr(SPR_MCARU); 562 pa = (pa << 32) | (u_register_t)mfspr(SPR_MCAR); 563 printf(" mcsr = 0x%b\n", 564 (int)mfspr(SPR_MCSR), MCSR_BITMASK); 565 printf(" mcar = 0x%jx\n", (uintmax_t)pa); 566 } 567 printf(" esr = 0x%b\n", 568 (int)frame->cpu.booke.esr, ESR_BITMASK); 569 #endif 570 } 571 572 static void 573 printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) 574 { 575 576 printf("\n"); 577 printf("%s %s trap:\n", isfatal ? "fatal" : "handled", 578 user ? "user" : "kernel"); 579 printf("\n"); 580 printf(" exception = 0x%x (%s)\n", vector, trapname(vector)); 581 switch (vector) { 582 case EXC_DSE: 583 case EXC_DSI: 584 case EXC_DTMISS: 585 case EXC_ALI: 586 case EXC_MCHK: 587 printf(" virtual address = 0x%" PRIxPTR "\n", frame->dar); 588 break; 589 case EXC_ISE: 590 case EXC_ISI: 591 case EXC_ITMISS: 592 printf(" virtual address = 0x%" PRIxPTR "\n", frame->srr0); 593 break; 594 } 595 cpu_printtrap(vector, frame, isfatal, user); 596 printf(" srr0 = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n", 597 frame->srr0, frame->srr0 - (register_t)(__startkernel - KERNBASE)); 598 printf(" srr1 = 0x%lx\n", (u_long)frame->srr1); 599 printf(" current msr = 0x%" PRIxPTR "\n", mfmsr()); 600 printf(" lr = 0x%" PRIxPTR " (0x%" PRIxPTR ")\n", 601 frame->lr, frame->lr - (register_t)(__startkernel - KERNBASE)); 602 printf(" frame = %p\n", frame); 603 printf(" curthread = %p\n", curthread); 604 if (curthread != NULL) 605 printf(" pid = %d, comm = %s\n", 606 curthread->td_proc->p_pid, curthread->td_name); 607 printf("\n"); 608 } 609 610 /* 611 * Handles a fatal fault when we have onfault state to recover. Returns 612 * non-zero if there was onfault recovery state available. 613 */ 614 static int 615 handle_onfault(struct trapframe *frame) 616 { 617 struct thread *td; 618 jmp_buf *fb; 619 620 td = curthread; 621 #if defined(__powerpc64__) || defined(BOOKE) 622 uintptr_t dispatch = (uintptr_t)td->td_pcb->pcb_onfault; 623 624 if (dispatch == 0) 625 return (0); 626 /* Short-circuit radix and Book-E paths. */ 627 switch (dispatch) { 628 case COPYFAULT: 629 frame->srr0 = (uintptr_t)copy_fault; 630 return (1); 631 case FUSUFAULT: 632 frame->srr0 = (uintptr_t)fusufault; 633 return (1); 634 default: 635 break; 636 } 637 #endif 638 fb = td->td_pcb->pcb_onfault; 639 if (fb != NULL) { 640 frame->srr0 = (*fb)->_jb[FAULTBUF_LR]; 641 frame->fixreg[1] = (*fb)->_jb[FAULTBUF_R1]; 642 frame->fixreg[2] = (*fb)->_jb[FAULTBUF_R2]; 643 frame->fixreg[3] = 1; 644 frame->cr = (*fb)->_jb[FAULTBUF_CR]; 645 bcopy(&(*fb)->_jb[FAULTBUF_R14], &frame->fixreg[14], 646 18 * sizeof(register_t)); 647 td->td_pcb->pcb_onfault = NULL; /* Returns twice, not thrice */ 648 return (1); 649 } 650 return (0); 651 } 652 653 int 654 cpu_fetch_syscall_args(struct thread *td) 655 { 656 struct proc *p; 657 struct trapframe *frame; 658 struct syscall_args *sa; 659 caddr_t params; 660 size_t argsz; 661 int error, n, narg, i; 662 663 p = td->td_proc; 664 frame = td->td_frame; 665 sa = &td->td_sa; 666 667 sa->code = frame->fixreg[0]; 668 sa->original_code = sa->code; 669 params = (caddr_t)(frame->fixreg + FIRSTARG); 670 n = NARGREG; 671 672 if (sa->code == SYS_syscall) { 673 /* 674 * code is first argument, 675 * followed by actual args. 676 */ 677 sa->code = *(register_t *) params; 678 params += sizeof(register_t); 679 n -= 1; 680 } else if (sa->code == SYS___syscall) { 681 /* 682 * Like syscall, but code is a quad, 683 * so as to maintain quad alignment 684 * for the rest of the args. 685 */ 686 if (SV_PROC_FLAG(p, SV_ILP32)) { 687 params += sizeof(register_t); 688 sa->code = *(register_t *) params; 689 params += sizeof(register_t); 690 n -= 2; 691 } else { 692 sa->code = *(register_t *) params; 693 params += sizeof(register_t); 694 n -= 1; 695 } 696 } 697 698 if (sa->code >= p->p_sysent->sv_size) 699 sa->callp = &nosys_sysent; 700 else 701 sa->callp = &p->p_sysent->sv_table[sa->code]; 702 703 narg = sa->callp->sy_narg; 704 705 if (SV_PROC_FLAG(p, SV_ILP32)) { 706 argsz = sizeof(uint32_t); 707 708 for (i = 0; i < n; i++) 709 sa->args[i] = ((u_register_t *)(params))[i] & 710 0xffffffff; 711 } else { 712 argsz = sizeof(uint64_t); 713 714 for (i = 0; i < n; i++) 715 sa->args[i] = ((u_register_t *)(params))[i]; 716 } 717 718 if (narg > n) 719 error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n, 720 (narg - n) * argsz); 721 else 722 error = 0; 723 724 #ifdef __powerpc64__ 725 if (SV_PROC_FLAG(p, SV_ILP32) && narg > n) { 726 /* Expand the size of arguments copied from the stack */ 727 728 for (i = narg; i >= n; i--) 729 sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n]; 730 } 731 #endif 732 733 if (error == 0) { 734 td->td_retval[0] = 0; 735 td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; 736 } 737 return (error); 738 } 739 740 #include "../../kern/subr_syscall.c" 741 742 void 743 syscall(struct trapframe *frame) 744 { 745 struct thread *td; 746 747 td = curthread; 748 td->td_frame = frame; 749 750 #if defined(__powerpc64__) && defined(AIM) 751 /* 752 * Speculatively restore last user SLB segment, which we know is 753 * invalid already, since we are likely to do copyin()/copyout(). 754 */ 755 if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0) 756 __asm __volatile ("slbmte %0, %1; isync" :: 757 "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE)); 758 #endif 759 760 syscallenter(td); 761 syscallret(td); 762 } 763 764 static bool 765 trap_pfault(struct trapframe *frame, bool user, int *signo, int *ucode) 766 { 767 vm_offset_t eva; 768 struct thread *td; 769 struct proc *p; 770 vm_map_t map; 771 vm_prot_t ftype; 772 int rv, is_user; 773 774 td = curthread; 775 p = td->td_proc; 776 if (frame->exc == EXC_ISI) { 777 eva = frame->srr0; 778 ftype = VM_PROT_EXECUTE; 779 if (frame->srr1 & SRR1_ISI_PFAULT) 780 ftype |= VM_PROT_READ; 781 } else { 782 eva = frame->dar; 783 #ifdef BOOKE 784 if (frame->cpu.booke.esr & ESR_ST) 785 #else 786 if (frame->cpu.aim.dsisr & DSISR_STORE) 787 #endif 788 ftype = VM_PROT_WRITE; 789 else 790 ftype = VM_PROT_READ; 791 } 792 #if defined(__powerpc64__) && defined(AIM) 793 if (radix_mmu && pmap_nofault(&p->p_vmspace->vm_pmap, eva, ftype) == 0) 794 return (true); 795 #endif 796 797 if (__predict_false((td->td_pflags & TDP_NOFAULTING) == 0)) { 798 /* 799 * If we get a page fault while in a critical section, then 800 * it is most likely a fatal kernel page fault. The kernel 801 * is already going to panic trying to get a sleep lock to 802 * do the VM lookup, so just consider it a fatal trap so the 803 * kernel can print out a useful trap message and even get 804 * to the debugger. 805 * 806 * If we get a page fault while holding a non-sleepable 807 * lock, then it is most likely a fatal kernel page fault. 808 * If WITNESS is enabled, then it's going to whine about 809 * bogus LORs with various VM locks, so just skip to the 810 * fatal trap handling directly. 811 */ 812 if (td->td_critnest != 0 || 813 WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL, 814 "Kernel page fault") != 0) { 815 trap_fatal(frame); 816 return (false); 817 } 818 } 819 if (user) { 820 KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace NULL")); 821 map = &p->p_vmspace->vm_map; 822 } else { 823 rv = pmap_decode_kernel_ptr(eva, &is_user, &eva); 824 if (rv != 0) 825 return (false); 826 827 if (is_user) 828 map = &p->p_vmspace->vm_map; 829 else 830 map = kernel_map; 831 } 832 833 /* Fault in the page. */ 834 rv = vm_fault_trap(map, eva, ftype, VM_FAULT_NORMAL, signo, ucode); 835 /* 836 * XXXDTRACE: add dtrace_doubletrap_func here? 837 */ 838 839 if (rv == KERN_SUCCESS) 840 return (true); 841 842 if (!user && handle_onfault(frame)) 843 return (true); 844 845 return (false); 846 } 847 848 /* 849 * For now, this only deals with the particular unaligned access case 850 * that gcc tends to generate. Eventually it should handle all of the 851 * possibilities that can happen on a 32-bit PowerPC in big-endian mode. 852 */ 853 854 static int 855 fix_unaligned(struct thread *td, struct trapframe *frame) 856 { 857 struct thread *fputhread; 858 #ifdef BOOKE 859 uint32_t inst; 860 #endif 861 int indicator, reg; 862 double *fpr; 863 864 #ifdef __SPE__ 865 indicator = (frame->cpu.booke.esr & (ESR_ST|ESR_SPE)); 866 if (indicator & ESR_SPE) { 867 if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0) 868 return (-1); 869 reg = EXC_ALI_INST_RST(inst); 870 fpr = (double *)td->td_pcb->pcb_vec.vr[reg]; 871 fputhread = PCPU_GET(vecthread); 872 873 /* Juggle the SPE to ensure that we've initialized 874 * the registers, and that their current state is in 875 * the PCB. 876 */ 877 if (fputhread != td) { 878 if (fputhread) 879 save_vec(fputhread); 880 enable_vec(td); 881 } 882 save_vec(td); 883 884 if (!(indicator & ESR_ST)) { 885 if (copyin((void *)frame->dar, fpr, 886 sizeof(double)) != 0) 887 return (-1); 888 frame->fixreg[reg] = td->td_pcb->pcb_vec.vr[reg][1]; 889 enable_vec(td); 890 } else { 891 td->td_pcb->pcb_vec.vr[reg][1] = frame->fixreg[reg]; 892 if (copyout(fpr, (void *)frame->dar, 893 sizeof(double)) != 0) 894 return (-1); 895 } 896 return (0); 897 } 898 #else 899 #ifdef BOOKE 900 indicator = (frame->cpu.booke.esr & ESR_ST) ? EXC_ALI_STFD : EXC_ALI_LFD; 901 #else 902 indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr); 903 #endif 904 905 switch (indicator) { 906 case EXC_ALI_LFD: 907 case EXC_ALI_STFD: 908 #ifdef BOOKE 909 if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0) 910 return (-1); 911 reg = EXC_ALI_INST_RST(inst); 912 #else 913 reg = EXC_ALI_RST(frame->cpu.aim.dsisr); 914 #endif 915 fpr = &td->td_pcb->pcb_fpu.fpr[reg].fpr; 916 fputhread = PCPU_GET(fputhread); 917 918 /* Juggle the FPU to ensure that we've initialized 919 * the FPRs, and that their current state is in 920 * the PCB. 921 */ 922 if (fputhread != td) { 923 if (fputhread) 924 save_fpu(fputhread); 925 enable_fpu(td); 926 } 927 save_fpu(td); 928 929 if (indicator == EXC_ALI_LFD) { 930 if (copyin((void *)frame->dar, fpr, 931 sizeof(double)) != 0) 932 return (-1); 933 enable_fpu(td); 934 } else { 935 if (copyout(fpr, (void *)frame->dar, 936 sizeof(double)) != 0) 937 return (-1); 938 } 939 return (0); 940 break; 941 } 942 #endif 943 944 return (-1); 945 } 946 947 #if defined(__powerpc64__) && defined(AIM) 948 #define MSKNSHL(x, m, n) "(((" #x ") & " #m ") << " #n ")" 949 #define MSKNSHR(x, m, n) "(((" #x ") & " #m ") >> " #n ")" 950 951 /* xvcpsgndp instruction, built in opcode format. 952 * This can be changed to use mnemonic after a toolchain update. 953 */ 954 #define XVCPSGNDP(xt, xa, xb) \ 955 __asm __volatile(".long (" \ 956 MSKNSHL(60, 0x3f, 26) " | " \ 957 MSKNSHL(xt, 0x1f, 21) " | " \ 958 MSKNSHL(xa, 0x1f, 16) " | " \ 959 MSKNSHL(xb, 0x1f, 11) " | " \ 960 MSKNSHL(240, 0xff, 3) " | " \ 961 MSKNSHR(xa, 0x20, 3) " | " \ 962 MSKNSHR(xa, 0x20, 4) " | " \ 963 MSKNSHR(xa, 0x20, 5) ")") 964 965 /* Macros to normalize 1 or 10 VSX registers */ 966 #define NORM(x) XVCPSGNDP(x, x, x) 967 #define NORM10(x) \ 968 NORM(x ## 0); NORM(x ## 1); NORM(x ## 2); NORM(x ## 3); NORM(x ## 4); \ 969 NORM(x ## 5); NORM(x ## 6); NORM(x ## 7); NORM(x ## 8); NORM(x ## 9) 970 971 static void 972 normalize_inputs(void) 973 { 974 register_t msr; 975 976 /* enable VSX */ 977 msr = mfmsr(); 978 mtmsr(msr | PSL_VSX); 979 980 NORM(0); NORM(1); NORM(2); NORM(3); NORM(4); 981 NORM(5); NORM(6); NORM(7); NORM(8); NORM(9); 982 NORM10(1); NORM10(2); NORM10(3); NORM10(4); NORM10(5); 983 NORM(60); NORM(61); NORM(62); NORM(63); 984 985 /* restore MSR */ 986 mtmsr(msr); 987 } 988 #endif 989 990 #ifdef KDB 991 int 992 db_trap_glue(struct trapframe *frame) 993 { 994 995 if (!(frame->srr1 & PSL_PR) 996 && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC 997 || frame_is_trap_inst(frame) 998 || frame->exc == EXC_BPT 999 || frame->exc == EXC_DEBUG 1000 || frame->exc == EXC_DSI)) { 1001 int type = frame->exc; 1002 1003 /* Ignore DTrace traps. */ 1004 if (*(uint32_t *)frame->srr0 == EXC_DTRACE) 1005 return (0); 1006 if (frame_is_trap_inst(frame)) { 1007 type = T_BREAKPOINT; 1008 } 1009 return (kdb_trap(type, 0, frame)); 1010 } 1011 1012 return (0); 1013 } 1014 #endif 1015