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