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


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

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

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

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

Cache object: 970e486f807c970cb5d233bbf023079f


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