1 /* $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $ */
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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
36 * from: Utah Hdr: trap.c 1.32 91/04/06
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
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
45 #include "opt_global.h"
46 #include "opt_ktrace.h"
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>
53 #include <sys/kernel.h>
54 #include <sys/signalvar.h>
55 #include <sys/syscall.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>
67 #include <sys/vnode.h>
68 #include <sys/pioctl.h>
69 #include <sys/sysctl.h>
70 #include <sys/syslog.h>
73 #include <sys/ktrace.h>
75 #include <net/netisr.h>
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>
88 #include <machine/db_machdep.h>
89 #include <ddb/db_sym.h>
94 #include <sys/cdefs.h>
95 #include <sys/syslog.h>
100 SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
101 &trap_debug, 0, "Debug information on all traps");
104 static void log_illegal_instruction(const char *, struct trapframe *);
105 static void log_bad_page_fault(char *, struct trapframe *, int);
106 static void log_frame_dump(struct trapframe *frame);
107 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
110 static void trap_frame_dump(struct trapframe *frame);
113 void (*machExceptionTable[]) (void)= {
115 * The kernel exception handlers.
117 MipsKernIntr, /* external interrupt */
118 MipsKernGenException, /* TLB modification */
119 MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
120 MipsTLBInvalidException,/* TLB miss (store) */
121 MipsKernGenException, /* address error (load or I-fetch) */
122 MipsKernGenException, /* address error (store) */
123 MipsKernGenException, /* bus error (I-fetch) */
124 MipsKernGenException, /* bus error (load or store) */
125 MipsKernGenException, /* system call */
126 MipsKernGenException, /* breakpoint */
127 MipsKernGenException, /* reserved instruction */
128 MipsKernGenException, /* coprocessor unusable */
129 MipsKernGenException, /* arithmetic overflow */
130 MipsKernGenException, /* trap exception */
131 MipsKernGenException, /* virtual coherence exception inst */
132 MipsKernGenException, /* floating point exception */
133 MipsKernGenException, /* reserved */
134 MipsKernGenException, /* reserved */
135 MipsKernGenException, /* reserved */
136 MipsKernGenException, /* reserved */
137 MipsKernGenException, /* reserved */
138 MipsKernGenException, /* reserved */
139 MipsKernGenException, /* reserved */
140 MipsKernGenException, /* watch exception */
141 MipsKernGenException, /* reserved */
142 MipsKernGenException, /* reserved */
143 MipsKernGenException, /* reserved */
144 MipsKernGenException, /* reserved */
145 MipsKernGenException, /* reserved */
146 MipsKernGenException, /* reserved */
147 MipsKernGenException, /* reserved */
148 MipsKernGenException, /* virtual coherence exception data */
150 * The user exception handlers.
152 MipsUserIntr, /* 0 */
153 MipsUserGenException, /* 1 */
154 MipsTLBInvalidException,/* 2 */
155 MipsTLBInvalidException,/* 3 */
156 MipsUserGenException, /* 4 */
157 MipsUserGenException, /* 5 */
158 MipsUserGenException, /* 6 */
159 MipsUserGenException, /* 7 */
160 MipsUserGenException, /* 8 */
161 MipsUserGenException, /* 9 */
162 MipsUserGenException, /* 10 */
163 MipsUserGenException, /* 11 */
164 MipsUserGenException, /* 12 */
165 MipsUserGenException, /* 13 */
166 MipsUserGenException, /* 14 */
167 MipsUserGenException, /* 15 */
168 MipsUserGenException, /* 16 */
169 MipsUserGenException, /* 17 */
170 MipsUserGenException, /* 18 */
171 MipsUserGenException, /* 19 */
172 MipsUserGenException, /* 20 */
173 MipsUserGenException, /* 21 */
174 MipsUserGenException, /* 22 */
175 MipsUserGenException, /* 23 */
176 MipsUserGenException, /* 24 */
177 MipsUserGenException, /* 25 */
178 MipsUserGenException, /* 26 */
179 MipsUserGenException, /* 27 */
180 MipsUserGenException, /* 28 */
181 MipsUserGenException, /* 29 */
182 MipsUserGenException, /* 20 */
183 MipsUserGenException, /* 31 */
186 char *trap_type[] = {
187 "external interrupt",
189 "TLB miss (load or instr. fetch)",
191 "address error (load or I-fetch)",
192 "address error (store)",
193 "bus error (I-fetch)",
194 "bus error (load or store)",
197 "reserved instruction",
198 "coprocessor unusable",
199 "arithmetic overflow",
201 "virtual coherency instruction",
218 "virtual coherency data",
221 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
222 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
225 #if defined(DDB) || defined(DEBUG)
226 void stacktrace(struct trapframe *);
227 void logstacktrace(struct trapframe *);
230 #define KERNLAND(x) ((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS)
231 #define DELAYBRANCH(x) ((int)(x) < 0)
234 * MIPS load/store access type
247 char *access_name[] = {
248 "Load Halfword Unsigned",
250 "Load Word Unsigned",
259 static int allow_unaligned_acc = 1;
261 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
262 &allow_unaligned_acc, 0, "Allow unaligned accesses");
264 static int emulate_unaligned_access(struct trapframe *frame, int mode);
266 extern void fswintrberr(void); /* XXX */
269 * Handle an exception.
270 * Called from MipsKernGenException() or MipsUserGenException()
271 * when a processor trap occurs.
272 * In the case of a kernel trap, we return the pc where to resume if
273 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
276 trap(struct trapframe *trapframe)
281 struct thread *td = curthread;
282 struct proc *p = curproc;
291 trapdebug_enter(trapframe, 0);
293 type = (trapframe->cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
294 if (TRAPF_USERMODE(trapframe)) {
302 * Enable hardware interrupts if they were on before the trap. If it
303 * was off disable all so we don't accidently enable it when doing a
304 * return to userland.
306 if (trapframe->sr & MIPS_SR_INT_IE) {
307 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
315 static vm_offset_t last_badvaddr = 0;
316 static vm_offset_t this_badvaddr = 0;
317 static int count = 0;
320 printf("trap type %x (%s - ", type,
321 trap_type[type & (~T_USER)]);
324 printf("user mode)\n");
326 printf("kernel mode)\n");
329 printf("cpuid = %d\n", PCPU_GET(cpuid));
331 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
332 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
333 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
334 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
335 (curproc ? curproc->p_pid : -1), pid);
337 switch (type & ~T_USER) {
343 this_badvaddr = trapframe->badvaddr;
346 this_badvaddr = trapframe->ra;
349 this_badvaddr = trapframe->pc;
352 if ((last_badvaddr == this_badvaddr) &&
353 ((type & ~T_USER) != T_SYSCALL)) {
355 trap_frame_dump(trapframe);
356 panic("too many faults at %p\n", (void *)last_badvaddr);
359 last_badvaddr = this_badvaddr;
367 kdb_trap(type, 0, trapframe);
372 /* check for kernel address */
373 if (KERNLAND(trapframe->badvaddr)) {
374 if (pmap_emulate_modified(kernel_pmap,
375 trapframe->badvaddr) != 0) {
376 ftype = VM_PROT_WRITE;
379 return (trapframe->pc);
383 case T_TLB_MOD + T_USER:
384 pmap = &p->p_vmspace->vm_pmap;
385 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
386 ftype = VM_PROT_WRITE;
390 return (trapframe->pc);
395 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
396 /* check for kernel address */
397 if (KERNLAND(trapframe->badvaddr)) {
402 va = trunc_page((vm_offset_t)trapframe->badvaddr);
403 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
404 if (rv == KERN_SUCCESS)
405 return (trapframe->pc);
406 if (td->td_pcb->pcb_onfault != NULL) {
407 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
408 td->td_pcb->pcb_onfault = NULL;
415 * It is an error for the kernel to access user space except
416 * through the copyin/copyout routines.
418 if (td->td_pcb->pcb_onfault == NULL)
421 /* check for fuswintr() or suswintr() getting a page fault */
422 /* XXX There must be a nicer way to do this. */
423 if (td->td_pcb->pcb_onfault == fswintrberr) {
424 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
425 td->td_pcb->pcb_onfault = NULL;
431 case T_TLB_LD_MISS + T_USER:
432 ftype = VM_PROT_READ;
435 case T_TLB_ST_MISS + T_USER:
436 ftype = VM_PROT_WRITE;
446 va = trunc_page((vm_offset_t)trapframe->badvaddr);
447 if (KERNLAND(trapframe->badvaddr)) {
449 * Don't allow user-mode faults in kernel
456 * Keep swapout from messing with us during this
463 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
469 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
470 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
471 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
474 if (rv == KERN_SUCCESS) {
476 return (trapframe->pc);
482 if (td->td_pcb->pcb_onfault != NULL) {
483 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
484 td->td_pcb->pcb_onfault = NULL;
490 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
491 addr = trapframe->pc;
493 msg = "BAD_PAGE_FAULT";
494 log_bad_page_fault(msg, trapframe, type);
499 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
500 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
501 if (trapframe->badvaddr < 0 ||
502 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
503 msg = "ADDRESS_SPACE_ERR";
504 } else if (allow_unaligned_acc) {
507 if (type == (T_ADDR_ERR_LD + T_USER))
510 mode = VM_PROT_WRITE;
512 access_type = emulate_unaligned_access(trapframe, mode);
513 if (access_type != 0)
515 msg = "ALIGNMENT_FIX_ERR";
522 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
523 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
524 ucode = 0; /* XXX should be VM_PROT_something */
526 addr = trapframe->pc;
529 log_bad_page_fault(msg, trapframe, type);
532 case T_SYSCALL + T_USER:
534 struct trapframe *locr0 = td->td_frame;
535 struct sysent *callp;
540 bzero(args, sizeof args);
543 * note: PCPU_LAZY_INC() can only be used if we can
544 * afford occassional inaccuracy in the count.
546 PCPU_LAZY_INC(cnt.v_syscall);
547 if (td->td_ucred != p->p_ucred)
548 cred_update_thread(td);
550 if (p->p_flag & P_SA)
551 thread_user_enter(td);
553 /* compute next PC after syscall instruction */
554 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
555 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
556 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
559 locr0->pc += sizeof(int);
564 #if defined(__mips_n32) || defined(__mips_n64)
567 * Quads fit in a single register in
575 * Code is first argument, followed by
583 #if defined(__mips_n32) || defined(__mips_n64)
592 #if defined(__mips_o32)
595 * Like syscall, but code is a quad, so as
596 * to maintain quad alignment for the rest
599 if (_QUAD_LOWWORD == 0) {
616 #if defined (__mips_n32) || defined(__mips_n64)
626 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
630 if (p->p_sysent->sv_mask)
631 code &= p->p_sysent->sv_mask;
633 if (code >= p->p_sysent->sv_size)
634 callp = &p->p_sysent->sv_table[0];
636 callp = &p->p_sysent->sv_table[code];
638 nargs = callp->sy_narg;
640 if (nargs > nsaved) {
641 #if defined(__mips_n32) || defined(__mips_n64)
644 * Is this right for new ABIs? I think the 4 there
645 * should be 8, size there are 8 registers to skip,
646 * not 4, but I'm not certain.
648 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
650 i = copyin((caddr_t)(intptr_t)(locr0->sp +
651 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
652 (u_int)(nargs - nsaved) * sizeof(register_t));
657 if (KTRPOINT(td, KTR_SYSCALL))
658 ktrsyscall(code, nargs, args);
665 for (i = 0; i < nargs; i++) {
666 printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
670 #ifdef SYSCALL_TRACING
671 printf("%s(", syscallnames[code]);
672 for (i = 0; i < nargs; i++) {
673 printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
678 if (KTRPOINT(td, KTR_SYSCALL))
679 ktrsyscall(code, nargs, args);
681 td->td_retval[0] = 0;
682 td->td_retval[1] = locr0->v1;
684 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
685 if (trp == trapdebug)
686 trapdebug[TRAPSIZE - 1].code = code;
690 STOPEVENT(p, S_SCE, nargs);
692 PTRACESTOP_SC(p, td, S_PT_SCE);
693 i = (*callp->sy_call) (td, args);
696 * Reinitialize proc pointer `p' as it may be
697 * different if this is a child returning from fork
701 locr0 = td->td_frame;
703 trapdebug_enter(locr0, -code);
704 cpu_set_syscall_retval(td, i);
707 * The sync'ing of I & D caches for SYS_ptrace() is
708 * done by procfs_domem() through procfs_rwmem()
709 * instead of being done here under a special check
714 * Check for misbehavior.
716 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
717 (code >= 0 && code < SYS_MAXSYSCALL) ?
718 syscallnames[code] : "???");
719 KASSERT(td->td_critnest == 0,
720 ("System call %s returning in a critical section",
721 (code >= 0 && code < SYS_MAXSYSCALL) ?
722 syscallnames[code] : "???"));
723 KASSERT(td->td_locks == 0,
724 ("System call %s returning with %d locks held",
725 (code >= 0 && code < SYS_MAXSYSCALL) ?
726 syscallnames[code] : "???",
728 userret(td, trapframe);
730 if (KTRPOINT(td, KTR_SYSRET))
731 ktrsysret(code, i, td->td_retval[0]);
734 * This works because errno is findable through the
735 * register set. If we ever support an emulation
736 * where this is not the case, this code will need
739 STOPEVENT(p, S_SCX, code);
741 PTRACESTOP_SC(p, td, S_PT_SCX);
743 mtx_assert(&Giant, MA_NOTOWNED);
744 return (trapframe->pc);
749 kdb_trap(type, 0, trapframe);
750 return (trapframe->pc);
753 case T_BREAK + T_USER:
758 /* compute address of break instruction */
760 if (DELAYBRANCH(trapframe->cause))
763 /* read break instruction */
764 instr = fuword32((caddr_t)va);
766 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
767 p->p_comm, p->p_pid, instr, trapframe->pc,
768 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
770 if (td->td_md.md_ss_addr != va ||
771 instr != MIPS_BREAK_SSTEP) {
773 addr = trapframe->pc;
777 * The restoration of the original instruction and
778 * the clearing of the berakpoint will be done later
779 * by the call to ptrace_clear_single_step() in
780 * issignal() when SIGTRAP is processed.
782 addr = trapframe->pc;
787 case T_IWATCH + T_USER:
788 case T_DWATCH + T_USER:
792 /* compute address of trapped instruction */
794 if (DELAYBRANCH(trapframe->cause))
796 printf("watch exception @ %p\n", (void *)va);
802 case T_TRAP + T_USER:
806 struct trapframe *locr0 = td->td_frame;
808 /* compute address of trap instruction */
810 if (DELAYBRANCH(trapframe->cause))
812 /* read break instruction */
813 instr = fuword32((caddr_t)va);
815 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
816 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
819 locr0->pc += sizeof(int);
822 i = SIGEMT; /* Stuff it with something for now */
826 case T_RES_INST + T_USER:
827 log_illegal_instruction("RES_INST", trapframe);
829 addr = trapframe->pc;
838 case T_COP_UNUSABLE + T_USER:
839 #if !defined(CPU_HAVEFPU)
840 /* FP (COP1) instruction */
841 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) {
842 log_illegal_instruction("COP1_UNUSABLE", trapframe);
847 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) {
848 log_illegal_instruction("COPn_UNUSABLE", trapframe);
849 i = SIGILL; /* only FPU instructions allowed */
852 addr = trapframe->pc;
853 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
854 PCPU_SET(fpcurthread, td);
855 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
856 td->td_md.md_flags |= MDTD_FPUSED;
860 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
863 printf("FPU Trap: PC %#jx CR %x SR %x\n",
864 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
869 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
872 case T_OVFLOW + T_USER:
874 addr = trapframe->pc;
877 case T_ADDR_ERR_LD: /* misaligned access */
878 case T_ADDR_ERR_ST: /* misaligned access */
881 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
882 (intmax_t)trapframe->badvaddr);
885 /* Only allow emulation on a user address */
886 if (allow_unaligned_acc &&
887 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
890 if (type == T_ADDR_ERR_LD)
893 mode = VM_PROT_WRITE;
895 access_type = emulate_unaligned_access(trapframe, mode);
896 if (access_type != 0)
897 return (trapframe->pc);
901 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
902 if (td->td_pcb->pcb_onfault != NULL) {
903 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
904 td->td_pcb->pcb_onfault = NULL;
913 #if !defined(SMP) && defined(DEBUG)
914 stacktrace(!usermode ? trapframe : td->td_frame);
918 printf("cpu:%d-", PCPU_GET(cpuid));
920 printf("Trap cause = %d (%s - ", type,
921 trap_type[type & (~T_USER)]);
924 printf("user mode)\n");
926 printf("kernel mode)\n");
930 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
931 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
932 (intmax_t)trapframe->sr);
936 if (debugger_on_panic || kdb_active) {
937 kdb_trap(type, 0, trapframe);
942 td->td_frame->pc = trapframe->pc;
943 td->td_frame->cause = trapframe->cause;
944 td->td_frame->badvaddr = trapframe->badvaddr;
945 ksiginfo_init_trap(&ksi);
947 ksi.ksi_code = ucode;
948 ksi.ksi_addr = (void *)addr;
949 ksi.ksi_trapno = type;
950 trapsignal(td, &ksi);
954 * Note: we should only get here if returning to user mode.
956 userret(td, trapframe);
957 mtx_assert(&Giant, MA_NOTOWNED);
958 return (trapframe->pc);
961 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
969 printf("trapDump(%s)\n", msg);
970 for (i = 0; i < TRAPSIZE; i++) {
971 if (trp == trapdebug) {
972 trp = &trapdebug[TRAPSIZE - 1];
980 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
981 trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >>
982 MIPS_CR_EXC_CODE_SHIFT],
983 (intmax_t)trp->vadr, (intmax_t)trp->pc,
984 (intmax_t)trp->cause, (intmax_t)trp->status);
986 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
987 (intmax_t)trp->sp, (int)trp->code);
995 * Return the resulting PC as if the branch was executed.
998 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1002 register_t *regsPtr = (register_t *) framePtr;
1003 uintptr_t retAddr = 0;
1006 #define GetBranchDest(InstPtr, inst) \
1007 (InstPtr + 4 + ((short)inst.IType.imm << 2))
1011 if (instptr < MIPS_KSEG0_START)
1012 inst.word = fuword32((void *)instptr);
1014 inst = *(InstFmt *) instptr;
1016 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1017 inst.word = fuword32((void *)instPC);
1019 inst = *(InstFmt *) instPC;
1022 switch ((int)inst.JType.op) {
1024 switch ((int)inst.RType.func) {
1027 retAddr = regsPtr[inst.RType.rs];
1031 retAddr = instPC + 4;
1037 switch ((int)inst.IType.rt) {
1042 if ((int)(regsPtr[inst.RType.rs]) < 0)
1043 retAddr = GetBranchDest(instPC, inst);
1045 retAddr = instPC + 8;
1052 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1053 retAddr = GetBranchDest(instPC, inst);
1055 retAddr = instPC + 8;
1064 retAddr = instPC + 4; /* Like syscall... */
1068 panic("MipsEmulateBranch: Bad branch cond");
1074 retAddr = (inst.JType.target << 2) |
1075 ((unsigned)(instPC + 4) & 0xF0000000);
1080 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1081 retAddr = GetBranchDest(instPC, inst);
1083 retAddr = instPC + 8;
1088 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1089 retAddr = GetBranchDest(instPC, inst);
1091 retAddr = instPC + 8;
1096 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1097 retAddr = GetBranchDest(instPC, inst);
1099 retAddr = instPC + 8;
1104 if ((int)(regsPtr[inst.RType.rs]) > 0)
1105 retAddr = GetBranchDest(instPC, inst);
1107 retAddr = instPC + 8;
1111 switch (inst.RType.rs) {
1114 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1115 condition = fpcCSR & MIPS_FPU_COND_BIT;
1117 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1119 retAddr = GetBranchDest(instPC, inst);
1121 retAddr = instPC + 8;
1125 retAddr = instPC + 4;
1130 retAddr = instPC + 4;
1136 #if defined(DDB) || defined(DEBUG)
1138 * Print a stack backtrace.
1141 stacktrace(struct trapframe *regs)
1143 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1148 log_frame_dump(struct trapframe *frame)
1150 log(LOG_ERR, "Trapframe Register Dump:\n");
1151 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1152 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1154 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1155 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1157 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1158 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1160 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1161 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1163 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1164 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1166 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1167 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1169 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1170 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1172 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1173 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1175 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1176 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1179 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1180 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1182 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1183 (intmax_t)frame->cause, (intmax_t)frame->pc);
1189 trap_frame_dump(struct trapframe *frame)
1191 printf("Trapframe Register Dump:\n");
1192 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1193 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1195 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1196 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1198 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1199 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1201 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1202 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1204 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1205 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1207 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1208 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1210 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1211 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1213 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1214 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1216 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1217 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1220 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1221 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1223 printf("\tcause: %#jx\tpc: %#jx\n",
1224 (intmax_t)frame->cause, (intmax_t)frame->pc);
1232 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1236 struct proc *p = curproc;
1238 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1240 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1242 ptep = (pt_entry_t *)0;
1249 log_illegal_instruction(const char *msg, struct trapframe *frame)
1254 struct proc *p = curproc;
1258 printf("cpuid = %d\n", PCPU_GET(cpuid));
1260 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1261 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n",
1262 msg, p->p_pid, p->p_comm,
1263 p->p_ucred ? p->p_ucred->cr_uid : -1,
1265 (intmax_t)frame->ra);
1267 /* log registers in trap frame */
1268 log_frame_dump(frame);
1270 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1273 * Dump a few words around faulting instruction, if the addres is
1277 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1278 /* dump page table entry for faulting instruction */
1279 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n",
1280 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0);
1282 addr = (unsigned int *)(intptr_t)pc;
1283 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1285 log(LOG_ERR, "%08x %08x %08x %08x\n",
1286 addr[0], addr[1], addr[2], addr[3]);
1288 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n",
1289 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0);
1294 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1299 struct proc *p = curproc;
1300 char *read_or_write;
1303 trap_type &= ~T_USER;
1306 printf("cpuid = %d\n", PCPU_GET(cpuid));
1308 switch (trap_type) {
1311 read_or_write = "write";
1315 case T_BUS_ERR_IFETCH:
1316 read_or_write = "read";
1322 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1323 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n",
1324 msg, p->p_pid, p->p_comm,
1325 p->p_ucred ? p->p_ucred->cr_uid : -1,
1328 (intmax_t)frame->badvaddr);
1330 /* log registers in trap frame */
1331 log_frame_dump(frame);
1333 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1336 * Dump a few words around faulting instruction, if the addres is
1339 if (!(pc & 3) && (pc != frame->badvaddr) &&
1340 (trap_type != T_BUS_ERR_IFETCH) &&
1341 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1342 /* dump page table entry for faulting instruction */
1343 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n",
1344 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0);
1346 addr = (unsigned int *)(intptr_t)pc;
1347 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1349 log(LOG_ERR, "%08x %08x %08x %08x\n",
1350 addr[0], addr[1], addr[2], addr[3]);
1352 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n",
1353 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0);
1356 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1357 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#x\n",
1358 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, ptep ? *ptep : 0);
1363 * Unaligned load/store emulation
1366 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1368 register_t *reg = (register_t *) frame;
1369 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1370 register_t value_msb, value;
1374 * ADDR_ERR faults have higher priority than TLB
1375 * Miss faults. Therefore, it is necessary to
1376 * verify that the faulting address is a valid
1377 * virtual address within the process' address space
1378 * before trying to emulate the unaligned access.
1380 switch (MIPS_INST_OPCODE(inst)) {
1381 case OP_LHU: case OP_LH:
1385 case OP_LWU: case OP_LW:
1394 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1398 if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1403 * Handle LL/SC LLD/SCD.
1405 switch (MIPS_INST_OPCODE(inst)) {
1407 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1408 lbu_macro(value_msb, addr);
1410 lbu_macro(value, addr);
1411 value |= value_msb << 8;
1412 reg[MIPS_INST_RT(inst)] = value;
1413 return (MIPS_LHU_ACCESS);
1416 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1417 lb_macro(value_msb, addr);
1419 lbu_macro(value, addr);
1420 value |= value_msb << 8;
1421 reg[MIPS_INST_RT(inst)] = value;
1422 return (MIPS_LH_ACCESS);
1425 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1426 lwl_macro(value, addr);
1428 lwr_macro(value, addr);
1429 value &= 0xffffffff;
1430 reg[MIPS_INST_RT(inst)] = value;
1431 return (MIPS_LWU_ACCESS);
1434 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1435 lwl_macro(value, addr);
1437 lwr_macro(value, addr);
1438 reg[MIPS_INST_RT(inst)] = value;
1439 return (MIPS_LW_ACCESS);
1441 #if defined(__mips_n32) || defined(__mips_n64)
1443 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1444 ldl_macro(value, addr);
1446 ldr_macro(value, addr);
1447 reg[MIPS_INST_RT(inst)] = value;
1448 return (MIPS_LD_ACCESS);
1452 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1453 value = reg[MIPS_INST_RT(inst)];
1454 value_msb = value >> 8;
1455 sb_macro(value_msb, addr);
1457 sb_macro(value, addr);
1458 return (MIPS_SH_ACCESS);
1461 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1462 value = reg[MIPS_INST_RT(inst)];
1463 swl_macro(value, addr);
1465 swr_macro(value, addr);
1466 return (MIPS_SW_ACCESS);
1468 #if defined(__mips_n32) || defined(__mips_n64)
1470 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1471 value = reg[MIPS_INST_RT(inst)];
1472 sdl_macro(value, addr);
1474 sdr_macro(value, addr);
1475 return (MIPS_SD_ACCESS);
1478 panic("%s: should not be reached.", __func__);
1483 emulate_unaligned_access(struct trapframe *frame, int mode)
1486 int access_type = 0;
1488 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1491 * Fall through if it's instruction fetch exception
1493 if (!((pc & 3) || (pc == frame->badvaddr))) {
1496 * Handle unaligned load and store
1500 * Return access type if the instruction was emulated.
1501 * Otherwise restore pc and fall through.
1503 access_type = mips_unaligned_load_store(frame,
1504 mode, frame->badvaddr, pc);
1507 if (DELAYBRANCH(frame->cause))
1508 frame->pc = MipsEmulateBranch(frame, frame->pc,
1513 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1514 access_name[access_type - 1], (intmax_t)pc,
1515 (intmax_t)frame->badvaddr);