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

Cache object: 9f5a8fbdf16f919f201803837a9f9614


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