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

Cache object: 32bca45d3060de30e10a40025a83254b


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