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

Cache object: 78ec183bc33e58d25002dcce6aee910b


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