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.4/sys/mips/mips/trap.c 269752 2014-08-09 14:05:01Z markj $");
   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         
  533         type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
  534         if (TRAPF_USERMODE(trapframe)) {
  535                 type |= T_USER;
  536                 usermode = 1;
  537         } else {
  538                 usermode = 0;
  539         }
  540 
  541         /*
  542          * Enable hardware interrupts if they were on before the trap. If it
  543          * was off disable all so we don't accidently enable it when doing a
  544          * return to userland.
  545          */
  546         if (trapframe->sr & MIPS_SR_INT_IE) {
  547                 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
  548                 intr_enable();
  549         } else {
  550                 intr_disable();
  551         }
  552 
  553 #ifdef TRAP_DEBUG
  554         if (trap_debug) {
  555                 static vm_offset_t last_badvaddr = 0;
  556                 static vm_offset_t this_badvaddr = 0;
  557                 static int count = 0;
  558                 u_int32_t pid;
  559 
  560                 printf("trap type %x (%s - ", type,
  561                     trap_type[type & (~T_USER)]);
  562 
  563                 if (type & T_USER)
  564                         printf("user mode)\n");
  565                 else
  566                         printf("kernel mode)\n");
  567 
  568 #ifdef SMP
  569                 printf("cpuid = %d\n", PCPU_GET(cpuid));
  570 #endif
  571                 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
  572                 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
  573                     (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
  574                     (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
  575                     (curproc ? curproc->p_pid : -1), pid);
  576 
  577                 switch (type & ~T_USER) {
  578                 case T_TLB_MOD:
  579                 case T_TLB_LD_MISS:
  580                 case T_TLB_ST_MISS:
  581                 case T_ADDR_ERR_LD:
  582                 case T_ADDR_ERR_ST:
  583                         this_badvaddr = trapframe->badvaddr;
  584                         break;
  585                 case T_SYSCALL:
  586                         this_badvaddr = trapframe->ra;
  587                         break;
  588                 default:
  589                         this_badvaddr = trapframe->pc;
  590                         break;
  591                 }
  592                 if ((last_badvaddr == this_badvaddr) &&
  593                     ((type & ~T_USER) != T_SYSCALL)) {
  594                         if (++count == 3) {
  595                                 trap_frame_dump(trapframe);
  596                                 panic("too many faults at %p\n", (void *)last_badvaddr);
  597                         }
  598                 } else {
  599                         last_badvaddr = this_badvaddr;
  600                         count = 0;
  601                 }
  602         }
  603 #endif
  604 
  605 #ifdef KDTRACE_HOOKS
  606         /*
  607          * A trap can occur while DTrace executes a probe. Before
  608          * executing the probe, DTrace blocks re-scheduling and sets
  609          * a flag in it's per-cpu flags to indicate that it doesn't
  610          * want to fault. On returning from the probe, the no-fault
  611          * flag is cleared and finally re-scheduling is enabled.
  612          *
  613          * If the DTrace kernel module has registered a trap handler,
  614          * call it and if it returns non-zero, assume that it has
  615          * handled the trap and modified the trap frame so that this
  616          * function can return normally.
  617          */
  618         /*
  619          * XXXDTRACE: add pid probe handler here (if ever)
  620          */
  621         if (!usermode) {
  622                 if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe, type))
  623                         return (trapframe->pc);
  624         }
  625 #endif
  626 
  627         switch (type) {
  628         case T_MCHECK:
  629 #ifdef DDB
  630                 kdb_trap(type, 0, trapframe);
  631 #endif
  632                 panic("MCHECK\n");
  633                 break;
  634         case T_TLB_MOD:
  635                 /* check for kernel address */
  636                 if (KERNLAND(trapframe->badvaddr)) {
  637                         if (pmap_emulate_modified(kernel_pmap, 
  638                             trapframe->badvaddr) != 0) {
  639                                 ftype = VM_PROT_WRITE;
  640                                 goto kernel_fault;
  641                         }
  642                         return (trapframe->pc);
  643                 }
  644                 /* FALLTHROUGH */
  645 
  646         case T_TLB_MOD + T_USER:
  647                 pmap = &p->p_vmspace->vm_pmap;
  648                 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
  649                         ftype = VM_PROT_WRITE;
  650                         goto dofault;
  651                 }
  652                 if (!usermode)
  653                         return (trapframe->pc);
  654                 goto out;
  655 
  656         case T_TLB_LD_MISS:
  657         case T_TLB_ST_MISS:
  658                 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
  659                 /* check for kernel address */
  660                 if (KERNLAND(trapframe->badvaddr)) {
  661                         vm_offset_t va;
  662                         int rv;
  663 
  664         kernel_fault:
  665                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  666                         rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
  667                         if (rv == KERN_SUCCESS)
  668                                 return (trapframe->pc);
  669                         if (td->td_pcb->pcb_onfault != NULL) {
  670                                 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  671                                 td->td_pcb->pcb_onfault = NULL;
  672                                 return (pc);
  673                         }
  674                         goto err;
  675                 }
  676 
  677                 /*
  678                  * It is an error for the kernel to access user space except
  679                  * through the copyin/copyout routines.
  680                  */
  681                 if (td->td_pcb->pcb_onfault == NULL)
  682                         goto err;
  683 
  684                 /* check for fuswintr() or suswintr() getting a page fault */
  685                 /* XXX There must be a nicer way to do this.  */
  686                 if (td->td_pcb->pcb_onfault == fswintrberr) {
  687                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  688                         td->td_pcb->pcb_onfault = NULL;
  689                         return (pc);
  690                 }
  691 
  692                 goto dofault;
  693 
  694         case T_TLB_LD_MISS + T_USER:
  695                 ftype = VM_PROT_READ;
  696                 goto dofault;
  697 
  698         case T_TLB_ST_MISS + T_USER:
  699                 ftype = VM_PROT_WRITE;
  700 dofault:
  701                 {
  702                         vm_offset_t va;
  703                         struct vmspace *vm;
  704                         vm_map_t map;
  705                         int rv = 0;
  706 
  707                         vm = p->p_vmspace;
  708                         map = &vm->vm_map;
  709                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  710                         if (KERNLAND(trapframe->badvaddr)) {
  711                                 /*
  712                                  * Don't allow user-mode faults in kernel
  713                                  * address space.
  714                                  */
  715                                 goto nogo;
  716                         }
  717 
  718                         /*
  719                          * Keep swapout from messing with us during this
  720                          * critical time.
  721                          */
  722                         PROC_LOCK(p);
  723                         ++p->p_lock;
  724                         PROC_UNLOCK(p);
  725 
  726                         rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
  727 
  728                         PROC_LOCK(p);
  729                         --p->p_lock;
  730                         PROC_UNLOCK(p);
  731                         /*
  732                          * XXXDTRACE: add dtrace_doubletrap_func here?
  733                          */
  734 #ifdef VMFAULT_TRACE
  735                         printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
  736                             map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
  737                             ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
  738 #endif
  739 
  740                         if (rv == KERN_SUCCESS) {
  741                                 if (!usermode) {
  742                                         return (trapframe->pc);
  743                                 }
  744                                 goto out;
  745                         }
  746         nogo:
  747                         if (!usermode) {
  748                                 if (td->td_pcb->pcb_onfault != NULL) {
  749                                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  750                                         td->td_pcb->pcb_onfault = NULL;
  751                                         return (pc);
  752                                 }
  753                                 goto err;
  754                         }
  755                         ucode = ftype;
  756                         i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
  757                         addr = trapframe->pc;
  758 
  759                         msg = "BAD_PAGE_FAULT";
  760                         log_bad_page_fault(msg, trapframe, type);
  761 
  762                         break;
  763                 }
  764 
  765         case T_ADDR_ERR_LD + T_USER:    /* misaligned or kseg access */
  766         case T_ADDR_ERR_ST + T_USER:    /* misaligned or kseg access */
  767                 if (trapframe->badvaddr < 0 ||
  768                     trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
  769                         msg = "ADDRESS_SPACE_ERR";
  770                 } else if (allow_unaligned_acc) {
  771                         int mode;
  772 
  773                         if (type == (T_ADDR_ERR_LD + T_USER))
  774                                 mode = VM_PROT_READ;
  775                         else
  776                                 mode = VM_PROT_WRITE;
  777 
  778                         access_type = emulate_unaligned_access(trapframe, mode);
  779                         if (access_type != 0)
  780                                 goto out;
  781                         msg = "ALIGNMENT_FIX_ERR";
  782                 } else {
  783                         msg = "ADDRESS_ERR";
  784                 }
  785 
  786                 /* FALL THROUGH */
  787 
  788         case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
  789         case T_BUS_ERR_LD_ST + T_USER:  /* BERR asserted to cpu */
  790                 ucode = 0;      /* XXX should be VM_PROT_something */
  791                 i = SIGBUS;
  792                 addr = trapframe->pc;
  793                 if (!msg)
  794                         msg = "BUS_ERR";
  795                 log_bad_page_fault(msg, trapframe, type);
  796                 break;
  797 
  798         case T_SYSCALL + T_USER:
  799                 {
  800                         struct syscall_args sa;
  801                         int error;
  802 
  803                         sa.trapframe = trapframe;
  804                         error = syscallenter(td, &sa);
  805 
  806 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  807                         if (trp == trapdebug)
  808                                 trapdebug[TRAPSIZE - 1].code = sa.code;
  809                         else
  810                                 trp[-1].code = sa.code;
  811 #endif
  812                         trapdebug_enter(td->td_frame, -sa.code);
  813 
  814                         /*
  815                          * The sync'ing of I & D caches for SYS_ptrace() is
  816                          * done by procfs_domem() through procfs_rwmem()
  817                          * instead of being done here under a special check
  818                          * for SYS_ptrace().
  819                          */
  820                         syscallret(td, error, &sa);
  821                         return (trapframe->pc);
  822                 }
  823 
  824 #ifdef DDB
  825         case T_BREAK:
  826                 kdb_trap(type, 0, trapframe);
  827                 return (trapframe->pc);
  828 #endif
  829 
  830         case T_BREAK + T_USER:
  831                 {
  832                         intptr_t va;
  833                         uint32_t instr;
  834 
  835                         /* compute address of break instruction */
  836                         va = trapframe->pc;
  837                         if (DELAYBRANCH(trapframe->cause))
  838                                 va += sizeof(int);
  839 
  840                         /* read break instruction */
  841                         instr = fuword32((caddr_t)va);
  842 #if 0
  843                         printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
  844                             p->p_comm, p->p_pid, instr, trapframe->pc,
  845                             p->p_md.md_ss_addr, p->p_md.md_ss_instr);   /* XXX */
  846 #endif
  847                         if (td->td_md.md_ss_addr != va ||
  848                             instr != MIPS_BREAK_SSTEP) {
  849                                 i = SIGTRAP;
  850                                 addr = trapframe->pc;
  851                                 break;
  852                         }
  853                         /*
  854                          * The restoration of the original instruction and
  855                          * the clearing of the berakpoint will be done later
  856                          * by the call to ptrace_clear_single_step() in
  857                          * issignal() when SIGTRAP is processed.
  858                          */
  859                         addr = trapframe->pc;
  860                         i = SIGTRAP;
  861                         break;
  862                 }
  863 
  864         case T_IWATCH + T_USER:
  865         case T_DWATCH + T_USER:
  866                 {
  867                         intptr_t va;
  868 
  869                         /* compute address of trapped instruction */
  870                         va = trapframe->pc;
  871                         if (DELAYBRANCH(trapframe->cause))
  872                                 va += sizeof(int);
  873                         printf("watch exception @ %p\n", (void *)va);
  874                         i = SIGTRAP;
  875                         addr = va;
  876                         break;
  877                 }
  878 
  879         case T_TRAP + T_USER:
  880                 {
  881                         intptr_t va;
  882                         uint32_t instr;
  883                         struct trapframe *locr0 = td->td_frame;
  884 
  885                         /* compute address of trap instruction */
  886                         va = trapframe->pc;
  887                         if (DELAYBRANCH(trapframe->cause))
  888                                 va += sizeof(int);
  889                         /* read break instruction */
  890                         instr = fuword32((caddr_t)va);
  891 
  892                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
  893                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
  894                                     0);
  895                         } else {
  896                                 locr0->pc += sizeof(int);
  897                         }
  898                         addr = va;
  899                         i = SIGEMT;     /* Stuff it with something for now */
  900                         break;
  901                 }
  902 
  903         case T_RES_INST + T_USER:
  904                 {
  905                         InstFmt inst;
  906                         inst = *(InstFmt *)(intptr_t)trapframe->pc;
  907                         switch (inst.RType.op) {
  908                         case OP_SPECIAL3:
  909                                 switch (inst.RType.func) {
  910                                 case OP_RDHWR:
  911                                         /* Register 29 used for TLS */
  912                                         if (inst.RType.rd == 29) {
  913                                                 frame_regs = &(trapframe->zero);
  914                                                 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
  915 #if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
  916                                                 if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
  917                                                         frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE32;
  918                                                 else
  919 #endif
  920                                                 frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE;
  921                                                 trapframe->pc += sizeof(int);
  922                                                 goto out;
  923                                         }
  924                                 break;
  925                                 }
  926                         break;
  927                         }
  928 
  929                         log_illegal_instruction("RES_INST", trapframe);
  930                         i = SIGILL;
  931                         addr = trapframe->pc;
  932                 }
  933                 break;
  934         case T_C2E:
  935         case T_C2E + T_USER:
  936                 goto err;
  937                 break;
  938         case T_COP_UNUSABLE:
  939 #ifdef  CPU_CNMIPS
  940                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
  941                 /* Handle only COP2 exception */
  942                 if (cop != 2)
  943                         goto err;
  944 
  945                 addr = trapframe->pc;
  946                 /* save userland cop2 context if it has been touched */
  947                 if ((td->td_md.md_flags & MDTD_COP2USED) &&
  948                     (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
  949                         if (td->td_md.md_ucop2)
  950                                 octeon_cop2_save(td->td_md.md_ucop2);
  951                         else
  952                                 panic("COP2 was used in user mode but md_ucop2 is NULL");
  953                 }
  954 
  955                 if (td->td_md.md_cop2 == NULL) {
  956                         td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
  957                         if (td->td_md.md_cop2 == NULL)
  958                                 panic("Failed to allocate COP2 context");
  959                         memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
  960                 }
  961 
  962                 octeon_cop2_restore(td->td_md.md_cop2);
  963                 
  964                 /* Make userland re-request its context */
  965                 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
  966                 td->td_md.md_flags |= MDTD_COP2USED;
  967                 td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
  968                 /* Enable COP2, it will be disabled in cpu_switch */
  969                 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
  970                 return (trapframe->pc);
  971 #else
  972                 goto err;
  973                 break;
  974 #endif
  975 
  976         case T_COP_UNUSABLE + T_USER:
  977                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
  978                 if (cop == 1) {
  979 #if !defined(CPU_HAVEFPU)
  980                 /* FP (COP1) instruction */
  981                         log_illegal_instruction("COP1_UNUSABLE", trapframe);
  982                         i = SIGILL;
  983                         break;
  984 #else
  985                         addr = trapframe->pc;
  986                         MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
  987                         PCPU_SET(fpcurthread, td);
  988                         td->td_frame->sr |= MIPS_SR_COP_1_BIT;
  989                         td->td_md.md_flags |= MDTD_FPUSED;
  990                         goto out;
  991 #endif
  992                 }
  993 #ifdef  CPU_CNMIPS
  994                 else  if (cop == 2) {
  995                         addr = trapframe->pc;
  996                         if ((td->td_md.md_flags & MDTD_COP2USED) &&
  997                             (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
  998                                 if (td->td_md.md_cop2)
  999                                         octeon_cop2_save(td->td_md.md_cop2);
 1000                                 else
 1001                                         panic("COP2 was used in kernel mode but md_cop2 is NULL");
 1002                         }
 1003 
 1004                         if (td->td_md.md_ucop2 == NULL) {
 1005                                 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
 1006                                 if (td->td_md.md_ucop2 == NULL)
 1007                                         panic("Failed to allocate userland COP2 context");
 1008                                 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
 1009                         }
 1010 
 1011                         octeon_cop2_restore(td->td_md.md_ucop2);
 1012 
 1013                         td->td_frame->sr |= MIPS_SR_COP_2_BIT;
 1014                         td->td_md.md_flags |= MDTD_COP2USED;
 1015                         td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
 1016                         goto out;
 1017                 }
 1018 #endif
 1019                 else {
 1020                         log_illegal_instruction("COPn_UNUSABLE", trapframe);
 1021                         i = SIGILL;     /* only FPU instructions allowed */
 1022                         break;
 1023                 }
 1024 
 1025         case T_FPE:
 1026 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
 1027                 trapDump("fpintr");
 1028 #else
 1029                 printf("FPU Trap: PC %#jx CR %x SR %x\n",
 1030                     (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
 1031                 goto err;
 1032 #endif
 1033 
 1034         case T_FPE + T_USER:
 1035                 if (!emulate_fp) {
 1036                         i = SIGILL;
 1037                         addr = trapframe->pc;
 1038                         break;
 1039                 }
 1040                 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
 1041                 goto out;
 1042 
 1043         case T_OVFLOW + T_USER:
 1044                 i = SIGFPE;
 1045                 addr = trapframe->pc;
 1046                 break;
 1047 
 1048         case T_ADDR_ERR_LD:     /* misaligned access */
 1049         case T_ADDR_ERR_ST:     /* misaligned access */
 1050 #ifdef TRAP_DEBUG
 1051                 if (trap_debug) {
 1052                         printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
 1053                             (intmax_t)trapframe->badvaddr);
 1054                 }
 1055 #endif
 1056                 /* Only allow emulation on a user address */
 1057                 if (allow_unaligned_acc &&
 1058                     ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
 1059                         int mode;
 1060 
 1061                         if (type == T_ADDR_ERR_LD)
 1062                                 mode = VM_PROT_READ;
 1063                         else
 1064                                 mode = VM_PROT_WRITE;
 1065 
 1066                         access_type = emulate_unaligned_access(trapframe, mode);
 1067                         if (access_type != 0)
 1068                                 return (trapframe->pc);
 1069                 }
 1070                 /* FALLTHROUGH */
 1071 
 1072         case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
 1073                 if (td->td_pcb->pcb_onfault != NULL) {
 1074                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
 1075                         td->td_pcb->pcb_onfault = NULL;
 1076                         return (pc);
 1077                 }
 1078 
 1079                 /* FALLTHROUGH */
 1080 
 1081         default:
 1082 err:
 1083 
 1084 #if !defined(SMP) && defined(DEBUG)
 1085                 stacktrace(!usermode ? trapframe : td->td_frame);
 1086                 trapDump("trap");
 1087 #endif
 1088 #ifdef SMP
 1089                 printf("cpu:%d-", PCPU_GET(cpuid));
 1090 #endif
 1091                 printf("Trap cause = %d (%s - ", type,
 1092                     trap_type[type & (~T_USER)]);
 1093 
 1094                 if (type & T_USER)
 1095                         printf("user mode)\n");
 1096                 else
 1097                         printf("kernel mode)\n");
 1098 
 1099 #ifdef TRAP_DEBUG
 1100                 if (trap_debug)
 1101                         printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
 1102                                (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
 1103                                (intmax_t)trapframe->sr);
 1104 #endif
 1105 
 1106 #ifdef KDB
 1107                 if (debugger_on_panic || kdb_active) {
 1108                         kdb_trap(type, 0, trapframe);
 1109                 }
 1110 #endif
 1111                 panic("trap");
 1112         }
 1113         td->td_frame->pc = trapframe->pc;
 1114         td->td_frame->cause = trapframe->cause;
 1115         td->td_frame->badvaddr = trapframe->badvaddr;
 1116         ksiginfo_init_trap(&ksi);
 1117         ksi.ksi_signo = i;
 1118         ksi.ksi_code = ucode;
 1119         ksi.ksi_addr = (void *)addr;
 1120         ksi.ksi_trapno = type;
 1121         trapsignal(td, &ksi);
 1122 out:
 1123 
 1124         /*
 1125          * Note: we should only get here if returning to user mode.
 1126          */
 1127         userret(td, trapframe);
 1128         return (trapframe->pc);
 1129 }
 1130 
 1131 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
 1132 void
 1133 trapDump(char *msg)
 1134 {
 1135         register_t s;
 1136         int i;
 1137 
 1138         s = intr_disable();
 1139         printf("trapDump(%s)\n", msg);
 1140         for (i = 0; i < TRAPSIZE; i++) {
 1141                 if (trp == trapdebug) {
 1142                         trp = &trapdebug[TRAPSIZE - 1];
 1143                 } else {
 1144                         trp--;
 1145                 }
 1146 
 1147                 if (trp->cause == 0)
 1148                         break;
 1149 
 1150                 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
 1151                     trap_type[(trp->cause & MIPS_CR_EXC_CODE) >> 
 1152                         MIPS_CR_EXC_CODE_SHIFT],
 1153                     (intmax_t)trp->vadr, (intmax_t)trp->pc,
 1154                     (intmax_t)trp->cause, (intmax_t)trp->status);
 1155 
 1156                 printf("   RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
 1157                     (intmax_t)trp->sp, (int)trp->code);
 1158         }
 1159         intr_restore(s);
 1160 }
 1161 #endif
 1162 
 1163 
 1164 /*
 1165  * Return the resulting PC as if the branch was executed.
 1166  */
 1167 uintptr_t
 1168 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
 1169     uintptr_t instptr)
 1170 {
 1171         InstFmt inst;
 1172         register_t *regsPtr = (register_t *) framePtr;
 1173         uintptr_t retAddr = 0;
 1174         int condition;
 1175 
 1176 #define GetBranchDest(InstPtr, inst) \
 1177         (InstPtr + 4 + ((short)inst.IType.imm << 2))
 1178 
 1179 
 1180         if (instptr) {
 1181                 if (instptr < MIPS_KSEG0_START)
 1182                         inst.word = fuword32((void *)instptr);
 1183                 else
 1184                         inst = *(InstFmt *) instptr;
 1185         } else {
 1186                 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
 1187                         inst.word = fuword32((void *)instPC);
 1188                 else
 1189                         inst = *(InstFmt *) instPC;
 1190         }
 1191 
 1192         switch ((int)inst.JType.op) {
 1193         case OP_SPECIAL:
 1194                 switch ((int)inst.RType.func) {
 1195                 case OP_JR:
 1196                 case OP_JALR:
 1197                         retAddr = regsPtr[inst.RType.rs];
 1198                         break;
 1199 
 1200                 default:
 1201                         retAddr = instPC + 4;
 1202                         break;
 1203                 }
 1204                 break;
 1205 
 1206         case OP_BCOND:
 1207                 switch ((int)inst.IType.rt) {
 1208                 case OP_BLTZ:
 1209                 case OP_BLTZL:
 1210                 case OP_BLTZAL:
 1211                 case OP_BLTZALL:
 1212                         if ((int)(regsPtr[inst.RType.rs]) < 0)
 1213                                 retAddr = GetBranchDest(instPC, inst);
 1214                         else
 1215                                 retAddr = instPC + 8;
 1216                         break;
 1217 
 1218                 case OP_BGEZ:
 1219                 case OP_BGEZL:
 1220                 case OP_BGEZAL:
 1221                 case OP_BGEZALL:
 1222                         if ((int)(regsPtr[inst.RType.rs]) >= 0)
 1223                                 retAddr = GetBranchDest(instPC, inst);
 1224                         else
 1225                                 retAddr = instPC + 8;
 1226                         break;
 1227 
 1228                 case OP_TGEI:
 1229                 case OP_TGEIU:
 1230                 case OP_TLTI:
 1231                 case OP_TLTIU:
 1232                 case OP_TEQI:
 1233                 case OP_TNEI:
 1234                         retAddr = instPC + 4;   /* Like syscall... */
 1235                         break;
 1236 
 1237                 default:
 1238                         panic("MipsEmulateBranch: Bad branch cond");
 1239                 }
 1240                 break;
 1241 
 1242         case OP_J:
 1243         case OP_JAL:
 1244                 retAddr = (inst.JType.target << 2) |
 1245                     ((unsigned)(instPC + 4) & 0xF0000000);
 1246                 break;
 1247 
 1248         case OP_BEQ:
 1249         case OP_BEQL:
 1250                 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
 1251                         retAddr = GetBranchDest(instPC, inst);
 1252                 else
 1253                         retAddr = instPC + 8;
 1254                 break;
 1255 
 1256         case OP_BNE:
 1257         case OP_BNEL:
 1258                 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
 1259                         retAddr = GetBranchDest(instPC, inst);
 1260                 else
 1261                         retAddr = instPC + 8;
 1262                 break;
 1263 
 1264         case OP_BLEZ:
 1265         case OP_BLEZL:
 1266                 if ((int)(regsPtr[inst.RType.rs]) <= 0)
 1267                         retAddr = GetBranchDest(instPC, inst);
 1268                 else
 1269                         retAddr = instPC + 8;
 1270                 break;
 1271 
 1272         case OP_BGTZ:
 1273         case OP_BGTZL:
 1274                 if ((int)(regsPtr[inst.RType.rs]) > 0)
 1275                         retAddr = GetBranchDest(instPC, inst);
 1276                 else
 1277                         retAddr = instPC + 8;
 1278                 break;
 1279 
 1280         case OP_COP1:
 1281                 switch (inst.RType.rs) {
 1282                 case OP_BCx:
 1283                 case OP_BCy:
 1284                         if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
 1285                                 condition = fpcCSR & MIPS_FPU_COND_BIT;
 1286                         else
 1287                                 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
 1288                         if (condition)
 1289                                 retAddr = GetBranchDest(instPC, inst);
 1290                         else
 1291                                 retAddr = instPC + 8;
 1292                         break;
 1293 
 1294                 default:
 1295                         retAddr = instPC + 4;
 1296                 }
 1297                 break;
 1298 
 1299         default:
 1300                 retAddr = instPC + 4;
 1301         }
 1302         return (retAddr);
 1303 }
 1304 
 1305 
 1306 #if defined(DDB) || defined(DEBUG)
 1307 /*
 1308  * Print a stack backtrace.
 1309  */
 1310 void
 1311 stacktrace(struct trapframe *regs)
 1312 {
 1313         stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
 1314 }
 1315 #endif
 1316 
 1317 static void
 1318 log_frame_dump(struct trapframe *frame)
 1319 {
 1320         log(LOG_ERR, "Trapframe Register Dump:\n");
 1321         log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
 1322             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
 1323 
 1324         log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
 1325             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
 1326 
 1327 #if defined(__mips_n32) || defined(__mips_n64)
 1328         log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
 1329             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
 1330 
 1331         log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1332             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1333 #else
 1334         log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1335             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1336 
 1337         log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
 1338             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
 1339 #endif
 1340         log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
 1341             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
 1342 
 1343         log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
 1344             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
 1345 
 1346         log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
 1347             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
 1348 
 1349         log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
 1350             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
 1351 
 1352         log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
 1353             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
 1354 
 1355 #ifdef IC_REG
 1356         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
 1357             (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
 1358 #else
 1359         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
 1360             (intmax_t)frame->cause, (intmax_t)frame->pc);
 1361 #endif
 1362 }
 1363 
 1364 #ifdef TRAP_DEBUG
 1365 static void
 1366 trap_frame_dump(struct trapframe *frame)
 1367 {
 1368         printf("Trapframe Register Dump:\n");
 1369         printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
 1370             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
 1371 
 1372         printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
 1373             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
 1374 #if defined(__mips_n32) || defined(__mips_n64)
 1375         printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
 1376             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
 1377 
 1378         printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1379             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1380 #else
 1381         printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1382             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1383 
 1384         printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
 1385             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
 1386 #endif
 1387         printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
 1388             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
 1389 
 1390         printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
 1391             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
 1392 
 1393         printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
 1394             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
 1395 
 1396         printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
 1397             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
 1398 
 1399         printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
 1400             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
 1401 
 1402 #ifdef IC_REG
 1403         printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
 1404             (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
 1405 #else
 1406         printf("\tcause: %#jx\tpc: %#jx\n",
 1407             (intmax_t)frame->cause, (intmax_t)frame->pc);
 1408 #endif
 1409 }
 1410 
 1411 #endif
 1412 
 1413 
 1414 static void
 1415 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
 1416 {
 1417         pt_entry_t *ptep;
 1418         pd_entry_t *pdep;
 1419         struct proc *p = curproc;
 1420 
 1421         pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
 1422         if (*pdep)
 1423                 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
 1424         else
 1425                 ptep = (pt_entry_t *)0;
 1426 
 1427         *pdepp = pdep;
 1428         *ptepp = ptep;
 1429 }
 1430 
 1431 static void
 1432 log_illegal_instruction(const char *msg, struct trapframe *frame)
 1433 {
 1434         pt_entry_t *ptep;
 1435         pd_entry_t *pdep;
 1436         unsigned int *addr;
 1437         struct thread *td;
 1438         struct proc *p;
 1439         register_t pc;
 1440 
 1441         td = curthread;
 1442         p = td->td_proc;
 1443 
 1444 #ifdef SMP
 1445         printf("cpuid = %d\n", PCPU_GET(cpuid));
 1446 #endif
 1447         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1448         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
 1449             msg, p->p_pid, (long)td->td_tid, p->p_comm,
 1450             p->p_ucred ? p->p_ucred->cr_uid : -1,
 1451             (intmax_t)pc,
 1452             (intmax_t)frame->ra);
 1453 
 1454         /* log registers in trap frame */
 1455         log_frame_dump(frame);
 1456 
 1457         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
 1458 
 1459         /*
 1460          * Dump a few words around faulting instruction, if the addres is
 1461          * valid.
 1462          */
 1463         if (!(pc & 3) &&
 1464             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
 1465                 /* dump page table entry for faulting instruction */
 1466                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
 1467                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1468 
 1469                 addr = (unsigned int *)(intptr_t)pc;
 1470                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
 1471                     addr);
 1472                 log(LOG_ERR, "%08x %08x %08x %08x\n",
 1473                     addr[0], addr[1], addr[2], addr[3]);
 1474         } else {
 1475                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
 1476                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1477         }
 1478 }
 1479 
 1480 static void
 1481 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
 1482 {
 1483         pt_entry_t *ptep;
 1484         pd_entry_t *pdep;
 1485         unsigned int *addr;
 1486         struct thread *td;
 1487         struct proc *p;
 1488         char *read_or_write;
 1489         register_t pc;
 1490 
 1491         trap_type &= ~T_USER;
 1492 
 1493         td = curthread;
 1494         p = td->td_proc;
 1495 
 1496 #ifdef SMP
 1497         printf("cpuid = %d\n", PCPU_GET(cpuid));
 1498 #endif
 1499         switch (trap_type) {
 1500         case T_TLB_MOD:
 1501         case T_TLB_ST_MISS:
 1502         case T_ADDR_ERR_ST:
 1503                 read_or_write = "write";
 1504                 break;
 1505         case T_TLB_LD_MISS:
 1506         case T_ADDR_ERR_LD:
 1507         case T_BUS_ERR_IFETCH:
 1508                 read_or_write = "read";
 1509                 break;
 1510         default:
 1511                 read_or_write = "unknown";
 1512         }
 1513 
 1514         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1515         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
 1516             "(type %#x) at %#jx\n",
 1517             msg, p->p_pid, (long)td->td_tid, p->p_comm,
 1518             p->p_ucred ? p->p_ucred->cr_uid : -1,
 1519             (intmax_t)pc,
 1520             read_or_write,
 1521             trap_type,
 1522             (intmax_t)frame->badvaddr);
 1523 
 1524         /* log registers in trap frame */
 1525         log_frame_dump(frame);
 1526 
 1527         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
 1528 
 1529         /*
 1530          * Dump a few words around faulting instruction, if the addres is
 1531          * valid.
 1532          */
 1533         if (!(pc & 3) && (pc != frame->badvaddr) &&
 1534             (trap_type != T_BUS_ERR_IFETCH) &&
 1535             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
 1536                 /* dump page table entry for faulting instruction */
 1537                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
 1538                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1539 
 1540                 addr = (unsigned int *)(intptr_t)pc;
 1541                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
 1542                     addr);
 1543                 log(LOG_ERR, "%08x %08x %08x %08x\n",
 1544                     addr[0], addr[1], addr[2], addr[3]);
 1545         } else {
 1546                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
 1547                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1548         }
 1549 
 1550         get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
 1551         log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
 1552             (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1553 }
 1554 
 1555 
 1556 /*
 1557  * Unaligned load/store emulation
 1558  */
 1559 static int
 1560 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
 1561 {
 1562         register_t *reg = (register_t *) frame;
 1563         u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
 1564         register_t value_msb, value;
 1565         unsigned size;
 1566 
 1567         /*
 1568          * ADDR_ERR faults have higher priority than TLB
 1569          * Miss faults.  Therefore, it is necessary to
 1570          * verify that the faulting address is a valid
 1571          * virtual address within the process' address space
 1572          * before trying to emulate the unaligned access.
 1573          */
 1574         switch (MIPS_INST_OPCODE(inst)) {
 1575         case OP_LHU: case OP_LH:
 1576         case OP_SH:
 1577                 size = 2;
 1578                 break;
 1579         case OP_LWU: case OP_LW:
 1580         case OP_SW:
 1581                 size = 4;
 1582                 break;
 1583         case OP_LD:
 1584         case OP_SD:
 1585                 size = 8;
 1586                 break;
 1587         default:
 1588                 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
 1589                 return (0);
 1590         }
 1591 
 1592         if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
 1593                 return (0);
 1594 
 1595         /*
 1596          * XXX
 1597          * Handle LL/SC LLD/SCD.
 1598          */
 1599         switch (MIPS_INST_OPCODE(inst)) {
 1600         case OP_LHU:
 1601                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1602                 lbu_macro(value_msb, addr);
 1603                 addr += 1;
 1604                 lbu_macro(value, addr);
 1605                 value |= value_msb << 8;
 1606                 reg[MIPS_INST_RT(inst)] = value;
 1607                 return (MIPS_LHU_ACCESS);
 1608 
 1609         case OP_LH:
 1610                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1611                 lb_macro(value_msb, addr);
 1612                 addr += 1;
 1613                 lbu_macro(value, addr);
 1614                 value |= value_msb << 8;
 1615                 reg[MIPS_INST_RT(inst)] = value;
 1616                 return (MIPS_LH_ACCESS);
 1617 
 1618         case OP_LWU:
 1619                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1620                 lwl_macro(value, addr);
 1621                 addr += 3;
 1622                 lwr_macro(value, addr);
 1623                 value &= 0xffffffff;
 1624                 reg[MIPS_INST_RT(inst)] = value;
 1625                 return (MIPS_LWU_ACCESS);
 1626 
 1627         case OP_LW:
 1628                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1629                 lwl_macro(value, addr);
 1630                 addr += 3;
 1631                 lwr_macro(value, addr);
 1632                 reg[MIPS_INST_RT(inst)] = value;
 1633                 return (MIPS_LW_ACCESS);
 1634 
 1635 #if defined(__mips_n32) || defined(__mips_n64)
 1636         case OP_LD:
 1637                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1638                 ldl_macro(value, addr);
 1639                 addr += 7;
 1640                 ldr_macro(value, addr);
 1641                 reg[MIPS_INST_RT(inst)] = value;
 1642                 return (MIPS_LD_ACCESS);
 1643 #endif
 1644 
 1645         case OP_SH:
 1646                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1647                 value = reg[MIPS_INST_RT(inst)];
 1648                 value_msb = value >> 8;
 1649                 sb_macro(value_msb, addr);
 1650                 addr += 1;
 1651                 sb_macro(value, addr);
 1652                 return (MIPS_SH_ACCESS);
 1653 
 1654         case OP_SW:
 1655                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1656                 value = reg[MIPS_INST_RT(inst)];
 1657                 swl_macro(value, addr);
 1658                 addr += 3;
 1659                 swr_macro(value, addr);
 1660                 return (MIPS_SW_ACCESS);
 1661 
 1662 #if defined(__mips_n32) || defined(__mips_n64)
 1663         case OP_SD:
 1664                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1665                 value = reg[MIPS_INST_RT(inst)];
 1666                 sdl_macro(value, addr);
 1667                 addr += 7;
 1668                 sdr_macro(value, addr);
 1669                 return (MIPS_SD_ACCESS);
 1670 #endif
 1671         }
 1672         panic("%s: should not be reached.", __func__);
 1673 }
 1674 
 1675 
 1676 static int
 1677 emulate_unaligned_access(struct trapframe *frame, int mode)
 1678 {
 1679         register_t pc;
 1680         int access_type = 0;
 1681 
 1682         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1683 
 1684         /*
 1685          * Fall through if it's instruction fetch exception
 1686          */
 1687         if (!((pc & 3) || (pc == frame->badvaddr))) {
 1688 
 1689                 /*
 1690                  * Handle unaligned load and store
 1691                  */
 1692 
 1693                 /*
 1694                  * Return access type if the instruction was emulated.
 1695                  * Otherwise restore pc and fall through.
 1696                  */
 1697                 access_type = mips_unaligned_load_store(frame,
 1698                     mode, frame->badvaddr, pc);
 1699 
 1700                 if (access_type) {
 1701                         if (DELAYBRANCH(frame->cause))
 1702                                 frame->pc = MipsEmulateBranch(frame, frame->pc,
 1703                                     0, 0);
 1704                         else
 1705                                 frame->pc += 4;
 1706 
 1707                         log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
 1708                             access_name[access_type - 1], (intmax_t)pc,
 1709                             (intmax_t)frame->badvaddr);
 1710                 }
 1711         }
 1712         return access_type;
 1713 }

Cache object: 8815c5b5cc6927dd56b5fa0843e9dd54


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