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/8.0/sys/mips/mips/trap.c 183428 2008-09-28 03:50:34Z imp $");
   43 
   44 #include "opt_ddb.h"
   45 #include "opt_global.h"
   46 
   47 #define NO_REG_DEFS     1       /* Prevent asm.h from including regdef.h */
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/sysent.h>
   51 #include <sys/proc.h>
   52 #include <sys/kernel.h>
   53 #include <sys/signalvar.h>
   54 #include <sys/syscall.h>
   55 #include <sys/lock.h>
   56 #include <vm/vm.h>
   57 #include <vm/vm_extern.h>
   58 #include <vm/vm_kern.h>
   59 #include <vm/vm_page.h>
   60 #include <vm/vm_map.h>
   61 #include <vm/vm_param.h>
   62 #include <sys/vmmeter.h>
   63 #include <sys/ptrace.h>
   64 #include <sys/user.h>
   65 #include <sys/buf.h>
   66 #include <sys/vnode.h>
   67 #include <sys/pioctl.h>
   68 #include <sys/sysctl.h>
   69 #include <sys/syslog.h>
   70 #include <sys/bus.h>
   71 #ifdef KTRACE
   72 #include <sys/ktrace.h>
   73 #endif
   74 #include <net/netisr.h>
   75 
   76 #include <machine/trap.h>
   77 #include <machine/psl.h>
   78 #include <machine/cpu.h>
   79 #include <machine/intr.h>
   80 #include <machine/pte.h>
   81 #include <machine/pmap.h>
   82 #include <machine/mips_opcode.h>
   83 #include <machine/frame.h>
   84 #include <machine/regnum.h>
   85 #include <machine/rm7000.h>
   86 #include <machine/archtype.h>
   87 #include <machine/asm.h>
   88 
   89 #ifdef DDB
   90 #include <machine/db_machdep.h>
   91 #include <ddb/db_sym.h>
   92 #include <ddb/ddb.h>
   93 #include <sys/kdb.h>
   94 #endif
   95 
   96 #include <sys/cdefs.h>
   97 #include <sys/syslog.h>
   98 
   99 
  100 #ifdef TRAP_DEBUG
  101 int trap_debug = 1;
  102 
  103 #endif
  104 
  105 extern unsigned onfault_table[];
  106 
  107 extern void MipsKernGenException(void);
  108 extern void MipsUserGenException(void);
  109 extern void MipsKernIntr(void);
  110 extern void MipsUserIntr(void);
  111 extern void MipsTLBInvalidException(void);
  112 extern void MipsKernTLBInvalidException(void);
  113 extern void MipsUserTLBInvalidException(void);
  114 extern void MipsTLBMissException(void);
  115 static void log_bad_page_fault(char *, struct trapframe *, int);
  116 static void log_frame_dump(struct trapframe *frame);
  117 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
  118 
  119 #ifdef TRAP_DEBUG
  120 static void trap_frame_dump(struct trapframe *frame);
  121 
  122 #endif
  123 extern char edata[];
  124 
  125 void (*machExceptionTable[]) (void)= {
  126 /*
  127  * The kernel exception handlers.
  128  */
  129         MipsKernIntr,           /* external interrupt */
  130         MipsKernGenException,   /* TLB modification */
  131         MipsKernTLBInvalidException,    /* TLB miss (load or instr. fetch) */
  132         MipsKernTLBInvalidException,    /* TLB miss (store) */
  133         MipsKernGenException,   /* address error (load or I-fetch) */
  134         MipsKernGenException,   /* address error (store) */
  135         MipsKernGenException,   /* bus error (I-fetch) */
  136         MipsKernGenException,   /* bus error (load or store) */
  137         MipsKernGenException,   /* system call */
  138         MipsKernGenException,   /* breakpoint */
  139         MipsKernGenException,   /* reserved instruction */
  140         MipsKernGenException,   /* coprocessor unusable */
  141         MipsKernGenException,   /* arithmetic overflow */
  142         MipsKernGenException,   /* trap exception */
  143         MipsKernGenException,   /* virtual coherence exception inst */
  144         MipsKernGenException,   /* floating point exception */
  145         MipsKernGenException,   /* reserved */
  146         MipsKernGenException,   /* reserved */
  147         MipsKernGenException,   /* reserved */
  148         MipsKernGenException,   /* reserved */
  149         MipsKernGenException,   /* reserved */
  150         MipsKernGenException,   /* reserved */
  151         MipsKernGenException,   /* reserved */
  152         MipsKernGenException,   /* watch exception */
  153         MipsKernGenException,   /* reserved */
  154         MipsKernGenException,   /* reserved */
  155         MipsKernGenException,   /* reserved */
  156         MipsKernGenException,   /* reserved */
  157         MipsKernGenException,   /* reserved */
  158         MipsKernGenException,   /* reserved */
  159         MipsKernGenException,   /* reserved */
  160         MipsKernGenException,   /* virtual coherence exception data */
  161 /*
  162  * The user exception handlers.
  163  */
  164         MipsUserIntr,           /* 0 */
  165         MipsUserGenException,   /* 1 */
  166         MipsUserTLBInvalidException,    /* 2 */
  167         MipsUserTLBInvalidException,    /* 3 */
  168         MipsUserGenException,   /* 4 */
  169         MipsUserGenException,   /* 5 */
  170         MipsUserGenException,   /* 6 */
  171         MipsUserGenException,   /* 7 */
  172         MipsUserGenException,   /* 8 */
  173         MipsUserGenException,   /* 9 */
  174         MipsUserGenException,   /* 10 */
  175         MipsUserGenException,   /* 11 */
  176         MipsUserGenException,   /* 12 */
  177         MipsUserGenException,   /* 13 */
  178         MipsUserGenException,   /* 14 */
  179         MipsUserGenException,   /* 15 */
  180         MipsUserGenException,   /* 16 */
  181         MipsUserGenException,   /* 17 */
  182         MipsUserGenException,   /* 18 */
  183         MipsUserGenException,   /* 19 */
  184         MipsUserGenException,   /* 20 */
  185         MipsUserGenException,   /* 21 */
  186         MipsUserGenException,   /* 22 */
  187         MipsUserGenException,   /* 23 */
  188         MipsUserGenException,   /* 24 */
  189         MipsUserGenException,   /* 25 */
  190         MipsUserGenException,   /* 26 */
  191         MipsUserGenException,   /* 27 */
  192         MipsUserGenException,   /* 28 */
  193         MipsUserGenException,   /* 29 */
  194         MipsUserGenException,   /* 20 */
  195         MipsUserGenException,   /* 31 */
  196 };
  197 
  198 char *trap_type[] = {
  199         "external interrupt",
  200         "TLB modification",
  201         "TLB miss (load or instr. fetch)",
  202         "TLB miss (store)",
  203         "address error (load or I-fetch)",
  204         "address error (store)",
  205         "bus error (I-fetch)",
  206         "bus error (load or store)",
  207         "system call",
  208         "breakpoint",
  209         "reserved instruction",
  210         "coprocessor unusable",
  211         "arithmetic overflow",
  212         "trap",
  213         "virtual coherency instruction",
  214         "floating point",
  215         "reserved 16",
  216         "reserved 17",
  217         "reserved 18",
  218         "reserved 19",
  219         "reserved 20",
  220         "reserved 21",
  221         "reserved 22",
  222         "watch",
  223         "reserved 24",
  224         "reserved 25",
  225         "reserved 26",
  226         "reserved 27",
  227         "reserved 28",
  228         "reserved 29",
  229         "reserved 30",
  230         "virtual coherency data",
  231 };
  232 
  233 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  234 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
  235 
  236 #endif
  237 
  238 #if defined(DDB) || defined(DEBUG)
  239 void stacktrace(struct trapframe *);
  240 void logstacktrace(struct trapframe *);
  241 int kdbpeek(int *);
  242 
  243 /* extern functions printed by name in stack backtraces */
  244 extern void MipsTLBMiss(void);
  245 extern void MipsUserSyscallException(void);
  246 extern char _locore[];
  247 extern char _locoreEnd[];
  248 
  249 #endif                          /* DDB || DEBUG */
  250 
  251 extern void MipsSwitchFPState(struct thread *, struct trapframe *);
  252 extern void MipsFPTrap(u_int, u_int, u_int);
  253 
  254 u_int trap(struct trapframe *);
  255 u_int MipsEmulateBranch(struct trapframe *, int, int, u_int);
  256 
  257 #define KERNLAND(x) ((int)(x) < 0)
  258 #define DELAYBRANCH(x) ((int)(x) < 0)
  259 
  260 /*
  261  * kdbpeekD(addr) - skip one word starting at 'addr', then read the second word
  262  */
  263 #define kdbpeekD(addr)  kdbpeek(((int *)(addr)) + 1)
  264 int rrs_debug = 0;
  265 
  266 /*
  267  * MIPS load/store access type
  268  */
  269 enum {
  270         MIPS_LHU_ACCESS = 1,
  271         MIPS_LH_ACCESS,
  272         MIPS_LWU_ACCESS,
  273         MIPS_LW_ACCESS,
  274         MIPS_LD_ACCESS,
  275         MIPS_SH_ACCESS,
  276         MIPS_SW_ACCESS,
  277         MIPS_SD_ACCESS
  278 };
  279 
  280 char *access_name[] = {
  281         "Load Halfword Unsigned",
  282         "Load Halfword",
  283         "Load Word Unsigned",
  284         "Load Word",
  285         "Load Doubleword",
  286         "Store Halfword",
  287         "Store Word",
  288         "Store Doubleword"
  289 };
  290 
  291 
  292 static int allow_unaligned_acc = 1;
  293 
  294 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
  295     &allow_unaligned_acc, 0, "Allow unaligned accesses");
  296 
  297 static int emulate_unaligned_access(struct trapframe *frame);
  298 
  299 extern char *syscallnames[];
  300 
  301 /*
  302  * Handle an exception.
  303  * Called from MipsKernGenException() or MipsUserGenException()
  304  * when a processor trap occurs.
  305  * In the case of a kernel trap, we return the pc where to resume if
  306  * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
  307  */
  308 u_int
  309 trap(trapframe)
  310         struct trapframe *trapframe;
  311 {
  312         int type, usermode;
  313         int i = 0;
  314         unsigned ucode = 0;
  315         struct thread *td = curthread;
  316         struct proc *p = curproc;
  317         vm_prot_t ftype;
  318         pt_entry_t *pte;
  319         unsigned int entry;
  320         pmap_t pmap;
  321         int quad_syscall = 0;
  322         int access_type;
  323         ksiginfo_t ksi;
  324         char *msg = NULL;
  325         register_t addr = 0;
  326 
  327         trapdebug_enter(trapframe, 0);
  328         
  329         type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
  330         if (USERMODE(trapframe->sr)) {
  331                 type |= T_USER;
  332                 usermode = 1;
  333         } else {
  334                 usermode = 0;
  335         }
  336 
  337         /*
  338          * Enable hardware interrupts if they were on before the trap. If it
  339          * was off disable all so we don't accidently enable it when doing a
  340          * return to userland.
  341          */
  342         if (trapframe->sr & SR_INT_ENAB) {
  343                 set_intr_mask(~(trapframe->sr & ALL_INT_MASK));
  344                 enableintr();
  345         } else {
  346                 disableintr();
  347         }
  348 
  349 #ifdef TRAP_DEBUG
  350         if (trap_debug) {
  351                 static vm_offset_t last_badvaddr = 0;
  352                 static vm_offset_t this_badvaddr = 0;
  353                 static int count = 0;
  354                 u_int32_t pid;
  355 
  356                 printf("trap type %x (%s - ", type,
  357                     trap_type[type & (~T_USER)]);
  358 
  359                 if (type & T_USER)
  360                         printf("user mode)\n");
  361                 else
  362                         printf("kernel mode)\n");
  363 
  364 #ifdef SMP
  365                 printf("cpuid = %d\n", PCPU_GET(cpuid));
  366 #endif
  367                 MachTLBGetPID(pid);
  368                 printf("badaddr = %p, pc = %p, ra = %p, sp = %p, sr = 0x%x, pid = %d, ASID = 0x%x\n",
  369                     trapframe->badvaddr, trapframe->pc, trapframe->ra,
  370                     trapframe->sp, trapframe->sr,
  371                     (curproc ? curproc->p_pid : -1), pid);
  372 
  373                 switch (type & ~T_USER) {
  374                 case T_TLB_MOD:
  375                 case T_TLB_LD_MISS:
  376                 case T_TLB_ST_MISS:
  377                 case T_ADDR_ERR_LD:
  378                 case T_ADDR_ERR_ST:
  379                         this_badvaddr = trapframe->badvaddr;
  380                         break;
  381                 case T_SYSCALL:
  382                         this_badvaddr = trapframe->ra;
  383                         break;
  384                 default:
  385                         this_badvaddr = trapframe->pc;
  386                         break;
  387                 }
  388                 if ((last_badvaddr == this_badvaddr) &&
  389                     ((type & ~T_USER) != T_SYSCALL)) {
  390                         if (++count == 3) {
  391                                 trap_frame_dump(trapframe);
  392                                 panic("too many faults at %p\n", last_badvaddr);
  393                         }
  394                 } else {
  395                         last_badvaddr = this_badvaddr;
  396                         count = 0;
  397                 }
  398         }
  399 #endif
  400         switch (type) {
  401         case T_MCHECK:
  402 #ifdef DDB
  403                 kdb_trap(type, 0, trapframe);
  404 #endif
  405                 panic("MCHECK\n");
  406                 break;
  407         case T_TLB_MOD:
  408                 /* check for kernel address */
  409                 if (KERNLAND(trapframe->badvaddr)) {
  410                         vm_offset_t pa;
  411 
  412                         PMAP_LOCK(kernel_pmap);
  413                         if (!(pte = pmap_segmap(kernel_pmap,
  414                             trapframe->badvaddr)))
  415                                 panic("trap: ktlbmod: invalid segmap");
  416                         pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
  417                         entry = *pte;
  418 #ifdef SMP
  419                         /* It is possible that some other CPU changed m-bit */
  420                         if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
  421                                 trapframe->badvaddr &= ~PGOFSET;
  422                                 pmap_update_page(kernel_pmap,
  423                                     trapframe->badvaddr, entry);
  424                                 PMAP_UNLOCK(kernel_pmap);
  425                                 return (trapframe->pc);
  426                         }
  427 #else
  428                         if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
  429                                 panic("trap: ktlbmod: invalid pte");
  430 #endif
  431                         if (entry & mips_pg_ro_bit()) {
  432                                 /* write to read only page in the kernel */
  433                                 ftype = VM_PROT_WRITE;
  434                                 PMAP_UNLOCK(kernel_pmap);
  435                                 goto kernel_fault;
  436                         }
  437                         entry |= mips_pg_m_bit();
  438                         *pte = entry;
  439                         trapframe->badvaddr &= ~PGOFSET;
  440                         pmap_update_page(kernel_pmap, trapframe->badvaddr, entry);
  441                         pa = mips_tlbpfn_to_paddr(entry);
  442                         if (!page_is_managed(pa))
  443                                 panic("trap: ktlbmod: unmanaged page");
  444                         pmap_set_modified(pa);
  445                         PMAP_UNLOCK(kernel_pmap);
  446                         return (trapframe->pc);
  447                 }
  448                 /* FALLTHROUGH */
  449 
  450         case T_TLB_MOD + T_USER:
  451                 {
  452                         vm_offset_t pa;
  453 
  454                         pmap = &p->p_vmspace->vm_pmap;
  455 
  456                         PMAP_LOCK(pmap);
  457                         if (!(pte = pmap_segmap(pmap, trapframe->badvaddr)))
  458                                 panic("trap: utlbmod: invalid segmap");
  459                         pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
  460                         entry = *pte;
  461 #ifdef SMP
  462                         /* It is possible that some other CPU changed m-bit */
  463                         if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
  464                                 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
  465                                 pmap_update_page(pmap, trapframe->badvaddr, entry);
  466                                 PMAP_UNLOCK(pmap);
  467                                 goto out;
  468                         }
  469 #else
  470                         if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
  471                                 panic("trap: utlbmod: invalid pte");
  472                         }
  473 #endif
  474 
  475                         if (entry & mips_pg_ro_bit()) {
  476                                 /* write to read only page */
  477                                 ftype = VM_PROT_WRITE;
  478                                 PMAP_UNLOCK(pmap);
  479                                 goto dofault;
  480                         }
  481                         entry |= mips_pg_m_bit();
  482                         *pte = entry;
  483                         trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
  484                         pmap_update_page(pmap, trapframe->badvaddr, entry);
  485                         trapframe->badvaddr |= (pmap->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT);
  486                         pa = mips_tlbpfn_to_paddr(entry);
  487                         if (!page_is_managed(pa))
  488                                 panic("trap: utlbmod: unmanaged page");
  489                         pmap_set_modified(pa);
  490 
  491                         PMAP_UNLOCK(pmap);
  492                         if (!usermode) {
  493                                 return (trapframe->pc);
  494                         }
  495                         goto out;
  496                 }
  497 
  498         case T_TLB_LD_MISS:
  499         case T_TLB_ST_MISS:
  500                 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
  501                 /* check for kernel address */
  502                 if (KERNLAND(trapframe->badvaddr)) {
  503                         vm_offset_t va;
  504                         int rv;
  505 
  506         kernel_fault:
  507                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  508                         rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
  509                         if (rv == KERN_SUCCESS)
  510                                 return (trapframe->pc);
  511                         if ((i = td->td_pcb->pcb_onfault) != 0) {
  512                                 td->td_pcb->pcb_onfault = 0;
  513                                 return (onfault_table[i]);
  514                         }
  515                         goto err;
  516                 }
  517                 /*
  518                  * It is an error for the kernel to access user space except
  519                  * through the copyin/copyout routines.
  520                  */
  521                 if ((i = td->td_pcb->pcb_onfault) == 0)
  522                         goto err;
  523                 /* check for fuswintr() or suswintr() getting a page fault */
  524                 if (i == 4) {
  525                         return (onfault_table[i]);
  526                 }
  527                 goto dofault;
  528 
  529         case T_TLB_LD_MISS + T_USER:
  530                 ftype = VM_PROT_READ;
  531                 goto dofault;
  532 
  533         case T_TLB_ST_MISS + T_USER:
  534                 ftype = VM_PROT_WRITE;
  535 dofault:
  536                 {
  537                         vm_offset_t va;
  538                         struct vmspace *vm;
  539                         vm_map_t map;
  540                         int rv = 0;
  541                         int flag;
  542 
  543                         vm = p->p_vmspace;
  544                         map = &vm->vm_map;
  545                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
  546                         if ((vm_offset_t)trapframe->badvaddr < VM_MIN_KERNEL_ADDRESS) {
  547                                 if (ftype & VM_PROT_WRITE)
  548                                         flag = VM_FAULT_DIRTY;
  549                                 else
  550                                         flag = VM_FAULT_NORMAL;
  551                         } else {
  552                                 /*
  553                                  * Don't allow user-mode faults in kernel
  554                                  * address space.
  555                                  */
  556                                 goto nogo;
  557                         }
  558 
  559                         /*
  560                          * Keep swapout from messing with us during this
  561                          * critical time.
  562                          */
  563                         PROC_LOCK(p);
  564                         ++p->p_lock;
  565                         PROC_UNLOCK(p);
  566 
  567                         rv = vm_fault(map, va, ftype, flag);
  568 
  569                         PROC_LOCK(p);
  570                         --p->p_lock;
  571                         PROC_UNLOCK(p);
  572 #ifdef VMFAULT_TRACE
  573                         printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
  574                             map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, flag,
  575                             rv, trapframe->pc);
  576 #endif
  577 
  578                         if (rv == KERN_SUCCESS) {
  579                                 if (!usermode) {
  580                                         return (trapframe->pc);
  581                                 }
  582                                 goto out;
  583                         }
  584         nogo:
  585                         if (!usermode) {
  586                                 if ((i = td->td_pcb->pcb_onfault) != 0) {
  587                                         td->td_pcb->pcb_onfault = 0;
  588                                         return (onfault_table[i]);
  589                                 }
  590                                 goto err;
  591                         }
  592                         ucode = ftype;
  593                         i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
  594                         addr = trapframe->pc;
  595 
  596                         msg = "BAD_PAGE_FAULT";
  597                         log_bad_page_fault(msg, trapframe, type);
  598 
  599                         break;
  600                 }
  601 
  602         case T_ADDR_ERR_LD + T_USER:    /* misaligned or kseg access */
  603         case T_ADDR_ERR_ST + T_USER:    /* misaligned or kseg access */
  604                 if (allow_unaligned_acc) {
  605                         int mode;
  606 
  607                         if (type == (T_ADDR_ERR_LD + T_USER))
  608                                 mode = VM_PROT_READ;
  609                         else
  610                                 mode = VM_PROT_WRITE;
  611 
  612                         /*
  613                          * ADDR_ERR faults have higher priority than TLB
  614                          * Miss faults.  Therefore, it is necessary to
  615                          * verify that the faulting address is a valid
  616                          * virtual address within the process' address space
  617                          * before trying to emulate the unaligned access.
  618                          */
  619                         if (useracc((caddr_t)
  620                             (((vm_offset_t)trapframe->badvaddr) &
  621                             ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
  622                                 access_type = emulate_unaligned_access(
  623                                     trapframe);
  624                                 if (access_type != 0)
  625                                         goto out;
  626                         }
  627                 }
  628                 msg = "ADDRESS_ERR";
  629 
  630                 /* FALL THROUGH */
  631 
  632         case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
  633         case T_BUS_ERR_LD_ST + T_USER:  /* BERR asserted to cpu */
  634                 ucode = 0;      /* XXX should be VM_PROT_something */
  635                 i = SIGBUS;
  636                 addr = trapframe->pc;
  637                 if (!msg)
  638                         msg = "BUS_ERR";
  639                 log_bad_page_fault(msg, trapframe, type);
  640                 break;
  641 
  642         case T_SYSCALL + T_USER:
  643                 {
  644                         struct trapframe *locr0 = td->td_frame;
  645                         struct sysent *callp;
  646                         unsigned int code;
  647                         unsigned int tpc;
  648                         int nargs, nsaved;
  649                         register_t args[8];
  650 
  651                         /*
  652                          * note: PCPU_LAZY_INC() can only be used if we can
  653                          * afford occassional inaccuracy in the count.
  654                          */
  655                         PCPU_LAZY_INC(cnt.v_syscall);
  656                         if (td->td_ucred != p->p_ucred)
  657                                 cred_update_thread(td);
  658 #ifdef KSE
  659                         if (p->p_flag & P_SA)
  660                                 thread_user_enter(td);
  661 #endif
  662                         /* compute next PC after syscall instruction */
  663                         tpc = trapframe->pc;    /* Remember if restart */
  664                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
  665                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
  666                                     0);
  667                         } else {
  668                                 locr0->pc += sizeof(int);
  669                         }
  670                         code = locr0->v0;
  671 
  672                         switch (code) {
  673                         case SYS_syscall:
  674                                 /*
  675                                  * Code is first argument, followed by
  676                                  * actual args.
  677                                  */
  678                                 code = locr0->a0;
  679                                 args[0] = locr0->a1;
  680                                 args[1] = locr0->a2;
  681                                 args[2] = locr0->a3;
  682                                 nsaved = 3;
  683                                 break;
  684 
  685                         case SYS___syscall:
  686                                 /*
  687                                  * Like syscall, but code is a quad, so as
  688                                  * to maintain quad alignment for the rest
  689                                  * of the arguments.
  690                                  */
  691                                 if (_QUAD_LOWWORD == 0) {
  692                                         code = locr0->a0;
  693                                 } else {
  694                                         code = locr0->a1;
  695                                 }
  696                                 args[0] = locr0->a2;
  697                                 args[1] = locr0->a3;
  698                                 nsaved = 2;
  699                                 quad_syscall = 1;
  700                                 break;
  701 
  702                         default:
  703                                 args[0] = locr0->a0;
  704                                 args[1] = locr0->a1;
  705                                 args[2] = locr0->a2;
  706                                 args[3] = locr0->a3;
  707                                 nsaved = 4;
  708                         }
  709 #ifdef TRAP_DEBUG
  710                         printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
  711 #endif
  712 
  713                         if (p->p_sysent->sv_mask)
  714                                 code &= p->p_sysent->sv_mask;
  715 
  716                         if (code >= p->p_sysent->sv_size)
  717                                 callp = &p->p_sysent->sv_table[0];
  718                         else
  719                                 callp = &p->p_sysent->sv_table[code];
  720 
  721                         nargs = callp->sy_narg;
  722 
  723                         if (nargs > nsaved) {
  724                                 i = copyin((caddr_t)(locr0->sp +
  725                                     4 * sizeof(register_t)), (caddr_t)&args[nsaved],
  726                                     (u_int)(nargs - nsaved) * sizeof(register_t));
  727                                 if (i) {
  728                                         locr0->v0 = i;
  729                                         locr0->a3 = 1;
  730 #ifdef KTRACE
  731                                         if (KTRPOINT(td, KTR_SYSCALL))
  732                                                 ktrsyscall(code, nargs, args);
  733 #endif
  734                                         goto done;
  735                                 }
  736                         }
  737 #ifdef KTRACE
  738                         if (KTRPOINT(td, KTR_SYSCALL))
  739                                 ktrsyscall(code, nargs, args);
  740 #endif
  741                         td->td_retval[0] = 0;
  742                         td->td_retval[1] = locr0->v1;
  743 
  744 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  745                         if (trp == trapdebug)
  746                                 trapdebug[TRAPSIZE - 1].code = code;
  747                         else
  748                                 trp[-1].code = code;
  749 #endif
  750                         STOPEVENT(p, S_SCE, nargs);
  751 
  752                         PTRACESTOP_SC(p, td, S_PT_SCE);
  753                         i = (*callp->sy_call) (td, args);
  754 #if 0
  755                         /*
  756                          * Reinitialize proc pointer `p' as it may be
  757                          * different if this is a child returning from fork
  758                          * syscall.
  759                          */
  760                         td = curthread;
  761                         locr0 = td->td_frame;
  762 #endif
  763                         trapdebug_enter(locr0, -code);
  764                         switch (i) {
  765                         case 0:
  766                                 if (quad_syscall && code != SYS_lseek) {
  767                                         /*
  768                                          * System call invoked through the
  769                                          * SYS___syscall interface but the
  770                                          * return value is really just 32
  771                                          * bits.
  772                                          */
  773                                         locr0->v0 = td->td_retval[0];
  774                                         if (_QUAD_LOWWORD)
  775                                                 locr0->v1 = td->td_retval[0];
  776                                         locr0->a3 = 0;
  777                                 } else {
  778                                         locr0->v0 = td->td_retval[0];
  779                                         locr0->v1 = td->td_retval[1];
  780                                         locr0->a3 = 0;
  781                                 }
  782                                 break;
  783 
  784                         case ERESTART:
  785                                 locr0->pc = tpc;
  786                                 break;
  787 
  788                         case EJUSTRETURN:
  789                                 break;  /* nothing to do */
  790 
  791                         default:
  792                                 if (quad_syscall && code != SYS_lseek) {
  793                                         locr0->v0 = i;
  794                                         if (_QUAD_LOWWORD)
  795                                                 locr0->v1 = i;
  796                                         locr0->a3 = 1;
  797                                 } else {
  798                                         locr0->v0 = i;
  799                                         locr0->a3 = 1;
  800                                 }
  801                         }
  802 
  803                         /*
  804                          * The sync'ing of I & D caches for SYS_ptrace() is
  805                          * done by procfs_domem() through procfs_rwmem()
  806                          * instead of being done here under a special check
  807                          * for SYS_ptrace().
  808                          */
  809         done:
  810                         /*
  811                          * Check for misbehavior.
  812                          */
  813                         WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
  814                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  815                             syscallnames[code] : "???");
  816                         KASSERT(td->td_critnest == 0,
  817                             ("System call %s returning in a critical section",
  818                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  819                             syscallnames[code] : "???"));
  820                         KASSERT(td->td_locks == 0,
  821                             ("System call %s returning with %d locks held",
  822                             (code >= 0 && code < SYS_MAXSYSCALL) ?
  823                             syscallnames[code] : "???",
  824                             td->td_locks));
  825                         userret(td, trapframe);
  826 #ifdef KTRACE
  827                         if (KTRPOINT(p, KTR_SYSRET))
  828                                 ktrsysret(code, i, td->td_retval[0]);
  829 #endif
  830                         /*
  831                          * This works because errno is findable through the
  832                          * register set.  If we ever support an emulation
  833                          * where this is not the case, this code will need
  834                          * to be revisited.
  835                          */
  836                         STOPEVENT(p, S_SCX, code);
  837 
  838                         PTRACESTOP_SC(p, td, S_PT_SCX);
  839 
  840                         mtx_assert(&Giant, MA_NOTOWNED);
  841                         return (trapframe->pc);
  842                 }
  843 
  844 #ifdef DDB
  845         case T_BREAK:
  846                 kdb_trap(type, 0, trapframe);
  847                 return (trapframe->pc);
  848 #endif
  849 
  850         case T_BREAK + T_USER:
  851                 {
  852                         unsigned int va, instr;
  853 
  854                         /* compute address of break instruction */
  855                         va = trapframe->pc;
  856                         if (DELAYBRANCH(trapframe->cause))
  857                                 va += sizeof(int);
  858 
  859                         /* read break instruction */
  860                         instr = fuword((caddr_t)va);
  861 #if 0
  862                         printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
  863                             p->p_comm, p->p_pid, instr, trapframe->pc,
  864                             p->p_md.md_ss_addr, p->p_md.md_ss_instr);   /* XXX */
  865 #endif
  866                         if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
  867                                 i = SIGTRAP;
  868                                 addr = trapframe->pc;
  869                                 break;
  870                         }
  871                         /*
  872                          * The restoration of the original instruction and
  873                          * the clearing of the berakpoint will be done later
  874                          * by the call to ptrace_clear_single_step() in
  875                          * issignal() when SIGTRAP is processed.
  876                          */
  877                         addr = trapframe->pc;
  878                         i = SIGTRAP;
  879                         break;
  880                 }
  881 
  882         case T_IWATCH + T_USER:
  883         case T_DWATCH + T_USER:
  884                 {
  885                         unsigned int va;
  886 
  887                         /* compute address of trapped instruction */
  888                         va = trapframe->pc;
  889                         if (DELAYBRANCH(trapframe->cause))
  890                                 va += sizeof(int);
  891                         printf("watch exception @ 0x%x\n", va);
  892                         i = SIGTRAP;
  893                         addr = va;
  894                         break;
  895                 }
  896 
  897         case T_TRAP + T_USER:
  898                 {
  899                         unsigned int va, instr;
  900                         struct trapframe *locr0 = td->td_frame;
  901 
  902                         /* compute address of trap instruction */
  903                         va = trapframe->pc;
  904                         if (DELAYBRANCH(trapframe->cause))
  905                                 va += sizeof(int);
  906                         /* read break instruction */
  907                         instr = fuword((caddr_t)va);
  908 
  909                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
  910                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
  911                                     0);
  912                         } else {
  913                                 locr0->pc += sizeof(int);
  914                         }
  915                         addr = va;
  916                         i = SIGEMT;     /* Stuff it with something for now */
  917                         break;
  918                 }
  919 
  920         case T_RES_INST + T_USER:
  921                 i = SIGILL;
  922                 addr = trapframe->pc;
  923                 break;
  924         case T_C2E:
  925         case T_C2E + T_USER:
  926                 goto err;
  927                 break;
  928         case T_COP_UNUSABLE:
  929                 goto err;
  930                 break;
  931         case T_COP_UNUSABLE + T_USER:
  932 #if defined(SOFTFLOAT)
  933                 /* FP (COP1) instruction */
  934                 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
  935                         i = SIGILL;
  936                         break;
  937                 }
  938 #endif
  939                 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
  940                         i = SIGILL;     /* only FPU instructions allowed */
  941                         break;
  942                 }
  943                 addr = trapframe->pc;
  944                 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
  945                 PCPU_SET(fpcurthread, td);
  946                 td->td_frame->sr |= SR_COP_1_BIT;
  947                 td->td_md.md_flags |= MDTD_FPUSED;
  948                 goto out;
  949 
  950         case T_FPE:
  951 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
  952                 trapDump("fpintr");
  953 #else
  954                 printf("FPU Trap: PC %x CR %x SR %x\n",
  955                     trapframe->pc, trapframe->cause, trapframe->sr);
  956                 goto err;
  957 #endif
  958 
  959         case T_FPE + T_USER:
  960                 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
  961                 goto out;
  962 
  963         case T_OVFLOW + T_USER:
  964                 i = SIGFPE;
  965                 addr = trapframe->pc;
  966                 break;
  967 
  968         case T_ADDR_ERR_LD:     /* misaligned access */
  969         case T_ADDR_ERR_ST:     /* misaligned access */
  970 #ifdef TRAP_DEBUG
  971                 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
  972                     trapframe->badvaddr);
  973 #endif
  974                 /* Only allow emulation on a user address */
  975                 if (allow_unaligned_acc &&
  976                     ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
  977                         int mode;
  978 
  979                         if (type == T_ADDR_ERR_LD)
  980                                 mode = VM_PROT_READ;
  981                         else
  982                                 mode = VM_PROT_WRITE;
  983 
  984                         /*
  985                          * ADDR_ERR faults have higher priority than TLB
  986                          * Miss faults.  Therefore, it is necessary to
  987                          * verify that the faulting address is a valid
  988                          * virtual address within the process' address space
  989                          * before trying to emulate the unaligned access.
  990                          */
  991                         if (useracc((caddr_t)
  992                             (((vm_offset_t)trapframe->badvaddr) &
  993                             ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
  994                                 access_type = emulate_unaligned_access(
  995                                     trapframe);
  996                                 if (access_type != 0) {
  997                                         return (trapframe->pc);
  998                                 }
  999                         }
 1000                 }
 1001                 /* FALLTHROUGH */
 1002 
 1003         case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
 1004                 if ((i = td->td_pcb->pcb_onfault) != 0) {
 1005                         td->td_pcb->pcb_onfault = 0;
 1006                         return (onfault_table[i]);
 1007                 }
 1008                 /* FALLTHROUGH */
 1009 
 1010         default:
 1011 err:
 1012 
 1013 #if !defined(SMP) && defined(DEBUG)
 1014                 stacktrace(!usermode ? trapframe : td->td_frame);
 1015                 trapDump("trap");
 1016 #endif
 1017 #ifdef SMP
 1018                 printf("cpu:%d-", PCPU_GET(cpuid));
 1019 #endif
 1020                 printf("Trap cause = %d (%s - ", type,
 1021                     trap_type[type & (~T_USER)]);
 1022 
 1023                 if (type & T_USER)
 1024                         printf("user mode)\n");
 1025                 else
 1026                         printf("kernel mode)\n");
 1027 
 1028 #ifdef TRAP_DEBUG
 1029                 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
 1030                        trapframe->badvaddr, trapframe->pc, trapframe->ra,
 1031                        trapframe->sr);
 1032 #endif
 1033 
 1034 #ifdef KDB
 1035                 if (debugger_on_panic || kdb_active) {
 1036                         kdb_trap(type, 0, trapframe);
 1037                 }
 1038 #endif
 1039                 panic("trap");
 1040         }
 1041         td->td_frame->pc = trapframe->pc;
 1042         td->td_frame->cause = trapframe->cause;
 1043         td->td_frame->badvaddr = trapframe->badvaddr;
 1044         ksiginfo_init_trap(&ksi);
 1045         ksi.ksi_signo = i;
 1046         ksi.ksi_code = ucode;
 1047         ksi.ksi_addr = (void *)addr;
 1048         ksi.ksi_trapno = type;
 1049         trapsignal(td, &ksi);
 1050 out:
 1051 
 1052         /*
 1053          * Note: we should only get here if returning to user mode.
 1054          */
 1055         userret(td, trapframe);
 1056         mtx_assert(&Giant, MA_NOTOWNED);
 1057         return (trapframe->pc);
 1058 }
 1059 
 1060 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
 1061 void
 1062 trapDump(char *msg)
 1063 {
 1064         int i, s;
 1065 
 1066         s = disableintr();
 1067         printf("trapDump(%s)\n", msg);
 1068         for (i = 0; i < TRAPSIZE; i++) {
 1069                 if (trp == trapdebug) {
 1070                         trp = &trapdebug[TRAPSIZE - 1];
 1071                 } else {
 1072                         trp--;
 1073                 }
 1074 
 1075                 if (trp->cause == 0)
 1076                         break;
 1077 
 1078                 printf("%s: ADR %x PC %x CR %x SR %x\n",
 1079                     trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
 1080                     trp->vadr, trp->pc, trp->cause, trp->status);
 1081 
 1082                 printf("   RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
 1083         }
 1084         restoreintr(s);
 1085 }
 1086 
 1087 #endif
 1088 
 1089 
 1090 /*
 1091  * Return the resulting PC as if the branch was executed.
 1092  */
 1093 u_int
 1094 MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR,
 1095     u_int instptr)
 1096 {
 1097         InstFmt inst;
 1098         register_t *regsPtr = (register_t *) framePtr;
 1099         unsigned retAddr = 0;
 1100         int condition;
 1101 
 1102 #define GetBranchDest(InstPtr, inst) \
 1103         ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
 1104 
 1105 
 1106         if (instptr) {
 1107                 if (instptr < MIPS_KSEG0_START)
 1108                         inst.word = fuword((void *)instptr);
 1109                 else
 1110                         inst = *(InstFmt *) instptr;
 1111         } else {
 1112                 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
 1113                         inst.word = fuword((void *)instPC);
 1114                 else
 1115                         inst = *(InstFmt *) instPC;
 1116         }
 1117 
 1118         switch ((int)inst.JType.op) {
 1119         case OP_SPECIAL:
 1120                 switch ((int)inst.RType.func) {
 1121                 case OP_JR:
 1122                 case OP_JALR:
 1123                         retAddr = regsPtr[inst.RType.rs];
 1124                         break;
 1125 
 1126                 default:
 1127                         retAddr = instPC + 4;
 1128                         break;
 1129                 }
 1130                 break;
 1131 
 1132         case OP_BCOND:
 1133                 switch ((int)inst.IType.rt) {
 1134                 case OP_BLTZ:
 1135                 case OP_BLTZL:
 1136                 case OP_BLTZAL:
 1137                 case OP_BLTZALL:
 1138                         if ((int)(regsPtr[inst.RType.rs]) < 0)
 1139                                 retAddr = GetBranchDest(instPC, inst);
 1140                         else
 1141                                 retAddr = instPC + 8;
 1142                         break;
 1143 
 1144                 case OP_BGEZ:
 1145                 case OP_BGEZL:
 1146                 case OP_BGEZAL:
 1147                 case OP_BGEZALL:
 1148                         if ((int)(regsPtr[inst.RType.rs]) >= 0)
 1149                                 retAddr = GetBranchDest(instPC, inst);
 1150                         else
 1151                                 retAddr = instPC + 8;
 1152                         break;
 1153 
 1154                 case OP_TGEI:
 1155                 case OP_TGEIU:
 1156                 case OP_TLTI:
 1157                 case OP_TLTIU:
 1158                 case OP_TEQI:
 1159                 case OP_TNEI:
 1160                         retAddr = instPC + 4;   /* Like syscall... */
 1161                         break;
 1162 
 1163                 default:
 1164                         panic("MipsEmulateBranch: Bad branch cond");
 1165                 }
 1166                 break;
 1167 
 1168         case OP_J:
 1169         case OP_JAL:
 1170                 retAddr = (inst.JType.target << 2) |
 1171                     ((unsigned)instPC & 0xF0000000);
 1172                 break;
 1173 
 1174         case OP_BEQ:
 1175         case OP_BEQL:
 1176                 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
 1177                         retAddr = GetBranchDest(instPC, inst);
 1178                 else
 1179                         retAddr = instPC + 8;
 1180                 break;
 1181 
 1182         case OP_BNE:
 1183         case OP_BNEL:
 1184                 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
 1185                         retAddr = GetBranchDest(instPC, inst);
 1186                 else
 1187                         retAddr = instPC + 8;
 1188                 break;
 1189 
 1190         case OP_BLEZ:
 1191         case OP_BLEZL:
 1192                 if ((int)(regsPtr[inst.RType.rs]) <= 0)
 1193                         retAddr = GetBranchDest(instPC, inst);
 1194                 else
 1195                         retAddr = instPC + 8;
 1196                 break;
 1197 
 1198         case OP_BGTZ:
 1199         case OP_BGTZL:
 1200                 if ((int)(regsPtr[inst.RType.rs]) > 0)
 1201                         retAddr = GetBranchDest(instPC, inst);
 1202                 else
 1203                         retAddr = instPC + 8;
 1204                 break;
 1205 
 1206         case OP_COP1:
 1207                 switch (inst.RType.rs) {
 1208                 case OP_BCx:
 1209                 case OP_BCy:
 1210                         if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
 1211                                 condition = fpcCSR & FPC_COND_BIT;
 1212                         else
 1213                                 condition = !(fpcCSR & FPC_COND_BIT);
 1214                         if (condition)
 1215                                 retAddr = GetBranchDest(instPC, inst);
 1216                         else
 1217                                 retAddr = instPC + 8;
 1218                         break;
 1219 
 1220                 default:
 1221                         retAddr = instPC + 4;
 1222                 }
 1223                 break;
 1224 
 1225         default:
 1226                 retAddr = instPC + 4;
 1227         }
 1228         return (retAddr);
 1229 }
 1230 
 1231 
 1232 #if defined(DDB) || defined(DEBUG)
 1233 #define MIPS_JR_RA      0x03e00008      /* instruction code for jr ra */
 1234 
 1235 /* forward */
 1236 char *fn_name(unsigned addr);
 1237 
 1238 /*
 1239  * Print a stack backtrace.
 1240  */
 1241 void
 1242 stacktrace(struct trapframe *regs)
 1243 {
 1244         stacktrace_subr(regs, printf);
 1245 }
 1246 
 1247 void
 1248 stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...))
 1249 {
 1250         InstFmt i;
 1251         unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr;
 1252         unsigned instr, mask;
 1253         unsigned int frames = 0;
 1254         int more, stksize;
 1255 
 1256         /* get initial values from the exception frame */
 1257         sp = regs->sp;
 1258         pc = regs->pc;
 1259         fp = regs->s8;
 1260         ra = regs->ra;          /* May be a 'leaf' function */
 1261         a0 = regs->a0;
 1262         a1 = regs->a1;
 1263         a2 = regs->a2;
 1264         a3 = regs->a3;
 1265 
 1266 /* Jump here when done with a frame, to start a new one */
 1267 loop:
 1268 
 1269 /* Jump here after a nonstandard (interrupt handler) frame */
 1270         stksize = 0;
 1271         subr = 0;
 1272         if (frames++ > 100) {
 1273                 (*printfn) ("\nstackframe count exceeded\n");
 1274                 /* return breaks stackframe-size heuristics with gcc -O2 */
 1275                 goto finish;    /* XXX */
 1276         }
 1277         /* check for bad SP: could foul up next frame */
 1278         if (sp & 3 || sp < 0x80000000) {
 1279                 (*printfn) ("SP 0x%x: not in kernel\n", sp);
 1280                 ra = 0;
 1281                 subr = 0;
 1282                 goto done;
 1283         }
 1284 #define Between(x, y, z) \
 1285                 ( ((x) <= (y)) && ((y) < (z)) )
 1286 #define pcBetween(a,b) \
 1287                 Between((unsigned)a, pc, (unsigned)b)
 1288 
 1289         /*
 1290          * Check for current PC in  exception handler code that don't have a
 1291          * preceding "j ra" at the tail of the preceding function. Depends
 1292          * on relative ordering of functions in exception.S, swtch.S.
 1293          */
 1294         if (pcBetween(MipsKernGenException, MipsUserGenException))
 1295                 subr = (unsigned)MipsKernGenException;
 1296         else if (pcBetween(MipsUserGenException, MipsKernIntr))
 1297                 subr = (unsigned)MipsUserGenException;
 1298         else if (pcBetween(MipsKernIntr, MipsUserIntr))
 1299                 subr = (unsigned)MipsKernIntr;
 1300         else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
 1301                 subr = (unsigned)MipsUserIntr;
 1302         else if (pcBetween(MipsTLBInvalidException,
 1303             MipsKernTLBInvalidException))
 1304                 subr = (unsigned)MipsTLBInvalidException;
 1305         else if (pcBetween(MipsKernTLBInvalidException,
 1306             MipsUserTLBInvalidException))
 1307                 subr = (unsigned)MipsKernTLBInvalidException;
 1308         else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
 1309                 subr = (unsigned)MipsUserTLBInvalidException;
 1310         else if (pcBetween(cpu_switch, MipsSwitchFPState))
 1311                 subr = (unsigned)cpu_switch;
 1312         else if (pcBetween(_locore, _locoreEnd)) {
 1313                 subr = (unsigned)_locore;
 1314                 ra = 0;
 1315                 goto done;
 1316         }
 1317         /* check for bad PC */
 1318         if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) {
 1319                 (*printfn) ("PC 0x%x: not in kernel\n", pc);
 1320                 ra = 0;
 1321                 goto done;
 1322         }
 1323         /*
 1324          * Find the beginning of the current subroutine by scanning
 1325          * backwards from the current PC for the end of the previous
 1326          * subroutine.
 1327          */
 1328         if (!subr) {
 1329                 va = pc - sizeof(int);
 1330                 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
 1331                         va -= sizeof(int);
 1332                 va += 2 * sizeof(int);  /* skip back over branch & delay slot */
 1333                 /* skip over nulls which might separate .o files */
 1334                 while ((instr = kdbpeek((int *)va)) == 0)
 1335                         va += sizeof(int);
 1336                 subr = va;
 1337         }
 1338         /* scan forwards to find stack size and any saved registers */
 1339         stksize = 0;
 1340         more = 3;
 1341         mask = 0;
 1342         for (va = subr; more; va += sizeof(int),
 1343             more = (more == 3) ? 3 : more - 1) {
 1344                 /* stop if hit our current position */
 1345                 if (va >= pc)
 1346                         break;
 1347                 instr = kdbpeek((int *)va);
 1348                 i.word = instr;
 1349                 switch (i.JType.op) {
 1350                 case OP_SPECIAL:
 1351                         switch (i.RType.func) {
 1352                         case OP_JR:
 1353                         case OP_JALR:
 1354                                 more = 2;       /* stop after next instruction */
 1355                                 break;
 1356 
 1357                         case OP_SYSCALL:
 1358                         case OP_BREAK:
 1359                                 more = 1;       /* stop now */
 1360                         };
 1361                         break;
 1362 
 1363                 case OP_BCOND:
 1364                 case OP_J:
 1365                 case OP_JAL:
 1366                 case OP_BEQ:
 1367                 case OP_BNE:
 1368                 case OP_BLEZ:
 1369                 case OP_BGTZ:
 1370                         more = 2;       /* stop after next instruction */
 1371                         break;
 1372 
 1373                 case OP_COP0:
 1374                 case OP_COP1:
 1375                 case OP_COP2:
 1376                 case OP_COP3:
 1377                         switch (i.RType.rs) {
 1378                         case OP_BCx:
 1379                         case OP_BCy:
 1380                                 more = 2;       /* stop after next instruction */
 1381                         };
 1382                         break;
 1383 
 1384                 case OP_SW:
 1385                         /* look for saved registers on the stack */
 1386                         if (i.IType.rs != 29)
 1387                                 break;
 1388                         /* only restore the first one */
 1389                         if (mask & (1 << i.IType.rt))
 1390                                 break;
 1391                         mask |= (1 << i.IType.rt);
 1392                         switch (i.IType.rt) {
 1393                         case 4:/* a0 */
 1394                                 a0 = kdbpeek((int *)(sp + (short)i.IType.imm));
 1395                                 break;
 1396 
 1397                         case 5:/* a1 */
 1398                                 a1 = kdbpeek((int *)(sp + (short)i.IType.imm));
 1399                                 break;
 1400 
 1401                         case 6:/* a2 */
 1402                                 a2 = kdbpeek((int *)(sp + (short)i.IType.imm));
 1403                                 break;
 1404 
 1405                         case 7:/* a3 */
 1406                                 a3 = kdbpeek((int *)(sp + (short)i.IType.imm));
 1407                                 break;
 1408 
 1409                         case 30:        /* fp */
 1410                                 fp = kdbpeek((int *)(sp + (short)i.IType.imm));
 1411                                 break;
 1412 
 1413                         case 31:        /* ra */
 1414                                 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
 1415                         }
 1416                         break;
 1417 
 1418                 case OP_SD:
 1419                         /* look for saved registers on the stack */
 1420                         if (i.IType.rs != 29)
 1421                                 break;
 1422                         /* only restore the first one */
 1423                         if (mask & (1 << i.IType.rt))
 1424                                 break;
 1425                         mask |= (1 << i.IType.rt);
 1426                         switch (i.IType.rt) {
 1427                         case 4:/* a0 */
 1428                                 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1429                                 break;
 1430 
 1431                         case 5:/* a1 */
 1432                                 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1433                                 break;
 1434 
 1435                         case 6:/* a2 */
 1436                                 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1437                                 break;
 1438 
 1439                         case 7:/* a3 */
 1440                                 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1441                                 break;
 1442 
 1443                         case 30:        /* fp */
 1444                                 fp = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1445                                 break;
 1446 
 1447                         case 31:        /* ra */
 1448                                 ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
 1449                         }
 1450                         break;
 1451 
 1452                 case OP_ADDI:
 1453                 case OP_ADDIU:
 1454                         /* look for stack pointer adjustment */
 1455                         if (i.IType.rs != 29 || i.IType.rt != 29)
 1456                                 break;
 1457                         stksize = -((short)i.IType.imm);
 1458                 }
 1459         }
 1460 
 1461 done:
 1462         (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
 1463             fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
 1464 
 1465         if (ra) {
 1466                 if (pc == ra && stksize == 0)
 1467                         (*printfn) ("stacktrace: loop!\n");
 1468                 else {
 1469                         pc = ra;
 1470                         sp += stksize;
 1471                         ra = 0;
 1472                         goto loop;
 1473                 }
 1474         } else {
 1475 finish:
 1476                 if (curproc)
 1477                         (*printfn) ("pid %d\n", curproc->p_pid);
 1478                 else
 1479                         (*printfn) ("curproc NULL\n");
 1480         }
 1481 }
 1482 
 1483 /*
 1484  * Functions ``special'' enough to print by name
 1485  */
 1486 #ifdef __STDC__
 1487 #define Name(_fn)  { (void*)_fn, # _fn }
 1488 #else
 1489 #define Name(_fn) { _fn, "_fn"}
 1490 #endif
 1491 static struct {
 1492         void *addr;
 1493         char *name;
 1494 }      names[] = {
 1495 
 1496         Name(trap),
 1497         Name(MipsKernGenException),
 1498         Name(MipsUserGenException),
 1499         Name(MipsKernIntr),
 1500         Name(MipsUserIntr),
 1501         Name(cpu_switch),
 1502         {
 1503                 0, 0
 1504         }
 1505 };
 1506 
 1507 /*
 1508  * Map a function address to a string name, if known; or a hex string.
 1509  */
 1510 char *
 1511 fn_name(unsigned addr)
 1512 {
 1513         static char buf[17];
 1514         int i = 0;
 1515 
 1516 #ifdef DDB
 1517         db_expr_t diff;
 1518         c_db_sym_t sym;
 1519         char *symname;
 1520 
 1521         diff = 0;
 1522         symname = NULL;
 1523         sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
 1524         db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
 1525         if (symname && diff == 0)
 1526                 return (symname);
 1527 #endif
 1528 
 1529         for (i = 0; names[i].name; i++)
 1530                 if (names[i].addr == (void *)addr)
 1531                         return (names[i].name);
 1532         sprintf(buf, "%x", addr);
 1533         return (buf);
 1534 }
 1535 
 1536 #endif                          /* DDB */
 1537 
 1538 static void
 1539 log_frame_dump(struct trapframe *frame)
 1540 {
 1541         log(LOG_ERR, "Trapframe Register Dump:\n");
 1542         log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
 1543             0, frame->ast, frame->v0, frame->v1);
 1544 
 1545         log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
 1546             frame->a0, frame->a1, frame->a2, frame->a3);
 1547 
 1548         log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
 1549             frame->t0, frame->t1, frame->t2, frame->t3);
 1550 
 1551         log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
 1552             frame->t4, frame->t5, frame->t6, frame->t7);
 1553 
 1554         log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
 1555             frame->t8, frame->t9, frame->s0, frame->s1);
 1556 
 1557         log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
 1558             frame->s2, frame->s3, frame->s4, frame->s5);
 1559 
 1560         log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
 1561             frame->s6, frame->s7, frame->k0, frame->k1);
 1562 
 1563         log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
 1564             frame->gp, frame->sp, frame->s8, frame->ra);
 1565 
 1566         log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
 1567             frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
 1568 
 1569 #ifdef IC_REG
 1570         log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n",
 1571             frame->cause, frame->pc, frame->ic);
 1572 #else
 1573         log(LOG_ERR, "\tcause: %08x\tpc: %08x\n",
 1574             frame->cause, frame->pc);
 1575 #endif
 1576 }
 1577 
 1578 #ifdef TRAP_DEBUG
 1579 static void
 1580 trap_frame_dump(struct trapframe *frame)
 1581 {
 1582         printf("Trapframe Register Dump:\n");
 1583         printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
 1584             0, frame->ast, frame->v0, frame->v1);
 1585 
 1586         printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
 1587             frame->a0, frame->a1, frame->a2, frame->a3);
 1588 
 1589         printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
 1590             frame->t0, frame->t1, frame->t2, frame->t3);
 1591 
 1592         printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
 1593             frame->t4, frame->t5, frame->t6, frame->t7);
 1594 
 1595         printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
 1596             frame->t8, frame->t9, frame->s0, frame->s1);
 1597 
 1598         printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
 1599             frame->s2, frame->s3, frame->s4, frame->s5);
 1600 
 1601         printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
 1602             frame->s6, frame->s7, frame->k0, frame->k1);
 1603 
 1604         printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
 1605             frame->gp, frame->sp, frame->s8, frame->ra);
 1606 
 1607         printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
 1608             frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
 1609 
 1610 #ifdef IC_REG
 1611         printf("\tcause: %08x\tpc: %08x\tic: %08x\n",
 1612             frame->cause, frame->pc, frame->ic);
 1613 #else
 1614         printf("\tcause: %08x\tpc: %08x\n",
 1615             frame->cause, frame->pc);
 1616 #endif
 1617 }
 1618 
 1619 #endif
 1620 
 1621 
 1622 static void
 1623 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
 1624 {
 1625         pt_entry_t *ptep;
 1626         pd_entry_t *pdep;
 1627         struct proc *p = curproc;
 1628 
 1629         pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
 1630         if (*pdep)
 1631                 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
 1632         else
 1633                 ptep = (pt_entry_t *)0;
 1634 
 1635         *pdepp = pdep;
 1636         *ptepp = ptep;
 1637 }
 1638 
 1639 
 1640 static void
 1641 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
 1642 {
 1643         pt_entry_t *ptep;
 1644         pd_entry_t *pdep;
 1645         unsigned int *addr;
 1646         struct proc *p = curproc;
 1647         char *read_or_write;
 1648         register_t pc;
 1649 
 1650         trap_type &= ~T_USER;
 1651 
 1652 #ifdef SMP
 1653         printf("cpuid = %d\n", PCPU_GET(cpuid));
 1654 #endif
 1655         switch (trap_type) {
 1656         case T_TLB_ST_MISS:
 1657         case T_ADDR_ERR_ST:
 1658                 read_or_write = "write";
 1659                 break;
 1660         case T_TLB_LD_MISS:
 1661         case T_ADDR_ERR_LD:
 1662         case T_BUS_ERR_IFETCH:
 1663                 read_or_write = "read";
 1664                 break;
 1665         default:
 1666                 read_or_write = "";
 1667         }
 1668 
 1669         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1670         log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n",
 1671             msg, p->p_pid, p->p_comm,
 1672             p->p_ucred ? p->p_ucred->cr_uid : -1,
 1673             pc,
 1674             read_or_write,
 1675             frame->badvaddr);
 1676 
 1677         /* log registers in trap frame */
 1678         log_frame_dump(frame);
 1679 
 1680         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
 1681 
 1682         /*
 1683          * Dump a few words around faulting instruction, if the addres is
 1684          * valid.
 1685          */
 1686         if (!(pc & 3) && (pc != frame->badvaddr) &&
 1687             (trap_type != T_BUS_ERR_IFETCH) &&
 1688             useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
 1689                 /* dump page table entry for faulting instruction */
 1690                 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n",
 1691                     pc, *pdep, ptep ? *ptep : 0);
 1692 
 1693                 addr = (unsigned int *)pc;
 1694                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
 1695                     addr);
 1696                 log(LOG_ERR, "%08x %08x %08x %08x\n",
 1697                     addr[0], addr[1], addr[2], addr[3]);
 1698         } else {
 1699                 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n",
 1700                     pc, *pdep, ptep ? *ptep : 0);
 1701         }
 1702         /*      panic("Bad trap");*/
 1703 }
 1704 
 1705 
 1706 /*
 1707  * Unaligned load/store emulation
 1708  */
 1709 static int
 1710 mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
 1711 {
 1712         register_t *reg = (register_t *) frame;
 1713         u_int32_t inst = *((u_int32_t *) pc);
 1714         u_int32_t value_msb, value;
 1715         int access_type = 0;
 1716 
 1717         switch (MIPS_INST_OPCODE(inst)) {
 1718         case OP_LHU:
 1719                 lbu_macro(value_msb, addr);
 1720                 addr += 1;
 1721                 lbu_macro(value, addr);
 1722                 value |= value_msb << 8;
 1723                 reg[MIPS_INST_RT(inst)] = value;
 1724                 access_type = MIPS_LHU_ACCESS;
 1725                 break;
 1726 
 1727         case OP_LH:
 1728                 lb_macro(value_msb, addr);
 1729                 addr += 1;
 1730                 lbu_macro(value, addr);
 1731                 value |= value_msb << 8;
 1732                 reg[MIPS_INST_RT(inst)] = value;
 1733                 access_type = MIPS_LH_ACCESS;
 1734                 break;
 1735 
 1736         case OP_LWU:
 1737                 lwl_macro(value, addr);
 1738                 addr += 3;
 1739                 lwr_macro(value, addr);
 1740                 value &= 0xffffffff;
 1741                 reg[MIPS_INST_RT(inst)] = value;
 1742                 access_type = MIPS_LWU_ACCESS;
 1743                 break;
 1744 
 1745         case OP_LW:
 1746                 lwl_macro(value, addr);
 1747                 addr += 3;
 1748                 lwr_macro(value, addr);
 1749                 reg[MIPS_INST_RT(inst)] = value;
 1750                 access_type = MIPS_LW_ACCESS;
 1751                 break;
 1752 
 1753         case OP_SH:
 1754                 value = reg[MIPS_INST_RT(inst)];
 1755                 value_msb = value >> 8;
 1756                 sb_macro(value_msb, addr);
 1757                 addr += 1;
 1758                 sb_macro(value, addr);
 1759                 access_type = MIPS_SH_ACCESS;
 1760                 break;
 1761 
 1762         case OP_SW:
 1763                 value = reg[MIPS_INST_RT(inst)];
 1764                 swl_macro(value, addr);
 1765                 addr += 3;
 1766                 swr_macro(value, addr);
 1767                 access_type = MIPS_SW_ACCESS;
 1768                 break;
 1769 
 1770         default:
 1771                 break;
 1772         }
 1773 
 1774         return access_type;
 1775 }
 1776 
 1777 
 1778 static int
 1779 emulate_unaligned_access(struct trapframe *frame)
 1780 {
 1781         register_t pc;
 1782         int access_type = 0;
 1783 
 1784         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
 1785 
 1786         /*
 1787          * Fall through if it's instruction fetch exception
 1788          */
 1789         if (!((pc & 3) || (pc == frame->badvaddr))) {
 1790 
 1791                 /*
 1792                  * Handle unaligned load and store
 1793                  */
 1794 
 1795                 /*
 1796                  * Return access type if the instruction was emulated.
 1797                  * Otherwise restore pc and fall through.
 1798                  */
 1799                 access_type = mips_unaligned_load_store(frame,
 1800                     frame->badvaddr, pc);
 1801 
 1802                 if (access_type) {
 1803                         if (DELAYBRANCH(frame->cause))
 1804                                 frame->pc = MipsEmulateBranch(frame, frame->pc,
 1805                                     0, 0);
 1806                         else
 1807                                 frame->pc += 4;
 1808 
 1809                         log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n",
 1810                             access_name[access_type - 1], pc, frame->badvaddr);
 1811                 }
 1812         }
 1813         return access_type;
 1814 }

Cache object: 595b321752aac209aaa3c5ef4316051f


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