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

Cache object: 52ab68f835581bab26e999507b3135e6


[ 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.