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

Cache object: 0a2d0e45464893fda5429062f310cfc3


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