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