The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/trap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 56c9a0433cac7dcf28202f8d2ee023ac


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.