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


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

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

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

    1 /*      $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $  */
    2 /* tracked to 1.23 */
    3 /*-
    4  * Copyright (c) 1988 University of Utah.
    5  * Copyright (c) 1992, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * the Systems Programming Group of the University of Utah Computer
   10  * Science Department and Ralph Campbell.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * from: Utah Hdr: trap.c 1.32 91/04/06
   37  *
   38  *      from: @(#)trap.c        8.5 (Berkeley) 1/11/94
   39  *      JNPR: trap.c,v 1.13.2.2 2007/08/29 10:03:49 girish
   40  */
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD: releng/9.0/sys/mips/mips/trap.c 223562 2011-06-26 10:07:48Z kevlo $");
   43 
   44 #include "opt_ddb.h"
   45 #include "opt_global.h"
   46 #include "opt_ktrace.h"
   47 
   48 #define NO_REG_DEFS     1       /* Prevent asm.h from including regdef.h */
   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/pte.h>
   80 #include <machine/pmap.h>
   81 #include <machine/md_var.h>
   82 #include <machine/mips_opcode.h>
   83 #include <machine/frame.h>
   84 #include <machine/regnum.h>
   85 #include <machine/asm.h>
   86 
   87 #ifdef DDB
   88 #include <machine/db_machdep.h>
   89 #include <ddb/db_sym.h>
   90 #include <ddb/ddb.h>
   91 #include <sys/kdb.h>
   92 #endif
   93 
   94 #ifdef TRAP_DEBUG
   95 int trap_debug = 0;
   96 SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
   97     &trap_debug, 0, "Debug information on all traps");
   98 #endif
   99 
  100 static void log_illegal_instruction(const char *, struct trapframe *);
  101 static void log_bad_page_fault(char *, struct trapframe *, int);
  102 static void log_frame_dump(struct trapframe *frame);
  103 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
  104 
  105 #ifdef TRAP_DEBUG
  106 static void trap_frame_dump(struct trapframe *frame);
  107 #endif
  108 
  109 void (*machExceptionTable[]) (void)= {
  110 /*
  111  * The kernel exception handlers.
  112  */
  113         MipsKernIntr,           /* external interrupt */
  114         MipsKernGenException,   /* TLB modification */
  115         MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
  116         MipsTLBInvalidException,/* TLB miss (store) */
  117         MipsKernGenException,   /* address error (load or I-fetch) */
  118         MipsKernGenException,   /* address error (store) */
  119         MipsKernGenException,   /* bus error (I-fetch) */
  120         MipsKernGenException,   /* bus error (load or store) */
  121         MipsKernGenException,   /* system call */
  122         MipsKernGenException,   /* breakpoint */
  123         MipsKernGenException,   /* reserved instruction */
  124         MipsKernGenException,   /* coprocessor unusable */
  125         MipsKernGenException,   /* arithmetic overflow */
  126         MipsKernGenException,   /* trap exception */
  127         MipsKernGenException,   /* virtual coherence exception inst */
  128         MipsKernGenException,   /* floating point exception */
  129         MipsKernGenException,   /* reserved */
  130         MipsKernGenException,   /* reserved */
  131         MipsKernGenException,   /* reserved */
  132         MipsKernGenException,   /* reserved */
  133         MipsKernGenException,   /* reserved */
  134         MipsKernGenException,   /* reserved */
  135         MipsKernGenException,   /* reserved */
  136         MipsKernGenException,   /* watch exception */
  137         MipsKernGenException,   /* reserved */
  138         MipsKernGenException,   /* reserved */
  139         MipsKernGenException,   /* reserved */
  140         MipsKernGenException,   /* reserved */
  141         MipsKernGenException,   /* reserved */
  142         MipsKernGenException,   /* reserved */
  143         MipsKernGenException,   /* reserved */
  144         MipsKernGenException,   /* virtual coherence exception data */
  145 /*
  146  * The user exception handlers.
  147  */
  148         MipsUserIntr,           /* 0 */
  149         MipsUserGenException,   /* 1 */
  150         MipsTLBInvalidException,/* 2 */
  151         MipsTLBInvalidException,/* 3 */
  152         MipsUserGenException,   /* 4 */
  153         MipsUserGenException,   /* 5 */
  154         MipsUserGenException,   /* 6 */
  155         MipsUserGenException,   /* 7 */
  156         MipsUserGenException,   /* 8 */
  157         MipsUserGenException,   /* 9 */
  158         MipsUserGenException,   /* 10 */
  159         MipsUserGenException,   /* 11 */
  160         MipsUserGenException,   /* 12 */
  161         MipsUserGenException,   /* 13 */
  162         MipsUserGenException,   /* 14 */
  163         MipsUserGenException,   /* 15 */
  164         MipsUserGenException,   /* 16 */
  165         MipsUserGenException,   /* 17 */
  166         MipsUserGenException,   /* 18 */
  167         MipsUserGenException,   /* 19 */
  168         MipsUserGenException,   /* 20 */
  169         MipsUserGenException,   /* 21 */
  170         MipsUserGenException,   /* 22 */
  171         MipsUserGenException,   /* 23 */
  172         MipsUserGenException,   /* 24 */
  173         MipsUserGenException,   /* 25 */
  174         MipsUserGenException,   /* 26 */
  175         MipsUserGenException,   /* 27 */
  176         MipsUserGenException,   /* 28 */
  177         MipsUserGenException,   /* 29 */
  178         MipsUserGenException,   /* 20 */
  179         MipsUserGenException,   /* 31 */
  180 };
  181 
  182 char *trap_type[] = {
  183         "external interrupt",
  184         "TLB modification",
  185         "TLB miss (load or instr. fetch)",
  186         "TLB miss (store)",
  187         "address error (load or I-fetch)",
  188         "address error (store)",
  189         "bus error (I-fetch)",
  190         "bus error (load or store)",
  191         "system call",
  192         "breakpoint",
  193         "reserved instruction",
  194         "coprocessor unusable",
  195         "arithmetic overflow",
  196         "trap",
  197         "virtual coherency instruction",
  198         "floating point",
  199         "reserved 16",
  200         "reserved 17",
  201         "reserved 18",
  202         "reserved 19",
  203         "reserved 20",
  204         "reserved 21",
  205         "reserved 22",
  206         "watch",
  207         "reserved 24",
  208         "reserved 25",
  209         "reserved 26",
  210         "reserved 27",
  211         "reserved 28",
  212         "reserved 29",
  213         "reserved 30",
  214         "virtual coherency data",
  215 };
  216 
  217 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  218 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
  219 #endif
  220 
  221 #if defined(DDB) || defined(DEBUG)
  222 void stacktrace(struct trapframe *);
  223 void logstacktrace(struct trapframe *);
  224 #endif
  225 
  226 #define KERNLAND(x)     ((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS)
  227 #define DELAYBRANCH(x)  ((int)(x) < 0)
  228 
  229 /*
  230  * MIPS load/store access type
  231  */
  232 enum {
  233         MIPS_LHU_ACCESS = 1,
  234         MIPS_LH_ACCESS,
  235         MIPS_LWU_ACCESS,
  236         MIPS_LW_ACCESS,
  237         MIPS_LD_ACCESS,
  238         MIPS_SH_ACCESS,
  239         MIPS_SW_ACCESS,
  240         MIPS_SD_ACCESS
  241 };
  242 
  243 char *access_name[] = {
  244         "Load Halfword Unsigned",
  245         "Load Halfword",
  246         "Load Word Unsigned",
  247         "Load Word",
  248         "Load Doubleword",
  249         "Store Halfword",
  250         "Store Word",
  251         "Store Doubleword"
  252 };
  253 
  254 
  255 static int allow_unaligned_acc = 1;
  256 
  257 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
  258     &allow_unaligned_acc, 0, "Allow unaligned accesses");
  259 
  260 static int emulate_unaligned_access(struct trapframe *frame, int mode);
  261 
  262 extern void fswintrberr(void); /* XXX */
  263 
  264 /*
  265  * Handle an exception.
  266  * Called from MipsKernGenException() or MipsUserGenException()
  267  * when a processor trap occurs.
  268  * In the case of a kernel trap, we return the pc where to resume if
  269  * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
  270  */
  271 register_t
  272 trap(struct trapframe *trapframe)
  273 {
  274         int type, usermode;
  275         int i = 0;
  276         unsigned ucode = 0;
  277         struct thread *td = curthread;
  278         struct proc *p = curproc;
  279         vm_prot_t ftype;
  280         pmap_t pmap;
  281         int access_type;
  282         ksiginfo_t ksi;
  283         char *msg = NULL;
  284         intptr_t addr = 0;
  285         register_t pc;
  286 
  287         trapdebug_enter(trapframe, 0);
  288         
  289         type = (trapframe->cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
  290         if (TRAPF_USERMODE(trapframe)) {
  291                 type |= T_USER;
  292                 usermode = 1;
  293         } else {
  294                 usermode = 0;
  295         }
  296 
  297         /*
  298          * Enable hardware interrupts if they were on before the trap. If it
  299          * was off disable all so we don't accidently enable it when doing a
  300          * return to userland.
  301          */
  302         if (trapframe->sr & MIPS_SR_INT_IE) {
  303                 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
  304                 intr_enable();
  305         } else {
  306                 intr_disable();
  307         }
  308 
  309 #ifdef TRAP_DEBUG
  310         if (trap_debug) {
  311                 static vm_offset_t last_badvaddr = 0;
  312                 static vm_offset_t this_badvaddr = 0;
  313                 static int count = 0;
  314                 u_int32_t pid;
  315 
  316                 printf("trap type %x (%s - ", type,
  317                     trap_type[type & (~T_USER)]);
  318 
  319                 if (type & T_USER)
  320                         printf("user mode)\n");
  321                 else
  322                         printf("kernel mode)\n");
  323 
  324 #ifdef SMP
  325                 printf("cpuid = %d\n", PCPU_GET(cpuid));
  326 #endif
  327                 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
  328                 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
  329                     (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
  330                     (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
  331                     (curproc ? curproc->p_pid : -1), pid);
  332 
  333                 switch (type & ~T_USER) {
  334                 case T_TLB_MOD:
  335                 case T_TLB_LD_MISS:
  336                 case T_TLB_ST_MISS:
  337                 case T_ADDR_ERR_LD:
  338                 case T_ADDR_ERR_ST:
  339                         this_badvaddr = trapframe->badvaddr;
  340                         break;
  341                 case T_SYSCALL:
  342                         this_badvaddr = trapframe->ra;
  343                         break;
  344                 default:
  345                         this_badvaddr = trapframe->pc;
  346                         break;
  347                 }
  348                 if ((last_badvaddr == this_badvaddr) &&
  349                     ((type & ~T_USER) != T_SYSCALL)) {
  350                         if (++count == 3) {
  351                                 trap_frame_dump(trapframe);
  352                                 panic("too many faults at %p\n", (void *)last_badvaddr);
  353                         }
  354                 } else {
  355                         last_badvaddr = this_badvaddr;
  356                         count = 0;
  357                 }
  358         }
  359 #endif
  360         switch (type) {
  361         case T_MCHECK:
  362 #ifdef DDB
  363                 kdb_trap(type, 0, trapframe);
  364 #endif
  365                 panic("MCHECK\n");
  366                 break;
  367         case T_TLB_MOD:
  368                 /* check for kernel address */
  369                 if (KERNLAND(trapframe->badvaddr)) {
  370                         if (pmap_emulate_modified(kernel_pmap, 
  371                             trapframe->badvaddr) != 0) {
  372                                 ftype = VM_PROT_WRITE;
  373                                 goto kernel_fault;
  374                         }
  375                         return (trapframe->pc);
  376                 }
  377                 /* FALLTHROUGH */
  378 
  379         case T_TLB_MOD + T_USER:
  380                 pmap = &p->p_vmspace->vm_pmap;
  381                 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
  382                         ftype = VM_PROT_WRITE;
  383                         goto dofault;
  384                 }
  385                 if (!usermode)
  386                         return (trapframe->pc);
  387                 goto out;
  388 
  389         case T_TLB_LD_MISS:
  390         case T_TLB_ST_MISS:
  391                 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
  392                 /* check for kernel address */
  393                 if (KERNLAND(trapframe->badvaddr)) {
  394                         vm_offset_t va;
  395                         int rv;
  396 
  397         kernel_fault:
  398                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  399                         rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
  400                         if (rv == KERN_SUCCESS)
  401                                 return (trapframe->pc);
  402                         if (td->td_pcb->pcb_onfault != NULL) {
  403                                 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  404                                 td->td_pcb->pcb_onfault = NULL;
  405                                 return (pc);
  406                         }
  407                         goto err;
  408                 }
  409 
  410                 /*
  411                  * It is an error for the kernel to access user space except
  412                  * through the copyin/copyout routines.
  413                  */
  414                 if (td->td_pcb->pcb_onfault == NULL)
  415                         goto err;
  416 
  417                 /* check for fuswintr() or suswintr() getting a page fault */
  418                 /* XXX There must be a nicer way to do this.  */
  419                 if (td->td_pcb->pcb_onfault == fswintrberr) {
  420                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  421                         td->td_pcb->pcb_onfault = NULL;
  422                         return (pc);
  423                 }
  424 
  425                 goto dofault;
  426 
  427         case T_TLB_LD_MISS + T_USER:
  428                 ftype = VM_PROT_READ;
  429                 goto dofault;
  430 
  431         case T_TLB_ST_MISS + T_USER:
  432                 ftype = VM_PROT_WRITE;
  433 dofault:
  434                 {
  435                         vm_offset_t va;
  436                         struct vmspace *vm;
  437                         vm_map_t map;
  438                         int rv = 0;
  439 
  440                         vm = p->p_vmspace;
  441                         map = &vm->vm_map;
  442                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  443                         if (KERNLAND(trapframe->badvaddr)) {
  444                                 /*
  445                                  * Don't allow user-mode faults in kernel
  446                                  * address space.
  447                                  */
  448                                 goto nogo;
  449                         }
  450 
  451                         /*
  452                          * Keep swapout from messing with us during this
  453                          * critical time.
  454                          */
  455                         PROC_LOCK(p);
  456                         ++p->p_lock;
  457                         PROC_UNLOCK(p);
  458 
  459                         rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
  460 
  461                         PROC_LOCK(p);
  462                         --p->p_lock;
  463                         PROC_UNLOCK(p);
  464 #ifdef VMFAULT_TRACE
  465                         printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
  466                             map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
  467                             ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
  468 #endif
  469 
  470                         if (rv == KERN_SUCCESS) {
  471                                 if (!usermode) {
  472                                         return (trapframe->pc);
  473                                 }
  474                                 goto out;
  475                         }
  476         nogo:
  477                         if (!usermode) {
  478                                 if (td->td_pcb->pcb_onfault != NULL) {
  479                                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  480                                         td->td_pcb->pcb_onfault = NULL;
  481                                         return (pc);
  482                                 }
  483                                 goto err;
  484                         }
  485                         ucode = ftype;
  486                         i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
  487                         addr = trapframe->pc;
  488 
  489                         msg = "BAD_PAGE_FAULT";
  490                         log_bad_page_fault(msg, trapframe, type);
  491 
  492                         break;
  493                 }
  494 
  495         case T_ADDR_ERR_LD + T_USER:    /* misaligned or kseg access */
  496         case T_ADDR_ERR_ST + T_USER:    /* misaligned or kseg access */
  497                 if (trapframe->badvaddr < 0 ||
  498                     trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
  499                         msg = "ADDRESS_SPACE_ERR";
  500                 } else if (allow_unaligned_acc) {
  501                         int mode;
  502 
  503                         if (type == (T_ADDR_ERR_LD + T_USER))
  504                                 mode = VM_PROT_READ;
  505                         else
  506                                 mode = VM_PROT_WRITE;
  507 
  508                         access_type = emulate_unaligned_access(trapframe, mode);
  509                         if (access_type != 0)
  510                                 goto out;
  511                         msg = "ALIGNMENT_FIX_ERR";
  512                 } else {
  513                         msg = "ADDRESS_ERR";
  514                 }
  515 
  516                 /* FALL THROUGH */
  517 
  518         case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
  519         case T_BUS_ERR_LD_ST + T_USER:  /* BERR asserted to cpu */
  520                 ucode = 0;      /* XXX should be VM_PROT_something */
  521                 i = SIGBUS;
  522                 addr = trapframe->pc;
  523                 if (!msg)
  524                         msg = "BUS_ERR";
  525                 log_bad_page_fault(msg, trapframe, type);
  526                 break;
  527 
  528         case T_SYSCALL + T_USER:
  529                 {
  530                         struct trapframe *locr0 = td->td_frame;
  531                         struct sysent *callp;
  532                         unsigned int code;
  533                         int nargs, nsaved;
  534                         register_t args[8];
  535 
  536                         bzero(args, sizeof args);
  537 
  538                         /*
  539                          * note: PCPU_LAZY_INC() can only be used if we can
  540                          * afford occassional inaccuracy in the count.
  541                          */
  542                         PCPU_LAZY_INC(cnt.v_syscall);
  543                         if (td->td_ucred != p->p_ucred)
  544                                 cred_update_thread(td);
  545 #ifdef KSE
  546                         if (p->p_flag & P_SA)
  547                                 thread_user_enter(td);
  548 #endif
  549                         /* compute next PC after syscall instruction */
  550                         td->td_pcb->pcb_tpc = trapframe->pc;    /* Remember if restart */
  551                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
  552                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
  553                                     0);
  554                         } else {
  555                                 locr0->pc += sizeof(int);
  556                         }
  557                         code = locr0->v0;
  558 
  559                         switch (code) {
  560 #if defined(__mips_n32) || defined(__mips_n64)
  561                         case SYS___syscall:
  562                                 /*
  563                                  * Quads fit in a single register in
  564                                  * new ABIs.
  565                                  *
  566                                  * XXX o64?
  567                                  */
  568 #endif
  569                         case SYS_syscall:
  570                                 /*
  571                                  * Code is first argument, followed by
  572                                  * actual args.
  573                                  */
  574                                 code = locr0->a0;
  575                                 args[0] = locr0->a1;
  576                                 args[1] = locr0->a2;
  577                                 args[2] = locr0->a3;
  578                                 nsaved = 3;
  579 #if defined(__mips_n32) || defined(__mips_n64)
  580                                 args[3] = locr0->t4;
  581                                 args[4] = locr0->t5;
  582                                 args[5] = locr0->t6;
  583                                 args[6] = locr0->t7;
  584                                 nsaved += 4;
  585 #endif
  586                                 break;
  587 
  588 #if defined(__mips_o32)
  589                         case SYS___syscall:
  590                                 /*
  591                                  * Like syscall, but code is a quad, so as
  592                                  * to maintain quad alignment for the rest
  593                                  * of the arguments.
  594                                  */
  595                                 if (_QUAD_LOWWORD == 0) {
  596                                         code = locr0->a0;
  597                                 } else {
  598                                         code = locr0->a1;
  599                                 }
  600                                 args[0] = locr0->a2;
  601                                 args[1] = locr0->a3;
  602                                 nsaved = 2;
  603                                 break;
  604 #endif
  605 
  606                         default:
  607                                 args[0] = locr0->a0;
  608                                 args[1] = locr0->a1;
  609                                 args[2] = locr0->a2;
  610                                 args[3] = locr0->a3;
  611                                 nsaved = 4;
  612 #if defined (__mips_n32) || defined(__mips_n64)
  613                                 args[4] = locr0->t4;
  614                                 args[5] = locr0->t5;
  615                                 args[6] = locr0->t6;
  616                                 args[7] = locr0->t7;
  617                                 nsaved += 4;
  618 #endif
  619                         }
  620 #ifdef TRAP_DEBUG
  621                         if (trap_debug) {
  622                                 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
  623                         }
  624 #endif
  625 
  626                         if (p->p_sysent->sv_mask)
  627                                 code &= p->p_sysent->sv_mask;
  628 
  629                         if (code >= p->p_sysent->sv_size)
  630                                 callp = &p->p_sysent->sv_table[0];
  631                         else
  632                                 callp = &p->p_sysent->sv_table[code];
  633 
  634                         nargs = callp->sy_narg;
  635 
  636                         if (nargs > nsaved) {
  637 #if defined(__mips_n32) || defined(__mips_n64)
  638                                 /*
  639                                  * XXX
  640                                  * Is this right for new ABIs?  I think the 4 there
  641                                  * should be 8, size there are 8 registers to skip,
  642                                  * not 4, but I'm not certain.
  643                                  */
  644                                 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
  645 #endif
  646                                 i = copyin((caddr_t)(intptr_t)(locr0->sp +
  647                                     4 * sizeof(register_t)), (caddr_t)&args[nsaved],
  648                                     (u_int)(nargs - nsaved) * sizeof(register_t));
  649                                 if (i) {
  650                                         locr0->v0 = i;
  651                                         locr0->a3 = 1;
  652 #ifdef KTRACE
  653                                         if (KTRPOINT(td, KTR_SYSCALL))
  654                                                 ktrsyscall(code, nargs, args);
  655 #endif
  656                                         goto done;
  657                                 }
  658                         }
  659 #ifdef TRAP_DEBUG
  660                         if (trap_debug) {
  661                                 for (i = 0; i < nargs; i++) {
  662                                         printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
  663                                 }
  664                         }
  665 #endif
  666 #ifdef SYSCALL_TRACING
  667                         printf("%s(", syscallnames[code]);
  668                         for (i = 0; i < nargs; i++) {
  669                                 printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
  670                         }
  671                         printf(")\n");
  672 #endif
  673 #ifdef KTRACE
  674                         if (KTRPOINT(td, KTR_SYSCALL))
  675                                 ktrsyscall(code, nargs, args);
  676 #endif
  677                         td->td_retval[0] = 0;
  678                         td->td_retval[1] = locr0->v1;
  679 
  680 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  681                         if (trp == trapdebug)
  682                                 trapdebug[TRAPSIZE - 1].code = code;
  683                         else
  684                                 trp[-1].code = code;
  685 #endif
  686                         STOPEVENT(p, S_SCE, nargs);
  687 
  688                         PTRACESTOP_SC(p, td, S_PT_SCE);
  689                         i = (*callp->sy_call) (td, args);
  690 #if 0
  691                         /*
  692                          * Reinitialize proc pointer `p' as it may be
  693                          * different if this is a child returning from fork
  694                          * syscall.
  695                          */
  696                         td = curthread;
  697                         locr0 = td->td_frame;
  698 #endif
  699                         trapdebug_enter(locr0, -code);
  700                         cpu_set_syscall_retval(td, i);
  701 
  702                         /*
  703                          * The sync'ing of I & D caches for SYS_ptrace() is
  704                          * done by procfs_domem() through procfs_rwmem()
  705                          * instead of being done here under a special check
  706                          * for SYS_ptrace().
  707                          */
  708         done:
  709                         /*
  710                          * Check for misbehavior.
  711                          */
  712                         WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
  713                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  714                             syscallnames[code] : "???");
  715                         KASSERT(td->td_critnest == 0,
  716                             ("System call %s returning in a critical section",
  717                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  718                             syscallnames[code] : "???"));
  719                         KASSERT(td->td_locks == 0,
  720                             ("System call %s returning with %d locks held",
  721                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  722                             syscallnames[code] : "???",
  723                             td->td_locks));
  724                         userret(td, trapframe);
  725 #ifdef KTRACE
  726                         if (KTRPOINT(td, KTR_SYSRET))
  727                                 ktrsysret(code, i, td->td_retval[0]);
  728 #endif
  729                         /*
  730                          * This works because errno is findable through the
  731                          * register set.  If we ever support an emulation
  732                          * where this is not the case, this code will need
  733                          * to be revisited.
  734                          */
  735                         STOPEVENT(p, S_SCX, code);
  736 
  737                         PTRACESTOP_SC(p, td, S_PT_SCX);
  738 
  739                         mtx_assert(&Giant, MA_NOTOWNED);
  740                         return (trapframe->pc);
  741                 }
  742 
  743 #ifdef DDB
  744         case T_BREAK:
  745                 kdb_trap(type, 0, trapframe);
  746                 return (trapframe->pc);
  747 #endif
  748 
  749         case T_BREAK + T_USER:
  750                 {
  751                         intptr_t va;
  752                         uint32_t instr;
  753 
  754                         /* compute address of break instruction */
  755                         va = trapframe->pc;
  756                         if (DELAYBRANCH(trapframe->cause))
  757                                 va += sizeof(int);
  758 
  759                         /* read break instruction */
  760                         instr = fuword32((caddr_t)va);
  761 #if 0
  762                         printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
  763                             p->p_comm, p->p_pid, instr, trapframe->pc,
  764                             p->p_md.md_ss_addr, p->p_md.md_ss_instr);   /* XXX */
  765 #endif
  766                         if (td->td_md.md_ss_addr != va ||
  767                             instr != MIPS_BREAK_SSTEP) {
  768                                 i = SIGTRAP;
  769                                 addr = trapframe->pc;
  770                                 break;
  771                         }
  772                         /*
  773                          * The restoration of the original instruction and
  774                          * the clearing of the berakpoint will be done later
  775                          * by the call to ptrace_clear_single_step() in
  776                          * issignal() when SIGTRAP is processed.
  777                          */
  778                         addr = trapframe->pc;
  779                         i = SIGTRAP;
  780                         break;
  781                 }
  782 
  783         case T_IWATCH + T_USER:
  784         case T_DWATCH + T_USER:
  785                 {
  786                         intptr_t va;
  787 
  788                         /* compute address of trapped instruction */
  789                         va = trapframe->pc;
  790                         if (DELAYBRANCH(trapframe->cause))
  791                                 va += sizeof(int);
  792                         printf("watch exception @ %p\n", (void *)va);
  793                         i = SIGTRAP;
  794                         addr = va;
  795                         break;
  796                 }
  797 
  798         case T_TRAP + T_USER:
  799                 {
  800                         intptr_t va;
  801                         uint32_t instr;
  802                         struct trapframe *locr0 = td->td_frame;
  803 
  804                         /* compute address of trap instruction */
  805                         va = trapframe->pc;
  806                         if (DELAYBRANCH(trapframe->cause))
  807                                 va += sizeof(int);
  808                         /* read break instruction */
  809                         instr = fuword32((caddr_t)va);
  810 
  811                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
  812                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
  813                                     0);
  814                         } else {
  815                                 locr0->pc += sizeof(int);
  816                         }
  817                         addr = va;
  818                         i = SIGEMT;     /* Stuff it with something for now */
  819                         break;
  820                 }
  821 
  822         case T_RES_INST + T_USER:
  823                 log_illegal_instruction("RES_INST", trapframe);
  824                 i = SIGILL;
  825                 addr = trapframe->pc;
  826                 break;
  827         case T_C2E:
  828         case T_C2E + T_USER:
  829                 goto err;
  830                 break;
  831         case T_COP_UNUSABLE:
  832                 goto err;
  833                 break;
  834         case T_COP_UNUSABLE + T_USER:
  835 #if !defined(CPU_HAVEFPU)
  836                 /* FP (COP1) instruction */
  837                 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) {
  838                         log_illegal_instruction("COP1_UNUSABLE", trapframe);
  839                         i = SIGILL;
  840                         break;
  841                 }
  842 #endif
  843                 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) {
  844                         log_illegal_instruction("COPn_UNUSABLE", trapframe);
  845                         i = SIGILL;     /* only FPU instructions allowed */
  846                         break;
  847                 }
  848                 addr = trapframe->pc;
  849                 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
  850                 PCPU_SET(fpcurthread, td);
  851                 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
  852                 td->td_md.md_flags |= MDTD_FPUSED;
  853                 goto out;
  854 
  855         case T_FPE:
  856 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  857                 trapDump("fpintr");
  858 #else
  859                 printf("FPU Trap: PC %#jx CR %x SR %x\n",
  860                     (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
  861                 goto err;
  862 #endif
  863 
  864         case T_FPE + T_USER:
  865                 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
  866                 goto out;
  867 
  868         case T_OVFLOW + T_USER:
  869                 i = SIGFPE;
  870                 addr = trapframe->pc;
  871                 break;
  872 
  873         case T_ADDR_ERR_LD:     /* misaligned access */
  874         case T_ADDR_ERR_ST:     /* misaligned access */
  875 #ifdef TRAP_DEBUG
  876                 if (trap_debug) {
  877                         printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
  878                             (intmax_t)trapframe->badvaddr);
  879                 }
  880 #endif
  881                 /* Only allow emulation on a user address */
  882                 if (allow_unaligned_acc &&
  883                     ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
  884                         int mode;
  885 
  886                         if (type == T_ADDR_ERR_LD)
  887                                 mode = VM_PROT_READ;
  888                         else
  889                                 mode = VM_PROT_WRITE;
  890 
  891                         access_type = emulate_unaligned_access(trapframe, mode);
  892                         if (access_type != 0)
  893                                 return (trapframe->pc);
  894                 }
  895                 /* FALLTHROUGH */
  896 
  897         case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
  898                 if (td->td_pcb->pcb_onfault != NULL) {
  899                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
  900                         td->td_pcb->pcb_onfault = NULL;
  901                         return (pc);
  902                 }
  903 
  904                 /* FALLTHROUGH */
  905 
  906         default:
  907 err:
  908 
  909 #if !defined(SMP) && defined(DEBUG)
  910                 stacktrace(!usermode ? trapframe : td->td_frame);
  911                 trapDump("trap");
  912 #endif
  913 #ifdef SMP
  914                 printf("cpu:%d-", PCPU_GET(cpuid));
  915 #endif
  916                 printf("Trap cause = %d (%s - ", type,
  917                     trap_type[type & (~T_USER)]);
  918 
  919                 if (type & T_USER)
  920                         printf("user mode)\n");
  921                 else
  922                         printf("kernel mode)\n");
  923 
  924 #ifdef TRAP_DEBUG
  925                 if (trap_debug)
  926                         printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
  927                                (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
  928                                (intmax_t)trapframe->sr);
  929 #endif
  930 
  931 #ifdef KDB
  932                 if (debugger_on_panic || kdb_active) {
  933                         kdb_trap(type, 0, trapframe);
  934                 }
  935 #endif
  936                 panic("trap");
  937         }
  938         td->td_frame->pc = trapframe->pc;
  939         td->td_frame->cause = trapframe->cause;
  940         td->td_frame->badvaddr = trapframe->badvaddr;
  941         ksiginfo_init_trap(&ksi);
  942         ksi.ksi_signo = i;
  943         ksi.ksi_code = ucode;
  944         ksi.ksi_addr = (void *)addr;
  945         ksi.ksi_trapno = type;
  946         trapsignal(td, &ksi);
  947 out:
  948 
  949         /*
  950          * Note: we should only get here if returning to user mode.
  951          */
  952         userret(td, trapframe);
  953         mtx_assert(&Giant, MA_NOTOWNED);
  954         return (trapframe->pc);
  955 }
  956 
  957 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  958 void
  959 trapDump(char *msg)
  960 {
  961         register_t s;
  962         int i;
  963 
  964         s = intr_disable();
  965         printf("trapDump(%s)\n", msg);
  966         for (i = 0; i < TRAPSIZE; i++) {
  967                 if (trp == trapdebug) {
  968                         trp = &trapdebug[TRAPSIZE - 1];
  969                 } else {
  970                         trp--;
  971                 }
  972 
  973                 if (trp->cause == 0)
  974                         break;
  975 
  976                 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
  977                     trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >> 
  978                         MIPS_CR_EXC_CODE_SHIFT],
  979                     (intmax_t)trp->vadr, (intmax_t)trp->pc,
  980                     (intmax_t)trp->cause, (intmax_t)trp->status);
  981 
  982                 printf("   RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
  983                     (intmax_t)trp->sp, (int)trp->code);
  984         }
  985         intr_restore(s);
  986 }
  987 #endif
  988 
  989 
  990 /*
  991  * Return the resulting PC as if the branch was executed.
  992  */
  993 uintptr_t
  994 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
  995     uintptr_t instptr)
  996 {
  997         InstFmt inst;
  998         register_t *regsPtr = (register_t *) framePtr;
  999         uintptr_t retAddr = 0;
 1000         int condition;
 1001 
 1002 #define GetBranchDest(InstPtr, inst) \
 1003         (InstPtr + 4 + ((short)inst.IType.imm << 2))
 1004 
 1005 
 1006         if (instptr) {
 1007                 if (instptr < MIPS_KSEG0_START)
 1008                         inst.word = fuword32((void *)instptr);
 1009                 else
 1010                         inst = *(InstFmt *) instptr;
 1011         } else {
 1012                 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
 1013                         inst.word = fuword32((void *)instPC);
 1014                 else
 1015                         inst = *(InstFmt *) instPC;
 1016         }
 1017 
 1018         switch ((int)inst.JType.op) {
 1019         case OP_SPECIAL:
 1020                 switch ((int)inst.RType.func) {
 1021                 case OP_JR:
 1022                 case OP_JALR:
 1023                         retAddr = regsPtr[inst.RType.rs];
 1024                         break;
 1025 
 1026                 default:
 1027                         retAddr = instPC + 4;
 1028                         break;
 1029                 }
 1030                 break;
 1031 
 1032         case OP_BCOND:
 1033                 switch ((int)inst.IType.rt) {
 1034                 case OP_BLTZ:
 1035                 case OP_BLTZL:
 1036                 case OP_BLTZAL:
 1037                 case OP_BLTZALL:
 1038                         if ((int)(regsPtr[inst.RType.rs]) < 0)
 1039                                 retAddr = GetBranchDest(instPC, inst);
 1040                         else
 1041                                 retAddr = instPC + 8;
 1042                         break;
 1043 
 1044                 case OP_BGEZ:
 1045                 case OP_BGEZL:
 1046                 case OP_BGEZAL:
 1047                 case OP_BGEZALL:
 1048                         if ((int)(regsPtr[inst.RType.rs]) >= 0)
 1049                                 retAddr = GetBranchDest(instPC, inst);
 1050                         else
 1051                                 retAddr = instPC + 8;
 1052                         break;
 1053 
 1054                 case OP_TGEI:
 1055                 case OP_TGEIU:
 1056                 case OP_TLTI:
 1057                 case OP_TLTIU:
 1058                 case OP_TEQI:
 1059                 case OP_TNEI:
 1060                         retAddr = instPC + 4;   /* Like syscall... */
 1061                         break;
 1062 
 1063                 default:
 1064                         panic("MipsEmulateBranch: Bad branch cond");
 1065                 }
 1066                 break;
 1067 
 1068         case OP_J:
 1069         case OP_JAL:
 1070                 retAddr = (inst.JType.target << 2) |
 1071                     ((unsigned)(instPC + 4) & 0xF0000000);
 1072                 break;
 1073 
 1074         case OP_BEQ:
 1075         case OP_BEQL:
 1076                 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
 1077                         retAddr = GetBranchDest(instPC, inst);
 1078                 else
 1079                         retAddr = instPC + 8;
 1080                 break;
 1081 
 1082         case OP_BNE:
 1083         case OP_BNEL:
 1084                 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
 1085                         retAddr = GetBranchDest(instPC, inst);
 1086                 else
 1087                         retAddr = instPC + 8;
 1088                 break;
 1089 
 1090         case OP_BLEZ:
 1091         case OP_BLEZL:
 1092                 if ((int)(regsPtr[inst.RType.rs]) <= 0)
 1093                         retAddr = GetBranchDest(instPC, inst);
 1094                 else
 1095                         retAddr = instPC + 8;
 1096                 break;
 1097 
 1098         case OP_BGTZ:
 1099         case OP_BGTZL:
 1100                 if ((int)(regsPtr[inst.RType.rs]) > 0)
 1101                         retAddr = GetBranchDest(instPC, inst);
 1102                 else
 1103                         retAddr = instPC + 8;
 1104                 break;
 1105 
 1106         case OP_COP1:
 1107                 switch (inst.RType.rs) {
 1108                 case OP_BCx:
 1109                 case OP_BCy:
 1110                         if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
 1111                                 condition = fpcCSR & MIPS_FPU_COND_BIT;
 1112                         else
 1113                                 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
 1114                         if (condition)
 1115                                 retAddr = GetBranchDest(instPC, inst);
 1116                         else
 1117                                 retAddr = instPC + 8;
 1118                         break;
 1119 
 1120                 default:
 1121                         retAddr = instPC + 4;
 1122                 }
 1123                 break;
 1124 
 1125         default:
 1126                 retAddr = instPC + 4;
 1127         }
 1128         return (retAddr);
 1129 }
 1130 
 1131 
 1132 #if defined(DDB) || defined(DEBUG)
 1133 /*
 1134  * Print a stack backtrace.
 1135  */
 1136 void
 1137 stacktrace(struct trapframe *regs)
 1138 {
 1139         stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
 1140 }
 1141 #endif
 1142 
 1143 static void
 1144 log_frame_dump(struct trapframe *frame)
 1145 {
 1146         log(LOG_ERR, "Trapframe Register Dump:\n");
 1147         log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
 1148             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
 1149 
 1150         log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
 1151             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
 1152 
 1153         log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1154             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1155 
 1156         log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
 1157             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
 1158 
 1159         log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
 1160             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
 1161 
 1162         log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
 1163             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
 1164 
 1165         log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
 1166             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
 1167 
 1168         log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
 1169             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
 1170 
 1171         log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
 1172             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
 1173 
 1174 #ifdef IC_REG
 1175         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
 1176             (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
 1177 #else
 1178         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
 1179             (intmax_t)frame->cause, (intmax_t)frame->pc);
 1180 #endif
 1181 }
 1182 
 1183 #ifdef TRAP_DEBUG
 1184 static void
 1185 trap_frame_dump(struct trapframe *frame)
 1186 {
 1187         printf("Trapframe Register Dump:\n");
 1188         printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
 1189             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
 1190 
 1191         printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
 1192             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
 1193 
 1194         printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
 1195             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
 1196 
 1197         printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
 1198             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
 1199 
 1200         printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
 1201             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
 1202 
 1203         printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
 1204             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
 1205 
 1206         printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
 1207             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
 1208 
 1209         printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
 1210             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
 1211 
 1212         printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
 1213             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
 1214 
 1215 #ifdef IC_REG
 1216         printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
 1217             (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
 1218 #else
 1219         printf("\tcause: %#jx\tpc: %#jx\n",
 1220             (intmax_t)frame->cause, (intmax_t)frame->pc);
 1221 #endif
 1222 }
 1223 
 1224 #endif
 1225 
 1226 
 1227 static void
 1228 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
 1229 {
 1230         pt_entry_t *ptep;
 1231         pd_entry_t *pdep;
 1232         struct proc *p = curproc;
 1233 
 1234         pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
 1235         if (*pdep)
 1236                 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
 1237         else
 1238                 ptep = (pt_entry_t *)0;
 1239 
 1240         *pdepp = pdep;
 1241         *ptepp = ptep;
 1242 }
 1243 
 1244 static void
 1245 log_illegal_instruction(const char *msg, struct trapframe *frame)
 1246 {
 1247         pt_entry_t *ptep;
 1248         pd_entry_t *pdep;
 1249         unsigned int *addr;
 1250         struct proc *p = curproc;
 1251         register_t pc;
 1252 
 1253 #ifdef SMP
 1254         printf("cpuid = %d\n", PCPU_GET(cpuid));
 1255 #endif
 1256         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1257         log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n",
 1258             msg, p->p_pid, p->p_comm,
 1259             p->p_ucred ? p->p_ucred->cr_uid : -1,
 1260             (intmax_t)pc,
 1261             (intmax_t)frame->ra);
 1262 
 1263         /* log registers in trap frame */
 1264         log_frame_dump(frame);
 1265 
 1266         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
 1267 
 1268         /*
 1269          * Dump a few words around faulting instruction, if the addres is
 1270          * valid.
 1271          */
 1272         if (!(pc & 3) &&
 1273             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
 1274                 /* dump page table entry for faulting instruction */
 1275                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
 1276                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1277 
 1278                 addr = (unsigned int *)(intptr_t)pc;
 1279                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
 1280                     addr);
 1281                 log(LOG_ERR, "%08x %08x %08x %08x\n",
 1282                     addr[0], addr[1], addr[2], addr[3]);
 1283         } else {
 1284                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
 1285                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1286         }
 1287 }
 1288 
 1289 static void
 1290 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
 1291 {
 1292         pt_entry_t *ptep;
 1293         pd_entry_t *pdep;
 1294         unsigned int *addr;
 1295         struct proc *p = curproc;
 1296         char *read_or_write;
 1297         register_t pc;
 1298 
 1299         trap_type &= ~T_USER;
 1300 
 1301 #ifdef SMP
 1302         printf("cpuid = %d\n", PCPU_GET(cpuid));
 1303 #endif
 1304         switch (trap_type) {
 1305         case T_TLB_ST_MISS:
 1306         case T_ADDR_ERR_ST:
 1307                 read_or_write = "write";
 1308                 break;
 1309         case T_TLB_LD_MISS:
 1310         case T_ADDR_ERR_LD:
 1311         case T_BUS_ERR_IFETCH:
 1312                 read_or_write = "read";
 1313                 break;
 1314         default:
 1315                 read_or_write = "";
 1316         }
 1317 
 1318         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1319         log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n",
 1320             msg, p->p_pid, p->p_comm,
 1321             p->p_ucred ? p->p_ucred->cr_uid : -1,
 1322             (intmax_t)pc,
 1323             read_or_write,
 1324             (intmax_t)frame->badvaddr);
 1325 
 1326         /* log registers in trap frame */
 1327         log_frame_dump(frame);
 1328 
 1329         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
 1330 
 1331         /*
 1332          * Dump a few words around faulting instruction, if the addres is
 1333          * valid.
 1334          */
 1335         if (!(pc & 3) && (pc != frame->badvaddr) &&
 1336             (trap_type != T_BUS_ERR_IFETCH) &&
 1337             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
 1338                 /* dump page table entry for faulting instruction */
 1339                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
 1340                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1341 
 1342                 addr = (unsigned int *)(intptr_t)pc;
 1343                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
 1344                     addr);
 1345                 log(LOG_ERR, "%08x %08x %08x %08x\n",
 1346                     addr[0], addr[1], addr[2], addr[3]);
 1347         } else {
 1348                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
 1349                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1350         }
 1351 
 1352         get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
 1353         log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
 1354             (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
 1355 }
 1356 
 1357 
 1358 /*
 1359  * Unaligned load/store emulation
 1360  */
 1361 static int
 1362 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
 1363 {
 1364         register_t *reg = (register_t *) frame;
 1365         u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
 1366         register_t value_msb, value;
 1367         unsigned size;
 1368 
 1369         /*
 1370          * ADDR_ERR faults have higher priority than TLB
 1371          * Miss faults.  Therefore, it is necessary to
 1372          * verify that the faulting address is a valid
 1373          * virtual address within the process' address space
 1374          * before trying to emulate the unaligned access.
 1375          */
 1376         switch (MIPS_INST_OPCODE(inst)) {
 1377         case OP_LHU: case OP_LH:
 1378         case OP_SH:
 1379                 size = 2;
 1380                 break;
 1381         case OP_LWU: case OP_LW:
 1382         case OP_SW:
 1383                 size = 4;
 1384                 break;
 1385         case OP_LD:
 1386         case OP_SD:
 1387                 size = 8;
 1388                 break;
 1389         default:
 1390                 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
 1391                 return (0);
 1392         }
 1393 
 1394         if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
 1395                 return (0);
 1396 
 1397         /*
 1398          * XXX
 1399          * Handle LL/SC LLD/SCD.
 1400          */
 1401         switch (MIPS_INST_OPCODE(inst)) {
 1402         case OP_LHU:
 1403                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1404                 lbu_macro(value_msb, addr);
 1405                 addr += 1;
 1406                 lbu_macro(value, addr);
 1407                 value |= value_msb << 8;
 1408                 reg[MIPS_INST_RT(inst)] = value;
 1409                 return (MIPS_LHU_ACCESS);
 1410 
 1411         case OP_LH:
 1412                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1413                 lb_macro(value_msb, addr);
 1414                 addr += 1;
 1415                 lbu_macro(value, addr);
 1416                 value |= value_msb << 8;
 1417                 reg[MIPS_INST_RT(inst)] = value;
 1418                 return (MIPS_LH_ACCESS);
 1419 
 1420         case OP_LWU:
 1421                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1422                 lwl_macro(value, addr);
 1423                 addr += 3;
 1424                 lwr_macro(value, addr);
 1425                 value &= 0xffffffff;
 1426                 reg[MIPS_INST_RT(inst)] = value;
 1427                 return (MIPS_LWU_ACCESS);
 1428 
 1429         case OP_LW:
 1430                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1431                 lwl_macro(value, addr);
 1432                 addr += 3;
 1433                 lwr_macro(value, addr);
 1434                 reg[MIPS_INST_RT(inst)] = value;
 1435                 return (MIPS_LW_ACCESS);
 1436 
 1437 #if defined(__mips_n32) || defined(__mips_n64)
 1438         case OP_LD:
 1439                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
 1440                 ldl_macro(value, addr);
 1441                 addr += 7;
 1442                 ldr_macro(value, addr);
 1443                 reg[MIPS_INST_RT(inst)] = value;
 1444                 return (MIPS_LD_ACCESS);
 1445 #endif
 1446 
 1447         case OP_SH:
 1448                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1449                 value = reg[MIPS_INST_RT(inst)];
 1450                 value_msb = value >> 8;
 1451                 sb_macro(value_msb, addr);
 1452                 addr += 1;
 1453                 sb_macro(value, addr);
 1454                 return (MIPS_SH_ACCESS);
 1455 
 1456         case OP_SW:
 1457                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1458                 value = reg[MIPS_INST_RT(inst)];
 1459                 swl_macro(value, addr);
 1460                 addr += 3;
 1461                 swr_macro(value, addr);
 1462                 return (MIPS_SW_ACCESS);
 1463 
 1464 #if defined(__mips_n32) || defined(__mips_n64)
 1465         case OP_SD:
 1466                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
 1467                 value = reg[MIPS_INST_RT(inst)];
 1468                 sdl_macro(value, addr);
 1469                 addr += 7;
 1470                 sdr_macro(value, addr);
 1471                 return (MIPS_SD_ACCESS);
 1472 #endif
 1473         }
 1474         panic("%s: should not be reached.", __func__);
 1475 }
 1476 
 1477 
 1478 static int
 1479 emulate_unaligned_access(struct trapframe *frame, int mode)
 1480 {
 1481         register_t pc;
 1482         int access_type = 0;
 1483 
 1484         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1485 
 1486         /*
 1487          * Fall through if it's instruction fetch exception
 1488          */
 1489         if (!((pc & 3) || (pc == frame->badvaddr))) {
 1490 
 1491                 /*
 1492                  * Handle unaligned load and store
 1493                  */
 1494 
 1495                 /*
 1496                  * Return access type if the instruction was emulated.
 1497                  * Otherwise restore pc and fall through.
 1498                  */
 1499                 access_type = mips_unaligned_load_store(frame,
 1500                     mode, frame->badvaddr, pc);
 1501 
 1502                 if (access_type) {
 1503                         if (DELAYBRANCH(frame->cause))
 1504                                 frame->pc = MipsEmulateBranch(frame, frame->pc,
 1505                                     0, 0);
 1506                         else
 1507                                 frame->pc += 4;
 1508 
 1509                         log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
 1510                             access_name[access_type - 1], (intmax_t)pc,
 1511                             (intmax_t)frame->badvaddr);
 1512                 }
 1513         }
 1514         return access_type;
 1515 }

Cache object: 8154afdb0642d28e61541c50e4347250


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