trap.c revision 331168
1/* $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $ */ 2/* tracked to 1.23 */ 3/*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 1988 University of Utah. 7 * Copyright (c) 1992, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * the Systems Programming Group of the University of Utah Computer 12 * Science Department and Ralph Campbell. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: Utah Hdr: trap.c 1.32 91/04/06 39 * 40 * from: @(#)trap.c 8.5 (Berkeley) 1/11/94 41 * JNPR: trap.c,v 1.13.2.2 2007/08/29 10:03:49 girish 42 */ 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD: stable/11/sys/mips/mips/trap.c 331168 2018-03-19 03:38:59Z eadler $"); 45 46#include "opt_compat.h" 47#include "opt_ddb.h" 48#include "opt_ktrace.h" 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/sysent.h> 53#include <sys/proc.h> 54#include <sys/kernel.h> 55#include <sys/signalvar.h> 56#include <sys/syscall.h> 57#include <sys/lock.h> 58#include <vm/vm.h> 59#include <vm/vm_extern.h> 60#include <vm/vm_kern.h> 61#include <vm/vm_page.h> 62#include <vm/vm_map.h> 63#include <vm/vm_param.h> 64#include <sys/vmmeter.h> 65#include <sys/ptrace.h> 66#include <sys/user.h> 67#include <sys/buf.h> 68#include <sys/vnode.h> 69#include <sys/pioctl.h> 70#include <sys/sysctl.h> 71#include <sys/syslog.h> 72#include <sys/bus.h> 73#ifdef KTRACE 74#include <sys/ktrace.h> 75#endif 76#include <net/netisr.h> 77 78#include <machine/trap.h> 79#include <machine/cpu.h> 80#include <machine/pte.h> 81#include <machine/pmap.h> 82#include <machine/md_var.h> 83#include <machine/mips_opcode.h> 84#include <machine/frame.h> 85#include <machine/regnum.h> 86#include <machine/tls.h> 87 88#ifdef DDB 89#include <machine/db_machdep.h> 90#include <ddb/db_sym.h> 91#include <ddb/ddb.h> 92#include <sys/kdb.h> 93#endif 94 95#ifdef KDTRACE_HOOKS 96#include <sys/dtrace_bsd.h> 97#endif 98 99#ifdef TRAP_DEBUG 100int trap_debug = 0; 101SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW, 102 &trap_debug, 0, "Debug information on all traps"); 103#endif 104 105#define lbu_macro(data, addr) \ 106 __asm __volatile ("lbu %0, 0x0(%1)" \ 107 : "=r" (data) /* outputs */ \ 108 : "r" (addr)); /* inputs */ 109 110#define lb_macro(data, addr) \ 111 __asm __volatile ("lb %0, 0x0(%1)" \ 112 : "=r" (data) /* outputs */ \ 113 : "r" (addr)); /* inputs */ 114 115#define lwl_macro(data, addr) \ 116 __asm __volatile ("lwl %0, 0x0(%1)" \ 117 : "=r" (data) /* outputs */ \ 118 : "r" (addr)); /* inputs */ 119 120#define lwr_macro(data, addr) \ 121 __asm __volatile ("lwr %0, 0x0(%1)" \ 122 : "=r" (data) /* outputs */ \ 123 : "r" (addr)); /* inputs */ 124 125#define ldl_macro(data, addr) \ 126 __asm __volatile ("ldl %0, 0x0(%1)" \ 127 : "=r" (data) /* outputs */ \ 128 : "r" (addr)); /* inputs */ 129 130#define ldr_macro(data, addr) \ 131 __asm __volatile ("ldr %0, 0x0(%1)" \ 132 : "=r" (data) /* outputs */ \ 133 : "r" (addr)); /* inputs */ 134 135#define sb_macro(data, addr) \ 136 __asm __volatile ("sb %0, 0x0(%1)" \ 137 : /* outputs */ \ 138 : "r" (data), "r" (addr)); /* inputs */ 139 140#define swl_macro(data, addr) \ 141 __asm __volatile ("swl %0, 0x0(%1)" \ 142 : /* outputs */ \ 143 : "r" (data), "r" (addr)); /* inputs */ 144 145#define swr_macro(data, addr) \ 146 __asm __volatile ("swr %0, 0x0(%1)" \ 147 : /* outputs */ \ 148 : "r" (data), "r" (addr)); /* inputs */ 149 150#define sdl_macro(data, addr) \ 151 __asm __volatile ("sdl %0, 0x0(%1)" \ 152 : /* outputs */ \ 153 : "r" (data), "r" (addr)); /* inputs */ 154 155#define sdr_macro(data, addr) \ 156 __asm __volatile ("sdr %0, 0x0(%1)" \ 157 : /* outputs */ \ 158 : "r" (data), "r" (addr)); /* inputs */ 159 160static void log_illegal_instruction(const char *, struct trapframe *); 161static void log_bad_page_fault(char *, struct trapframe *, int); 162static void log_frame_dump(struct trapframe *frame); 163static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **); 164 165int (*dtrace_invop_jump_addr)(struct trapframe *); 166 167#ifdef TRAP_DEBUG 168static void trap_frame_dump(struct trapframe *frame); 169#endif 170 171void (*machExceptionTable[]) (void)= { 172/* 173 * The kernel exception handlers. 174 */ 175 MipsKernIntr, /* external interrupt */ 176 MipsKernGenException, /* TLB modification */ 177 MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */ 178 MipsTLBInvalidException,/* TLB miss (store) */ 179 MipsKernGenException, /* address error (load or I-fetch) */ 180 MipsKernGenException, /* address error (store) */ 181 MipsKernGenException, /* bus error (I-fetch) */ 182 MipsKernGenException, /* bus error (load or store) */ 183 MipsKernGenException, /* system call */ 184 MipsKernGenException, /* breakpoint */ 185 MipsKernGenException, /* reserved instruction */ 186 MipsKernGenException, /* coprocessor unusable */ 187 MipsKernGenException, /* arithmetic overflow */ 188 MipsKernGenException, /* trap exception */ 189 MipsKernGenException, /* virtual coherence exception inst */ 190 MipsKernGenException, /* floating point exception */ 191 MipsKernGenException, /* reserved */ 192 MipsKernGenException, /* reserved */ 193 MipsKernGenException, /* reserved */ 194 MipsKernGenException, /* reserved */ 195 MipsKernGenException, /* reserved */ 196 MipsKernGenException, /* reserved */ 197 MipsKernGenException, /* reserved */ 198 MipsKernGenException, /* watch exception */ 199 MipsKernGenException, /* reserved */ 200 MipsKernGenException, /* reserved */ 201 MipsKernGenException, /* reserved */ 202 MipsKernGenException, /* reserved */ 203 MipsKernGenException, /* reserved */ 204 MipsKernGenException, /* reserved */ 205 MipsKernGenException, /* reserved */ 206 MipsKernGenException, /* virtual coherence exception data */ 207/* 208 * The user exception handlers. 209 */ 210 MipsUserIntr, /* 0 */ 211 MipsUserGenException, /* 1 */ 212 MipsTLBInvalidException,/* 2 */ 213 MipsTLBInvalidException,/* 3 */ 214 MipsUserGenException, /* 4 */ 215 MipsUserGenException, /* 5 */ 216 MipsUserGenException, /* 6 */ 217 MipsUserGenException, /* 7 */ 218 MipsUserGenException, /* 8 */ 219 MipsUserGenException, /* 9 */ 220 MipsUserGenException, /* 10 */ 221 MipsUserGenException, /* 11 */ 222 MipsUserGenException, /* 12 */ 223 MipsUserGenException, /* 13 */ 224 MipsUserGenException, /* 14 */ 225 MipsUserGenException, /* 15 */ 226 MipsUserGenException, /* 16 */ 227 MipsUserGenException, /* 17 */ 228 MipsUserGenException, /* 18 */ 229 MipsUserGenException, /* 19 */ 230 MipsUserGenException, /* 20 */ 231 MipsUserGenException, /* 21 */ 232 MipsUserGenException, /* 22 */ 233 MipsUserGenException, /* 23 */ 234 MipsUserGenException, /* 24 */ 235 MipsUserGenException, /* 25 */ 236 MipsUserGenException, /* 26 */ 237 MipsUserGenException, /* 27 */ 238 MipsUserGenException, /* 28 */ 239 MipsUserGenException, /* 29 */ 240 MipsUserGenException, /* 20 */ 241 MipsUserGenException, /* 31 */ 242}; 243 244char *trap_type[] = { 245 "external interrupt", 246 "TLB modification", 247 "TLB miss (load or instr. fetch)", 248 "TLB miss (store)", 249 "address error (load or I-fetch)", 250 "address error (store)", 251 "bus error (I-fetch)", 252 "bus error (load or store)", 253 "system call", 254 "breakpoint", 255 "reserved instruction", 256 "coprocessor unusable", 257 "arithmetic overflow", 258 "trap", 259 "virtual coherency instruction", 260 "floating point", 261 "reserved 16", 262 "reserved 17", 263 "reserved 18", 264 "reserved 19", 265 "reserved 20", 266 "reserved 21", 267 "reserved 22", 268 "watch", 269 "reserved 24", 270 "reserved 25", 271 "reserved 26", 272 "reserved 27", 273 "reserved 28", 274 "reserved 29", 275 "reserved 30", 276 "virtual coherency data", 277}; 278 279#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 280struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug; 281#endif 282 283#if defined(DDB) || defined(DEBUG) 284void stacktrace(struct trapframe *); 285void logstacktrace(struct trapframe *); 286#endif 287 288#define KERNLAND(x) ((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS) 289#define DELAYBRANCH(x) ((int)(x) < 0) 290 291/* 292 * MIPS load/store access type 293 */ 294enum { 295 MIPS_LHU_ACCESS = 1, 296 MIPS_LH_ACCESS, 297 MIPS_LWU_ACCESS, 298 MIPS_LW_ACCESS, 299 MIPS_LD_ACCESS, 300 MIPS_SH_ACCESS, 301 MIPS_SW_ACCESS, 302 MIPS_SD_ACCESS 303}; 304 305char *access_name[] = { 306 "Load Halfword Unsigned", 307 "Load Halfword", 308 "Load Word Unsigned", 309 "Load Word", 310 "Load Doubleword", 311 "Store Halfword", 312 "Store Word", 313 "Store Doubleword" 314}; 315 316#ifdef CPU_CNMIPS 317#include <machine/octeon_cop2.h> 318#endif 319 320static int allow_unaligned_acc = 1; 321 322SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW, 323 &allow_unaligned_acc, 0, "Allow unaligned accesses"); 324 325/* 326 * FP emulation is assumed to work on O32, but the code is outdated and crufty 327 * enough that it's a more sensible default to have it disabled when using 328 * other ABIs. At the very least, it needs a lot of help in using 329 * type-semantic ABI-oblivious macros for everything it does. 330 */ 331#if defined(__mips_o32) 332static int emulate_fp = 1; 333#else 334static int emulate_fp = 0; 335#endif 336SYSCTL_INT(_machdep, OID_AUTO, emulate_fp, CTLFLAG_RW, 337 &emulate_fp, 0, "Emulate unimplemented FPU instructions"); 338 339static int emulate_unaligned_access(struct trapframe *frame, int mode); 340 341extern void fswintrberr(void); /* XXX */ 342 343int 344cpu_fetch_syscall_args(struct thread *td) 345{ 346 struct trapframe *locr0; 347 struct sysentvec *se; 348 struct syscall_args *sa; 349 int error, nsaved; 350 351 locr0 = td->td_frame; 352 sa = &td->td_sa; 353 354 bzero(sa->args, sizeof(sa->args)); 355 356 /* compute next PC after syscall instruction */ 357 td->td_pcb->pcb_tpc = sa->trapframe->pc; /* Remember if restart */ 358 if (DELAYBRANCH(sa->trapframe->cause)) /* Check BD bit */ 359 locr0->pc = MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0); 360 else 361 locr0->pc += sizeof(int); 362 sa->code = locr0->v0; 363 364 switch (sa->code) { 365 case SYS___syscall: 366 case SYS_syscall: 367 /* 368 * This is an indirect syscall, in which the code is the first argument. 369 */ 370#if (!defined(__mips_n32) && !defined(__mips_n64)) || defined(COMPAT_FREEBSD32) 371 if (sa->code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 372 /* 373 * Like syscall, but code is a quad, so as to maintain alignment 374 * for the rest of the arguments. 375 */ 376 if (_QUAD_LOWWORD == 0) 377 sa->code = locr0->a0; 378 else 379 sa->code = locr0->a1; 380 sa->args[0] = locr0->a2; 381 sa->args[1] = locr0->a3; 382 nsaved = 2; 383 break; 384 } 385#endif 386 /* 387 * This is either not a quad syscall, or is a quad syscall with a 388 * new ABI in which quads fit in a single register. 389 */ 390 sa->code = locr0->a0; 391 sa->args[0] = locr0->a1; 392 sa->args[1] = locr0->a2; 393 sa->args[2] = locr0->a3; 394 nsaved = 3; 395#if defined(__mips_n32) || defined(__mips_n64) 396#ifdef COMPAT_FREEBSD32 397 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 398#endif 399 /* 400 * Non-o32 ABIs support more arguments in registers. 401 */ 402 sa->args[3] = locr0->a4; 403 sa->args[4] = locr0->a5; 404 sa->args[5] = locr0->a6; 405 sa->args[6] = locr0->a7; 406 nsaved += 4; 407#ifdef COMPAT_FREEBSD32 408 } 409#endif 410#endif 411 break; 412 default: 413 /* 414 * A direct syscall, arguments are just parameters to the syscall. 415 */ 416 sa->args[0] = locr0->a0; 417 sa->args[1] = locr0->a1; 418 sa->args[2] = locr0->a2; 419 sa->args[3] = locr0->a3; 420 nsaved = 4; 421#if defined (__mips_n32) || defined(__mips_n64) 422#ifdef COMPAT_FREEBSD32 423 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 424#endif 425 /* 426 * Non-o32 ABIs support more arguments in registers. 427 */ 428 sa->args[4] = locr0->a4; 429 sa->args[5] = locr0->a5; 430 sa->args[6] = locr0->a6; 431 sa->args[7] = locr0->a7; 432 nsaved += 4; 433#ifdef COMPAT_FREEBSD32 434 } 435#endif 436#endif 437 break; 438 } 439 440#ifdef TRAP_DEBUG 441 if (trap_debug) 442 printf("SYSCALL #%d pid:%u\n", sa->code, td->td_proc->p_pid); 443#endif 444 445 se = td->td_proc->p_sysent; 446 /* 447 * XXX 448 * Shouldn't this go before switching on the code? 449 */ 450 if (se->sv_mask) 451 sa->code &= se->sv_mask; 452 453 if (sa->code >= se->sv_size) 454 sa->callp = &se->sv_table[0]; 455 else 456 sa->callp = &se->sv_table[sa->code]; 457 458 sa->narg = sa->callp->sy_narg; 459 460 if (sa->narg > nsaved) { 461#if defined(__mips_n32) || defined(__mips_n64) 462 /* 463 * XXX 464 * Is this right for new ABIs? I think the 4 there 465 * should be 8, size there are 8 registers to skip, 466 * not 4, but I'm not certain. 467 */ 468#ifdef COMPAT_FREEBSD32 469 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) 470#endif 471 printf("SYSCALL #%u pid:%u, narg (%u) > nsaved (%u).\n", 472 sa->code, td->td_proc->p_pid, sa->narg, nsaved); 473#endif 474#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32) 475 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 476 unsigned i; 477 int32_t arg; 478 479 error = 0; /* XXX GCC is awful. */ 480 for (i = nsaved; i < sa->narg; i++) { 481 error = copyin((caddr_t)(intptr_t)(locr0->sp + 482 (4 + (i - nsaved)) * sizeof(int32_t)), 483 (caddr_t)&arg, sizeof arg); 484 if (error != 0) 485 break; 486 sa->args[i] = arg; 487 } 488 } else 489#endif 490 error = copyin((caddr_t)(intptr_t)(locr0->sp + 491 4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved], 492 (u_int)(sa->narg - nsaved) * sizeof(register_t)); 493 if (error != 0) { 494 locr0->v0 = error; 495 locr0->a3 = 1; 496 } 497 } else 498 error = 0; 499 500 if (error == 0) { 501 td->td_retval[0] = 0; 502 td->td_retval[1] = locr0->v1; 503 } 504 505 return (error); 506} 507 508#undef __FBSDID 509#define __FBSDID(x) 510#include "../../kern/subr_syscall.c" 511 512/* 513 * Handle an exception. 514 * Called from MipsKernGenException() or MipsUserGenException() 515 * when a processor trap occurs. 516 * In the case of a kernel trap, we return the pc where to resume if 517 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc. 518 */ 519register_t 520trap(struct trapframe *trapframe) 521{ 522 int type, usermode; 523 int i = 0; 524 unsigned ucode = 0; 525 struct thread *td = curthread; 526 struct proc *p = curproc; 527 vm_prot_t ftype; 528 pmap_t pmap; 529 int access_type; 530 ksiginfo_t ksi; 531 char *msg = NULL; 532 intptr_t addr = 0; 533 register_t pc; 534 int cop; 535 register_t *frame_regs; 536 537 trapdebug_enter(trapframe, 0); 538 539 type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT; 540 if (TRAPF_USERMODE(trapframe)) { 541 type |= T_USER; 542 usermode = 1; 543 } else { 544 usermode = 0; 545 } 546 547 /* 548 * Enable hardware interrupts if they were on before the trap. If it 549 * was off disable all so we don't accidently enable it when doing a 550 * return to userland. 551 */ 552 if (trapframe->sr & MIPS_SR_INT_IE) { 553 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK); 554 intr_enable(); 555 } else { 556 intr_disable(); 557 } 558 559#ifdef TRAP_DEBUG 560 if (trap_debug) { 561 static vm_offset_t last_badvaddr = 0; 562 static vm_offset_t this_badvaddr = 0; 563 static int count = 0; 564 u_int32_t pid; 565 566 printf("trap type %x (%s - ", type, 567 trap_type[type & (~T_USER)]); 568 569 if (type & T_USER) 570 printf("user mode)\n"); 571 else 572 printf("kernel mode)\n"); 573 574#ifdef SMP 575 printf("cpuid = %d\n", PCPU_GET(cpuid)); 576#endif 577 pid = mips_rd_entryhi() & TLBHI_ASID_MASK; 578 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n", 579 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra, 580 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr, 581 (curproc ? curproc->p_pid : -1), pid); 582 583 switch (type & ~T_USER) { 584 case T_TLB_MOD: 585 case T_TLB_LD_MISS: 586 case T_TLB_ST_MISS: 587 case T_ADDR_ERR_LD: 588 case T_ADDR_ERR_ST: 589 this_badvaddr = trapframe->badvaddr; 590 break; 591 case T_SYSCALL: 592 this_badvaddr = trapframe->ra; 593 break; 594 default: 595 this_badvaddr = trapframe->pc; 596 break; 597 } 598 if ((last_badvaddr == this_badvaddr) && 599 ((type & ~T_USER) != T_SYSCALL)) { 600 if (++count == 3) { 601 trap_frame_dump(trapframe); 602 panic("too many faults at %p\n", (void *)last_badvaddr); 603 } 604 } else { 605 last_badvaddr = this_badvaddr; 606 count = 0; 607 } 608 } 609#endif 610 611#ifdef KDTRACE_HOOKS 612 /* 613 * A trap can occur while DTrace executes a probe. Before 614 * executing the probe, DTrace blocks re-scheduling and sets 615 * a flag in its per-cpu flags to indicate that it doesn't 616 * want to fault. On returning from the probe, the no-fault 617 * flag is cleared and finally re-scheduling is enabled. 618 * 619 * If the DTrace kernel module has registered a trap handler, 620 * call it and if it returns non-zero, assume that it has 621 * handled the trap and modified the trap frame so that this 622 * function can return normally. 623 */ 624 /* 625 * XXXDTRACE: add pid probe handler here (if ever) 626 */ 627 if (!usermode) { 628 if (dtrace_trap_func != NULL && 629 (*dtrace_trap_func)(trapframe, type) != 0) 630 return (trapframe->pc); 631 } 632#endif 633 634 switch (type) { 635 case T_MCHECK: 636#ifdef DDB 637 kdb_trap(type, 0, trapframe); 638#endif 639 panic("MCHECK\n"); 640 break; 641 case T_TLB_MOD: 642 /* check for kernel address */ 643 if (KERNLAND(trapframe->badvaddr)) { 644 if (pmap_emulate_modified(kernel_pmap, 645 trapframe->badvaddr) != 0) { 646 ftype = VM_PROT_WRITE; 647 goto kernel_fault; 648 } 649 return (trapframe->pc); 650 } 651 /* FALLTHROUGH */ 652 653 case T_TLB_MOD + T_USER: 654 pmap = &p->p_vmspace->vm_pmap; 655 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) { 656 ftype = VM_PROT_WRITE; 657 goto dofault; 658 } 659 if (!usermode) 660 return (trapframe->pc); 661 goto out; 662 663 case T_TLB_LD_MISS: 664 case T_TLB_ST_MISS: 665 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ; 666 /* check for kernel address */ 667 if (KERNLAND(trapframe->badvaddr)) { 668 vm_offset_t va; 669 int rv; 670 671 kernel_fault: 672 va = trunc_page((vm_offset_t)trapframe->badvaddr); 673 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL); 674 if (rv == KERN_SUCCESS) 675 return (trapframe->pc); 676 if (td->td_pcb->pcb_onfault != NULL) { 677 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 678 td->td_pcb->pcb_onfault = NULL; 679 return (pc); 680 } 681 goto err; 682 } 683 684 /* 685 * It is an error for the kernel to access user space except 686 * through the copyin/copyout routines. 687 */ 688 if (td->td_pcb->pcb_onfault == NULL) 689 goto err; 690 691 /* check for fuswintr() or suswintr() getting a page fault */ 692 /* XXX There must be a nicer way to do this. */ 693 if (td->td_pcb->pcb_onfault == fswintrberr) { 694 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 695 td->td_pcb->pcb_onfault = NULL; 696 return (pc); 697 } 698 699 goto dofault; 700 701 case T_TLB_LD_MISS + T_USER: 702 ftype = VM_PROT_READ; 703 goto dofault; 704 705 case T_TLB_ST_MISS + T_USER: 706 ftype = VM_PROT_WRITE; 707dofault: 708 { 709 vm_offset_t va; 710 struct vmspace *vm; 711 vm_map_t map; 712 int rv = 0; 713 714 vm = p->p_vmspace; 715 map = &vm->vm_map; 716 va = trunc_page((vm_offset_t)trapframe->badvaddr); 717 if (KERNLAND(trapframe->badvaddr)) { 718 /* 719 * Don't allow user-mode faults in kernel 720 * address space. 721 */ 722 goto nogo; 723 } 724 725 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); 726 /* 727 * XXXDTRACE: add dtrace_doubletrap_func here? 728 */ 729#ifdef VMFAULT_TRACE 730 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n", 731 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr, 732 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc); 733#endif 734 735 if (rv == KERN_SUCCESS) { 736 if (!usermode) { 737 return (trapframe->pc); 738 } 739 goto out; 740 } 741 nogo: 742 if (!usermode) { 743 if (td->td_pcb->pcb_onfault != NULL) { 744 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 745 td->td_pcb->pcb_onfault = NULL; 746 return (pc); 747 } 748 goto err; 749 } 750 ucode = ftype; 751 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 752 addr = trapframe->pc; 753 754 msg = "BAD_PAGE_FAULT"; 755 log_bad_page_fault(msg, trapframe, type); 756 757 break; 758 } 759 760 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */ 761 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */ 762 if (trapframe->badvaddr < 0 || 763 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) { 764 msg = "ADDRESS_SPACE_ERR"; 765 } else if (allow_unaligned_acc) { 766 int mode; 767 768 if (type == (T_ADDR_ERR_LD + T_USER)) 769 mode = VM_PROT_READ; 770 else 771 mode = VM_PROT_WRITE; 772 773 access_type = emulate_unaligned_access(trapframe, mode); 774 if (access_type != 0) 775 goto out; 776 msg = "ALIGNMENT_FIX_ERR"; 777 } else { 778 msg = "ADDRESS_ERR"; 779 } 780 781 /* FALL THROUGH */ 782 783 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */ 784 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */ 785 ucode = 0; /* XXX should be VM_PROT_something */ 786 i = SIGBUS; 787 addr = trapframe->pc; 788 if (!msg) 789 msg = "BUS_ERR"; 790 log_bad_page_fault(msg, trapframe, type); 791 break; 792 793 case T_SYSCALL + T_USER: 794 { 795 int error; 796 797 td->td_sa.trapframe = trapframe; 798 error = syscallenter(td); 799 800#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 801 if (trp == trapdebug) 802 trapdebug[TRAPSIZE - 1].code = td->td_sa.code; 803 else 804 trp[-1].code = td->td_sa.code; 805#endif 806 trapdebug_enter(td->td_frame, -td->td_sa.code); 807 808 /* 809 * The sync'ing of I & D caches for SYS_ptrace() is 810 * done by procfs_domem() through procfs_rwmem() 811 * instead of being done here under a special check 812 * for SYS_ptrace(). 813 */ 814 syscallret(td, error); 815 return (trapframe->pc); 816 } 817 818#if defined(KDTRACE_HOOKS) || defined(DDB) 819 case T_BREAK: 820#ifdef KDTRACE_HOOKS 821 if (!usermode && dtrace_invop_jump_addr != 0) { 822 dtrace_invop_jump_addr(trapframe); 823 return (trapframe->pc); 824 } 825#endif 826#ifdef DDB 827 kdb_trap(type, 0, trapframe); 828 return (trapframe->pc); 829#endif 830#endif 831 832 case T_BREAK + T_USER: 833 { 834 intptr_t va; 835 uint32_t instr; 836 837 /* compute address of break instruction */ 838 va = trapframe->pc; 839 if (DELAYBRANCH(trapframe->cause)) 840 va += sizeof(int); 841 842 /* read break instruction */ 843 instr = fuword32((caddr_t)va); 844#if 0 845 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", 846 p->p_comm, p->p_pid, instr, trapframe->pc, 847 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ 848#endif 849 if (td->td_md.md_ss_addr != va || 850 instr != MIPS_BREAK_SSTEP) { 851 i = SIGTRAP; 852 addr = trapframe->pc; 853 break; 854 } 855 /* 856 * The restoration of the original instruction and 857 * the clearing of the breakpoint will be done later 858 * by the call to ptrace_clear_single_step() in 859 * issignal() when SIGTRAP is processed. 860 */ 861 addr = trapframe->pc; 862 i = SIGTRAP; 863 break; 864 } 865 866 case T_IWATCH + T_USER: 867 case T_DWATCH + T_USER: 868 { 869 intptr_t va; 870 871 /* compute address of trapped instruction */ 872 va = trapframe->pc; 873 if (DELAYBRANCH(trapframe->cause)) 874 va += sizeof(int); 875 printf("watch exception @ %p\n", (void *)va); 876 i = SIGTRAP; 877 addr = va; 878 break; 879 } 880 881 case T_TRAP + T_USER: 882 { 883 intptr_t va; 884 uint32_t instr; 885 struct trapframe *locr0 = td->td_frame; 886 887 /* compute address of trap instruction */ 888 va = trapframe->pc; 889 if (DELAYBRANCH(trapframe->cause)) 890 va += sizeof(int); 891 /* read break instruction */ 892 instr = fuword32((caddr_t)va); 893 894 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */ 895 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 896 0); 897 } else { 898 locr0->pc += sizeof(int); 899 } 900 addr = va; 901 i = SIGEMT; /* Stuff it with something for now */ 902 break; 903 } 904 905 case T_RES_INST + T_USER: 906 { 907 InstFmt inst; 908 inst = *(InstFmt *)(intptr_t)trapframe->pc; 909 switch (inst.RType.op) { 910 case OP_SPECIAL3: 911 switch (inst.RType.func) { 912 case OP_RDHWR: 913 /* Register 29 used for TLS */ 914 if (inst.RType.rd == 29) { 915 frame_regs = &(trapframe->zero); 916 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls; 917#if defined(__mips_n64) && defined(COMPAT_FREEBSD32) 918 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) 919 frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE32; 920 else 921#endif 922 frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE; 923 trapframe->pc += sizeof(int); 924 goto out; 925 } 926 break; 927 } 928 break; 929 } 930 931 log_illegal_instruction("RES_INST", trapframe); 932 i = SIGILL; 933 addr = trapframe->pc; 934 } 935 break; 936 case T_C2E: 937 case T_C2E + T_USER: 938 goto err; 939 break; 940 case T_COP_UNUSABLE: 941#ifdef CPU_CNMIPS 942 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT; 943 /* Handle only COP2 exception */ 944 if (cop != 2) 945 goto err; 946 947 addr = trapframe->pc; 948 /* save userland cop2 context if it has been touched */ 949 if ((td->td_md.md_flags & MDTD_COP2USED) && 950 (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) { 951 if (td->td_md.md_ucop2) 952 octeon_cop2_save(td->td_md.md_ucop2); 953 else 954 panic("COP2 was used in user mode but md_ucop2 is NULL"); 955 } 956 957 if (td->td_md.md_cop2 == NULL) { 958 td->td_md.md_cop2 = octeon_cop2_alloc_ctx(); 959 if (td->td_md.md_cop2 == NULL) 960 panic("Failed to allocate COP2 context"); 961 memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2)); 962 } 963 964 octeon_cop2_restore(td->td_md.md_cop2); 965 966 /* Make userland re-request its context */ 967 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT; 968 td->td_md.md_flags |= MDTD_COP2USED; 969 td->td_md.md_cop2owner = COP2_OWNER_KERNEL; 970 /* Enable COP2, it will be disabled in cpu_switch */ 971 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT); 972 return (trapframe->pc); 973#else 974 goto err; 975 break; 976#endif 977 978 case T_COP_UNUSABLE + T_USER: 979 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT; 980 if (cop == 1) { 981#if !defined(CPU_HAVEFPU) 982 /* FP (COP1) instruction */ 983 log_illegal_instruction("COP1_UNUSABLE", trapframe); 984 i = SIGILL; 985 break; 986#else 987 addr = trapframe->pc; 988 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame); 989 PCPU_SET(fpcurthread, td); 990 td->td_frame->sr |= MIPS_SR_COP_1_BIT; 991 td->td_md.md_flags |= MDTD_FPUSED; 992 goto out; 993#endif 994 } 995#ifdef CPU_CNMIPS 996 else if (cop == 2) { 997 addr = trapframe->pc; 998 if ((td->td_md.md_flags & MDTD_COP2USED) && 999 (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) { 1000 if (td->td_md.md_cop2) 1001 octeon_cop2_save(td->td_md.md_cop2); 1002 else 1003 panic("COP2 was used in kernel mode but md_cop2 is NULL"); 1004 } 1005 1006 if (td->td_md.md_ucop2 == NULL) { 1007 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx(); 1008 if (td->td_md.md_ucop2 == NULL) 1009 panic("Failed to allocate userland COP2 context"); 1010 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2)); 1011 } 1012 1013 octeon_cop2_restore(td->td_md.md_ucop2); 1014 1015 td->td_frame->sr |= MIPS_SR_COP_2_BIT; 1016 td->td_md.md_flags |= MDTD_COP2USED; 1017 td->td_md.md_cop2owner = COP2_OWNER_USERLAND; 1018 goto out; 1019 } 1020#endif 1021 else { 1022 log_illegal_instruction("COPn_UNUSABLE", trapframe); 1023 i = SIGILL; /* only FPU instructions allowed */ 1024 break; 1025 } 1026 1027 case T_FPE: 1028#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 1029 trapDump("fpintr"); 1030#else 1031 printf("FPU Trap: PC %#jx CR %x SR %x\n", 1032 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr); 1033 goto err; 1034#endif 1035 1036 case T_FPE + T_USER: 1037 if (!emulate_fp) { 1038 i = SIGILL; 1039 addr = trapframe->pc; 1040 break; 1041 } 1042 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc); 1043 goto out; 1044 1045 case T_OVFLOW + T_USER: 1046 i = SIGFPE; 1047 addr = trapframe->pc; 1048 break; 1049 1050 case T_ADDR_ERR_LD: /* misaligned access */ 1051 case T_ADDR_ERR_ST: /* misaligned access */ 1052#ifdef TRAP_DEBUG 1053 if (trap_debug) { 1054 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type, 1055 (intmax_t)trapframe->badvaddr); 1056 } 1057#endif 1058 /* Only allow emulation on a user address */ 1059 if (allow_unaligned_acc && 1060 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) { 1061 int mode; 1062 1063 if (type == T_ADDR_ERR_LD) 1064 mode = VM_PROT_READ; 1065 else 1066 mode = VM_PROT_WRITE; 1067 1068 access_type = emulate_unaligned_access(trapframe, mode); 1069 if (access_type != 0) 1070 return (trapframe->pc); 1071 } 1072 /* FALLTHROUGH */ 1073 1074 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 1075 if (td->td_pcb->pcb_onfault != NULL) { 1076 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 1077 td->td_pcb->pcb_onfault = NULL; 1078 return (pc); 1079 } 1080 1081 /* FALLTHROUGH */ 1082 1083 default: 1084err: 1085 1086#if !defined(SMP) && defined(DEBUG) 1087 stacktrace(!usermode ? trapframe : td->td_frame); 1088 trapDump("trap"); 1089#endif 1090#ifdef SMP 1091 printf("cpu:%d-", PCPU_GET(cpuid)); 1092#endif 1093 printf("Trap cause = %d (%s - ", type, 1094 trap_type[type & (~T_USER)]); 1095 1096 if (type & T_USER) 1097 printf("user mode)\n"); 1098 else 1099 printf("kernel mode)\n"); 1100 1101#ifdef TRAP_DEBUG 1102 if (trap_debug) 1103 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n", 1104 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra, 1105 (intmax_t)trapframe->sr); 1106#endif 1107 1108#ifdef KDB 1109 if (debugger_on_panic || kdb_active) { 1110 kdb_trap(type, 0, trapframe); 1111 } 1112#endif 1113 panic("trap"); 1114 } 1115 td->td_frame->pc = trapframe->pc; 1116 td->td_frame->cause = trapframe->cause; 1117 td->td_frame->badvaddr = trapframe->badvaddr; 1118 ksiginfo_init_trap(&ksi); 1119 ksi.ksi_signo = i; 1120 ksi.ksi_code = ucode; 1121 ksi.ksi_addr = (void *)addr; 1122 ksi.ksi_trapno = type; 1123 trapsignal(td, &ksi); 1124out: 1125 1126 /* 1127 * Note: we should only get here if returning to user mode. 1128 */ 1129 userret(td, trapframe); 1130 return (trapframe->pc); 1131} 1132 1133#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 1134void 1135trapDump(char *msg) 1136{ 1137 register_t s; 1138 int i; 1139 1140 s = intr_disable(); 1141 printf("trapDump(%s)\n", msg); 1142 for (i = 0; i < TRAPSIZE; i++) { 1143 if (trp == trapdebug) { 1144 trp = &trapdebug[TRAPSIZE - 1]; 1145 } else { 1146 trp--; 1147 } 1148 1149 if (trp->cause == 0) 1150 break; 1151 1152 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n", 1153 trap_type[(trp->cause & MIPS_CR_EXC_CODE) >> 1154 MIPS_CR_EXC_CODE_SHIFT], 1155 (intmax_t)trp->vadr, (intmax_t)trp->pc, 1156 (intmax_t)trp->cause, (intmax_t)trp->status); 1157 1158 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra, 1159 (intmax_t)trp->sp, (int)trp->code); 1160 } 1161 intr_restore(s); 1162} 1163#endif 1164 1165 1166/* 1167 * Return the resulting PC as if the branch was executed. 1168 */ 1169uintptr_t 1170MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR, 1171 uintptr_t instptr) 1172{ 1173 InstFmt inst; 1174 register_t *regsPtr = (register_t *) framePtr; 1175 uintptr_t retAddr = 0; 1176 int condition; 1177 1178#define GetBranchDest(InstPtr, inst) \ 1179 (InstPtr + 4 + ((short)inst.IType.imm << 2)) 1180 1181 1182 if (instptr) { 1183 if (instptr < MIPS_KSEG0_START) 1184 inst.word = fuword32((void *)instptr); 1185 else 1186 inst = *(InstFmt *) instptr; 1187 } else { 1188 if ((vm_offset_t)instPC < MIPS_KSEG0_START) 1189 inst.word = fuword32((void *)instPC); 1190 else 1191 inst = *(InstFmt *) instPC; 1192 } 1193 1194 switch ((int)inst.JType.op) { 1195 case OP_SPECIAL: 1196 switch ((int)inst.RType.func) { 1197 case OP_JR: 1198 case OP_JALR: 1199 retAddr = regsPtr[inst.RType.rs]; 1200 break; 1201 1202 default: 1203 retAddr = instPC + 4; 1204 break; 1205 } 1206 break; 1207 1208 case OP_BCOND: 1209 switch ((int)inst.IType.rt) { 1210 case OP_BLTZ: 1211 case OP_BLTZL: 1212 case OP_BLTZAL: 1213 case OP_BLTZALL: 1214 if ((int)(regsPtr[inst.RType.rs]) < 0) 1215 retAddr = GetBranchDest(instPC, inst); 1216 else 1217 retAddr = instPC + 8; 1218 break; 1219 1220 case OP_BGEZ: 1221 case OP_BGEZL: 1222 case OP_BGEZAL: 1223 case OP_BGEZALL: 1224 if ((int)(regsPtr[inst.RType.rs]) >= 0) 1225 retAddr = GetBranchDest(instPC, inst); 1226 else 1227 retAddr = instPC + 8; 1228 break; 1229 1230 case OP_TGEI: 1231 case OP_TGEIU: 1232 case OP_TLTI: 1233 case OP_TLTIU: 1234 case OP_TEQI: 1235 case OP_TNEI: 1236 retAddr = instPC + 4; /* Like syscall... */ 1237 break; 1238 1239 default: 1240 panic("MipsEmulateBranch: Bad branch cond"); 1241 } 1242 break; 1243 1244 case OP_J: 1245 case OP_JAL: 1246 retAddr = (inst.JType.target << 2) | 1247 ((unsigned)(instPC + 4) & 0xF0000000); 1248 break; 1249 1250 case OP_BEQ: 1251 case OP_BEQL: 1252 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) 1253 retAddr = GetBranchDest(instPC, inst); 1254 else 1255 retAddr = instPC + 8; 1256 break; 1257 1258 case OP_BNE: 1259 case OP_BNEL: 1260 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) 1261 retAddr = GetBranchDest(instPC, inst); 1262 else 1263 retAddr = instPC + 8; 1264 break; 1265 1266 case OP_BLEZ: 1267 case OP_BLEZL: 1268 if ((int)(regsPtr[inst.RType.rs]) <= 0) 1269 retAddr = GetBranchDest(instPC, inst); 1270 else 1271 retAddr = instPC + 8; 1272 break; 1273 1274 case OP_BGTZ: 1275 case OP_BGTZL: 1276 if ((int)(regsPtr[inst.RType.rs]) > 0) 1277 retAddr = GetBranchDest(instPC, inst); 1278 else 1279 retAddr = instPC + 8; 1280 break; 1281 1282 case OP_COP1: 1283 switch (inst.RType.rs) { 1284 case OP_BCx: 1285 case OP_BCy: 1286 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) 1287 condition = fpcCSR & MIPS_FPU_COND_BIT; 1288 else 1289 condition = !(fpcCSR & MIPS_FPU_COND_BIT); 1290 if (condition) 1291 retAddr = GetBranchDest(instPC, inst); 1292 else 1293 retAddr = instPC + 8; 1294 break; 1295 1296 default: 1297 retAddr = instPC + 4; 1298 } 1299 break; 1300 1301 default: 1302 retAddr = instPC + 4; 1303 } 1304 return (retAddr); 1305} 1306 1307 1308#if defined(DDB) || defined(DEBUG) 1309/* 1310 * Print a stack backtrace. 1311 */ 1312void 1313stacktrace(struct trapframe *regs) 1314{ 1315 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf); 1316} 1317#endif 1318 1319static void 1320log_frame_dump(struct trapframe *frame) 1321{ 1322 log(LOG_ERR, "Trapframe Register Dump:\n"); 1323 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1324 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1325 1326 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1327 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1328 1329#if defined(__mips_n32) || defined(__mips_n64) 1330 log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n", 1331 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7); 1332 1333 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1334 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1335#else 1336 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1337 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1338 1339 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1340 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1341#endif 1342 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1343 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1344 1345 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1346 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1347 1348 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1349 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1350 1351 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1352 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1353 1354 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1355 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1356 1357#ifdef IC_REG 1358 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1359 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1360#else 1361 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n", 1362 (intmax_t)frame->cause, (intmax_t)frame->pc); 1363#endif 1364} 1365 1366#ifdef TRAP_DEBUG 1367static void 1368trap_frame_dump(struct trapframe *frame) 1369{ 1370 printf("Trapframe Register Dump:\n"); 1371 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1372 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1373 1374 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1375 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1376#if defined(__mips_n32) || defined(__mips_n64) 1377 printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n", 1378 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7); 1379 1380 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1381 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1382#else 1383 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1384 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1385 1386 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1387 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1388#endif 1389 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1390 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1391 1392 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1393 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1394 1395 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1396 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1397 1398 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1399 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1400 1401 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1402 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1403 1404#ifdef IC_REG 1405 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1406 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1407#else 1408 printf("\tcause: %#jx\tpc: %#jx\n", 1409 (intmax_t)frame->cause, (intmax_t)frame->pc); 1410#endif 1411} 1412 1413#endif 1414 1415 1416static void 1417get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) 1418{ 1419 pt_entry_t *ptep; 1420 pd_entry_t *pdep; 1421 struct proc *p = curproc; 1422 1423 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)])); 1424 if (*pdep) 1425 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); 1426 else 1427 ptep = (pt_entry_t *)0; 1428 1429 *pdepp = pdep; 1430 *ptepp = ptep; 1431} 1432 1433static void 1434log_illegal_instruction(const char *msg, struct trapframe *frame) 1435{ 1436 pt_entry_t *ptep; 1437 pd_entry_t *pdep; 1438 unsigned int *addr; 1439 struct thread *td; 1440 struct proc *p; 1441 register_t pc; 1442 1443 td = curthread; 1444 p = td->td_proc; 1445 1446#ifdef SMP 1447 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1448#endif 1449 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1450 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n", 1451 msg, p->p_pid, (long)td->td_tid, p->p_comm, 1452 p->p_ucred ? p->p_ucred->cr_uid : -1, 1453 (intmax_t)pc, 1454 (intmax_t)frame->ra); 1455 1456 /* log registers in trap frame */ 1457 log_frame_dump(frame); 1458 1459 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1460 1461 /* 1462 * Dump a few words around faulting instruction, if the addres is 1463 * valid. 1464 */ 1465 if (!(pc & 3) && 1466 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1467 /* dump page table entry for faulting instruction */ 1468 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n", 1469 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0)); 1470 1471 addr = (unsigned int *)(intptr_t)pc; 1472 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1473 addr); 1474 log(LOG_ERR, "%08x %08x %08x %08x\n", 1475 addr[0], addr[1], addr[2], addr[3]); 1476 } else { 1477 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n", 1478 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0)); 1479 } 1480} 1481 1482static void 1483log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type) 1484{ 1485 pt_entry_t *ptep; 1486 pd_entry_t *pdep; 1487 unsigned int *addr; 1488 struct thread *td; 1489 struct proc *p; 1490 char *read_or_write; 1491 register_t pc; 1492 1493 trap_type &= ~T_USER; 1494 1495 td = curthread; 1496 p = td->td_proc; 1497 1498#ifdef SMP 1499 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1500#endif 1501 switch (trap_type) { 1502 case T_TLB_MOD: 1503 case T_TLB_ST_MISS: 1504 case T_ADDR_ERR_ST: 1505 read_or_write = "write"; 1506 break; 1507 case T_TLB_LD_MISS: 1508 case T_ADDR_ERR_LD: 1509 case T_BUS_ERR_IFETCH: 1510 read_or_write = "read"; 1511 break; 1512 default: 1513 read_or_write = "unknown"; 1514 } 1515 1516 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1517 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault " 1518 "(type %#x) at %#jx\n", 1519 msg, p->p_pid, (long)td->td_tid, p->p_comm, 1520 p->p_ucred ? p->p_ucred->cr_uid : -1, 1521 (intmax_t)pc, 1522 read_or_write, 1523 trap_type, 1524 (intmax_t)frame->badvaddr); 1525 1526 /* log registers in trap frame */ 1527 log_frame_dump(frame); 1528 1529 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1530 1531 /* 1532 * Dump a few words around faulting instruction, if the addres is 1533 * valid. 1534 */ 1535 if (!(pc & 3) && (pc != frame->badvaddr) && 1536 (trap_type != T_BUS_ERR_IFETCH) && 1537 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1538 /* dump page table entry for faulting instruction */ 1539 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n", 1540 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0)); 1541 1542 addr = (unsigned int *)(intptr_t)pc; 1543 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1544 addr); 1545 log(LOG_ERR, "%08x %08x %08x %08x\n", 1546 addr[0], addr[1], addr[2], addr[3]); 1547 } else { 1548 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n", 1549 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0)); 1550 } 1551 1552 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep); 1553 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n", 1554 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0)); 1555} 1556 1557 1558/* 1559 * Unaligned load/store emulation 1560 */ 1561static int 1562mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc) 1563{ 1564 register_t *reg = (register_t *) frame; 1565 u_int32_t inst = *((u_int32_t *)(intptr_t)pc); 1566 register_t value_msb, value; 1567 unsigned size; 1568 1569 /* 1570 * ADDR_ERR faults have higher priority than TLB 1571 * Miss faults. Therefore, it is necessary to 1572 * verify that the faulting address is a valid 1573 * virtual address within the process' address space 1574 * before trying to emulate the unaligned access. 1575 */ 1576 switch (MIPS_INST_OPCODE(inst)) { 1577 case OP_LHU: case OP_LH: 1578 case OP_SH: 1579 size = 2; 1580 break; 1581 case OP_LWU: case OP_LW: 1582 case OP_SW: 1583 size = 4; 1584 break; 1585 case OP_LD: 1586 case OP_SD: 1587 size = 8; 1588 break; 1589 default: 1590 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst)); 1591 return (0); 1592 } 1593 1594 if (!useracc((void *)rounddown2((vm_offset_t)addr, size), size * 2, mode)) 1595 return (0); 1596 1597 /* 1598 * XXX 1599 * Handle LL/SC LLD/SCD. 1600 */ 1601 switch (MIPS_INST_OPCODE(inst)) { 1602 case OP_LHU: 1603 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); 1604 lbu_macro(value_msb, addr); 1605 addr += 1; 1606 lbu_macro(value, addr); 1607 value |= value_msb << 8; 1608 reg[MIPS_INST_RT(inst)] = value; 1609 return (MIPS_LHU_ACCESS); 1610 1611 case OP_LH: 1612 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); 1613 lb_macro(value_msb, addr); 1614 addr += 1; 1615 lbu_macro(value, addr); 1616 value |= value_msb << 8; 1617 reg[MIPS_INST_RT(inst)] = value; 1618 return (MIPS_LH_ACCESS); 1619 1620 case OP_LWU: 1621 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); 1622 lwl_macro(value, addr); 1623 addr += 3; 1624 lwr_macro(value, addr); 1625 value &= 0xffffffff; 1626 reg[MIPS_INST_RT(inst)] = value; 1627 return (MIPS_LWU_ACCESS); 1628 1629 case OP_LW: 1630 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); 1631 lwl_macro(value, addr); 1632 addr += 3; 1633 lwr_macro(value, addr); 1634 reg[MIPS_INST_RT(inst)] = value; 1635 return (MIPS_LW_ACCESS); 1636 1637#if defined(__mips_n32) || defined(__mips_n64) 1638 case OP_LD: 1639 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction.")); 1640 ldl_macro(value, addr); 1641 addr += 7; 1642 ldr_macro(value, addr); 1643 reg[MIPS_INST_RT(inst)] = value; 1644 return (MIPS_LD_ACCESS); 1645#endif 1646 1647 case OP_SH: 1648 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); 1649 value = reg[MIPS_INST_RT(inst)]; 1650 value_msb = value >> 8; 1651 sb_macro(value_msb, addr); 1652 addr += 1; 1653 sb_macro(value, addr); 1654 return (MIPS_SH_ACCESS); 1655 1656 case OP_SW: 1657 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); 1658 value = reg[MIPS_INST_RT(inst)]; 1659 swl_macro(value, addr); 1660 addr += 3; 1661 swr_macro(value, addr); 1662 return (MIPS_SW_ACCESS); 1663 1664#if defined(__mips_n32) || defined(__mips_n64) 1665 case OP_SD: 1666 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction.")); 1667 value = reg[MIPS_INST_RT(inst)]; 1668 sdl_macro(value, addr); 1669 addr += 7; 1670 sdr_macro(value, addr); 1671 return (MIPS_SD_ACCESS); 1672#endif 1673 } 1674 panic("%s: should not be reached.", __func__); 1675} 1676 1677 1678/* 1679 * XXX TODO: SMP? 1680 */ 1681static struct timeval unaligned_lasterr; 1682static int unaligned_curerr; 1683 1684static int unaligned_pps_log_limit = 4; 1685 1686SYSCTL_INT(_machdep, OID_AUTO, unaligned_log_pps_limit, CTLFLAG_RWTUN, 1687 &unaligned_pps_log_limit, 0, 1688 "limit number of userland unaligned log messages per second"); 1689 1690static int 1691emulate_unaligned_access(struct trapframe *frame, int mode) 1692{ 1693 register_t pc; 1694 int access_type = 0; 1695 struct thread *td = curthread; 1696 struct proc *p = curproc; 1697 1698 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1699 1700 /* 1701 * Fall through if it's instruction fetch exception 1702 */ 1703 if (!((pc & 3) || (pc == frame->badvaddr))) { 1704 1705 /* 1706 * Handle unaligned load and store 1707 */ 1708 1709 /* 1710 * Return access type if the instruction was emulated. 1711 * Otherwise restore pc and fall through. 1712 */ 1713 access_type = mips_unaligned_load_store(frame, 1714 mode, frame->badvaddr, pc); 1715 1716 if (access_type) { 1717 if (DELAYBRANCH(frame->cause)) 1718 frame->pc = MipsEmulateBranch(frame, frame->pc, 1719 0, 0); 1720 else 1721 frame->pc += 4; 1722 1723 if (ppsratecheck(&unaligned_lasterr, 1724 &unaligned_curerr, unaligned_pps_log_limit)) { 1725 /* XXX TODO: keep global/tid/pid counters? */ 1726 log(LOG_INFO, 1727 "Unaligned %s: pid=%ld (%s), tid=%ld, " 1728 "pc=%#jx, badvaddr=%#jx\n", 1729 access_name[access_type - 1], 1730 (long) p->p_pid, 1731 p->p_comm, 1732 (long) td->td_tid, 1733 (intmax_t)pc, 1734 (intmax_t)frame->badvaddr); 1735 } 1736 } 1737 } 1738 return access_type; 1739} 1740