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>
96 SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
97 &trap_debug, 0, "Debug information on all traps");
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 **);
106 static void trap_frame_dump(struct trapframe *frame);
109 void (*machExceptionTable[]) (void)= {
111 * The kernel exception handlers.
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 */
146 * The user exception handlers.
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 */
182 char *trap_type[] = {
183 "external interrupt",
185 "TLB miss (load or instr. fetch)",
187 "address error (load or I-fetch)",
188 "address error (store)",
189 "bus error (I-fetch)",
190 "bus error (load or store)",
193 "reserved instruction",
194 "coprocessor unusable",
195 "arithmetic overflow",
197 "virtual coherency instruction",
214 "virtual coherency data",
217 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
218 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
221 #if defined(DDB) || defined(DEBUG)
222 void stacktrace(struct trapframe *);
223 void logstacktrace(struct trapframe *);
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)
230 * MIPS load/store access type
243 char *access_name[] = {
244 "Load Halfword Unsigned",
246 "Load Word Unsigned",
255 static int allow_unaligned_acc = 1;
257 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
258 &allow_unaligned_acc, 0, "Allow unaligned accesses");
260 static int emulate_unaligned_access(struct trapframe *frame, int mode);
262 extern void fswintrberr(void); /* XXX */
265 * Handle an exception.
266 * Called from MipsKernGenException() or MipsUserGenException()
267 * when a processor trap occurs.
268 * In the case of a kernel trap, we return the pc where to resume if
269 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
272 trap(struct trapframe *trapframe)
277 struct thread *td = curthread;
278 struct proc *p = curproc;
287 trapdebug_enter(trapframe, 0);
289 type = (trapframe->cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
290 if (TRAPF_USERMODE(trapframe)) {
298 * Enable hardware interrupts if they were on before the trap. If it
299 * was off disable all so we don't accidently enable it when doing a
300 * return to userland.
302 if (trapframe->sr & MIPS_SR_INT_IE) {
303 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
311 static vm_offset_t last_badvaddr = 0;
312 static vm_offset_t this_badvaddr = 0;
313 static int count = 0;
316 printf("trap type %x (%s - ", type,
317 trap_type[type & (~T_USER)]);
320 printf("user mode)\n");
322 printf("kernel mode)\n");
325 printf("cpuid = %d\n", PCPU_GET(cpuid));
327 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
328 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
329 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
330 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
331 (curproc ? curproc->p_pid : -1), pid);
333 switch (type & ~T_USER) {
339 this_badvaddr = trapframe->badvaddr;
342 this_badvaddr = trapframe->ra;
345 this_badvaddr = trapframe->pc;
348 if ((last_badvaddr == this_badvaddr) &&
349 ((type & ~T_USER) != T_SYSCALL)) {
351 trap_frame_dump(trapframe);
352 panic("too many faults at %p\n", (void *)last_badvaddr);
355 last_badvaddr = this_badvaddr;
363 kdb_trap(type, 0, trapframe);
368 /* check for kernel address */
369 if (KERNLAND(trapframe->badvaddr)) {
370 if (pmap_emulate_modified(kernel_pmap,
371 trapframe->badvaddr) != 0) {
372 ftype = VM_PROT_WRITE;
375 return (trapframe->pc);
379 case T_TLB_MOD + T_USER:
380 pmap = &p->p_vmspace->vm_pmap;
381 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
382 ftype = VM_PROT_WRITE;
386 return (trapframe->pc);
391 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
392 /* check for kernel address */
393 if (KERNLAND(trapframe->badvaddr)) {
398 va = trunc_page((vm_offset_t)trapframe->badvaddr);
399 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
400 if (rv == KERN_SUCCESS)
401 return (trapframe->pc);
402 if (td->td_pcb->pcb_onfault != NULL) {
403 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
404 td->td_pcb->pcb_onfault = NULL;
411 * It is an error for the kernel to access user space except
412 * through the copyin/copyout routines.
414 if (td->td_pcb->pcb_onfault == NULL)
417 /* check for fuswintr() or suswintr() getting a page fault */
418 /* XXX There must be a nicer way to do this. */
419 if (td->td_pcb->pcb_onfault == fswintrberr) {
420 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
421 td->td_pcb->pcb_onfault = NULL;
427 case T_TLB_LD_MISS + T_USER:
428 ftype = VM_PROT_READ;
431 case T_TLB_ST_MISS + T_USER:
432 ftype = VM_PROT_WRITE;
442 va = trunc_page((vm_offset_t)trapframe->badvaddr);
443 if (KERNLAND(trapframe->badvaddr)) {
445 * Don't allow user-mode faults in kernel
452 * Keep swapout from messing with us during this
459 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
465 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
466 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
467 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
470 if (rv == KERN_SUCCESS) {
472 return (trapframe->pc);
478 if (td->td_pcb->pcb_onfault != NULL) {
479 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
480 td->td_pcb->pcb_onfault = NULL;
486 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
487 addr = trapframe->pc;
489 msg = "BAD_PAGE_FAULT";
490 log_bad_page_fault(msg, trapframe, type);
495 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
496 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
497 if (trapframe->badvaddr < 0 ||
498 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
499 msg = "ADDRESS_SPACE_ERR";
500 } else if (allow_unaligned_acc) {
503 if (type == (T_ADDR_ERR_LD + T_USER))
506 mode = VM_PROT_WRITE;
508 access_type = emulate_unaligned_access(trapframe, mode);
509 if (access_type != 0)
511 msg = "ALIGNMENT_FIX_ERR";
518 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
519 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
520 ucode = 0; /* XXX should be VM_PROT_something */
522 addr = trapframe->pc;
525 log_bad_page_fault(msg, trapframe, type);
528 case T_SYSCALL + T_USER:
530 struct trapframe *locr0 = td->td_frame;
531 struct sysent *callp;
536 bzero(args, sizeof args);
539 * note: PCPU_LAZY_INC() can only be used if we can
540 * afford occassional inaccuracy in the count.
542 PCPU_LAZY_INC(cnt.v_syscall);
543 if (td->td_ucred != p->p_ucred)
544 cred_update_thread(td);
546 if (p->p_flag & P_SA)
547 thread_user_enter(td);
549 /* compute next PC after syscall instruction */
550 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
551 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
552 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
555 locr0->pc += sizeof(int);
560 #if defined(__mips_n32) || defined(__mips_n64)
563 * Quads fit in a single register in
571 * Code is first argument, followed by
579 #if defined(__mips_n32) || defined(__mips_n64)
588 #if defined(__mips_o32)
591 * Like syscall, but code is a quad, so as
592 * to maintain quad alignment for the rest
595 if (_QUAD_LOWWORD == 0) {
612 #if defined (__mips_n32) || defined(__mips_n64)
622 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
626 if (p->p_sysent->sv_mask)
627 code &= p->p_sysent->sv_mask;
629 if (code >= p->p_sysent->sv_size)
630 callp = &p->p_sysent->sv_table[0];
632 callp = &p->p_sysent->sv_table[code];
634 nargs = callp->sy_narg;
636 if (nargs > nsaved) {
637 #if defined(__mips_n32) || defined(__mips_n64)
640 * Is this right for new ABIs? I think the 4 there
641 * should be 8, size there are 8 registers to skip,
642 * not 4, but I'm not certain.
644 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
646 i = copyin((caddr_t)(intptr_t)(locr0->sp +
647 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
648 (u_int)(nargs - nsaved) * sizeof(register_t));
653 if (KTRPOINT(td, KTR_SYSCALL))
654 ktrsyscall(code, nargs, args);
661 for (i = 0; i < nargs; i++) {
662 printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
666 #ifdef SYSCALL_TRACING
667 printf("%s(", syscallnames[code]);
668 for (i = 0; i < nargs; i++) {
669 printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
674 if (KTRPOINT(td, KTR_SYSCALL))
675 ktrsyscall(code, nargs, args);
677 td->td_retval[0] = 0;
678 td->td_retval[1] = locr0->v1;
680 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
681 if (trp == trapdebug)
682 trapdebug[TRAPSIZE - 1].code = code;
686 STOPEVENT(p, S_SCE, nargs);
688 PTRACESTOP_SC(p, td, S_PT_SCE);
689 i = (*callp->sy_call) (td, args);
692 * Reinitialize proc pointer `p' as it may be
693 * different if this is a child returning from fork
697 locr0 = td->td_frame;
699 trapdebug_enter(locr0, -code);
700 cpu_set_syscall_retval(td, i);
703 * The sync'ing of I & D caches for SYS_ptrace() is
704 * done by procfs_domem() through procfs_rwmem()
705 * instead of being done here under a special check
710 * Check for misbehavior.
712 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
713 (code >= 0 && code < SYS_MAXSYSCALL) ?
714 syscallnames[code] : "???");
715 KASSERT(td->td_critnest == 0,
716 ("System call %s returning in a critical section",
717 (code >= 0 && code < SYS_MAXSYSCALL) ?
718 syscallnames[code] : "???"));
719 KASSERT(td->td_locks == 0,
720 ("System call %s returning with %d locks held",
721 (code >= 0 && code < SYS_MAXSYSCALL) ?
722 syscallnames[code] : "???",
724 userret(td, trapframe);
726 if (KTRPOINT(td, KTR_SYSRET))
727 ktrsysret(code, i, td->td_retval[0]);
730 * This works because errno is findable through the
731 * register set. If we ever support an emulation
732 * where this is not the case, this code will need
735 STOPEVENT(p, S_SCX, code);
737 PTRACESTOP_SC(p, td, S_PT_SCX);
739 mtx_assert(&Giant, MA_NOTOWNED);
740 return (trapframe->pc);
745 kdb_trap(type, 0, trapframe);
746 return (trapframe->pc);
749 case T_BREAK + T_USER:
754 /* compute address of break instruction */
756 if (DELAYBRANCH(trapframe->cause))
759 /* read break instruction */
760 instr = fuword32((caddr_t)va);
762 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
763 p->p_comm, p->p_pid, instr, trapframe->pc,
764 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
766 if (td->td_md.md_ss_addr != va ||
767 instr != MIPS_BREAK_SSTEP) {
769 addr = trapframe->pc;
773 * The restoration of the original instruction and
774 * the clearing of the berakpoint will be done later
775 * by the call to ptrace_clear_single_step() in
776 * issignal() when SIGTRAP is processed.
778 addr = trapframe->pc;
783 case T_IWATCH + T_USER:
784 case T_DWATCH + T_USER:
788 /* compute address of trapped instruction */
790 if (DELAYBRANCH(trapframe->cause))
792 printf("watch exception @ %p\n", (void *)va);
798 case T_TRAP + T_USER:
802 struct trapframe *locr0 = td->td_frame;
804 /* compute address of trap instruction */
806 if (DELAYBRANCH(trapframe->cause))
808 /* read break instruction */
809 instr = fuword32((caddr_t)va);
811 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
812 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
815 locr0->pc += sizeof(int);
818 i = SIGEMT; /* Stuff it with something for now */
822 case T_RES_INST + T_USER:
823 log_illegal_instruction("RES_INST", trapframe);
825 addr = trapframe->pc;
834 case T_COP_UNUSABLE + T_USER:
835 #if !defined(CPU_HAVEFPU)
836 /* FP (COP1) instruction */
837 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) {
838 log_illegal_instruction("COP1_UNUSABLE", trapframe);
843 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) {
844 log_illegal_instruction("COPn_UNUSABLE", trapframe);
845 i = SIGILL; /* only FPU instructions allowed */
848 addr = trapframe->pc;
849 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
850 PCPU_SET(fpcurthread, td);
851 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
852 td->td_md.md_flags |= MDTD_FPUSED;
856 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
859 printf("FPU Trap: PC %#jx CR %x SR %x\n",
860 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
865 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
868 case T_OVFLOW + T_USER:
870 addr = trapframe->pc;
873 case T_ADDR_ERR_LD: /* misaligned access */
874 case T_ADDR_ERR_ST: /* misaligned access */
877 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
878 (intmax_t)trapframe->badvaddr);
881 /* Only allow emulation on a user address */
882 if (allow_unaligned_acc &&
883 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
886 if (type == T_ADDR_ERR_LD)
889 mode = VM_PROT_WRITE;
891 access_type = emulate_unaligned_access(trapframe, mode);
892 if (access_type != 0)
893 return (trapframe->pc);
897 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
898 if (td->td_pcb->pcb_onfault != NULL) {
899 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
900 td->td_pcb->pcb_onfault = NULL;
909 #if !defined(SMP) && defined(DEBUG)
910 stacktrace(!usermode ? trapframe : td->td_frame);
914 printf("cpu:%d-", PCPU_GET(cpuid));
916 printf("Trap cause = %d (%s - ", type,
917 trap_type[type & (~T_USER)]);
920 printf("user mode)\n");
922 printf("kernel mode)\n");
926 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
927 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
928 (intmax_t)trapframe->sr);
932 if (debugger_on_panic || kdb_active) {
933 kdb_trap(type, 0, trapframe);
938 td->td_frame->pc = trapframe->pc;
939 td->td_frame->cause = trapframe->cause;
940 td->td_frame->badvaddr = trapframe->badvaddr;
941 ksiginfo_init_trap(&ksi);
943 ksi.ksi_code = ucode;
944 ksi.ksi_addr = (void *)addr;
945 ksi.ksi_trapno = type;
946 trapsignal(td, &ksi);
950 * Note: we should only get here if returning to user mode.
952 userret(td, trapframe);
953 mtx_assert(&Giant, MA_NOTOWNED);
954 return (trapframe->pc);
957 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
965 printf("trapDump(%s)\n", msg);
966 for (i = 0; i < TRAPSIZE; i++) {
967 if (trp == trapdebug) {
968 trp = &trapdebug[TRAPSIZE - 1];
976 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
977 trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >>
978 MIPS_CR_EXC_CODE_SHIFT],
979 (intmax_t)trp->vadr, (intmax_t)trp->pc,
980 (intmax_t)trp->cause, (intmax_t)trp->status);
982 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
983 (intmax_t)trp->sp, (int)trp->code);
991 * Return the resulting PC as if the branch was executed.
994 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
998 register_t *regsPtr = (register_t *) framePtr;
999 uintptr_t retAddr = 0;
1002 #define GetBranchDest(InstPtr, inst) \
1003 (InstPtr + 4 + ((short)inst.IType.imm << 2))
1007 if (instptr < MIPS_KSEG0_START)
1008 inst.word = fuword32((void *)instptr);
1010 inst = *(InstFmt *) instptr;
1012 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1013 inst.word = fuword32((void *)instPC);
1015 inst = *(InstFmt *) instPC;
1018 switch ((int)inst.JType.op) {
1020 switch ((int)inst.RType.func) {
1023 retAddr = regsPtr[inst.RType.rs];
1027 retAddr = instPC + 4;
1033 switch ((int)inst.IType.rt) {
1038 if ((int)(regsPtr[inst.RType.rs]) < 0)
1039 retAddr = GetBranchDest(instPC, inst);
1041 retAddr = instPC + 8;
1048 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1049 retAddr = GetBranchDest(instPC, inst);
1051 retAddr = instPC + 8;
1060 retAddr = instPC + 4; /* Like syscall... */
1064 panic("MipsEmulateBranch: Bad branch cond");
1070 retAddr = (inst.JType.target << 2) |
1071 ((unsigned)(instPC + 4) & 0xF0000000);
1076 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1077 retAddr = GetBranchDest(instPC, inst);
1079 retAddr = instPC + 8;
1084 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1085 retAddr = GetBranchDest(instPC, inst);
1087 retAddr = instPC + 8;
1092 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1093 retAddr = GetBranchDest(instPC, inst);
1095 retAddr = instPC + 8;
1100 if ((int)(regsPtr[inst.RType.rs]) > 0)
1101 retAddr = GetBranchDest(instPC, inst);
1103 retAddr = instPC + 8;
1107 switch (inst.RType.rs) {
1110 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1111 condition = fpcCSR & MIPS_FPU_COND_BIT;
1113 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1115 retAddr = GetBranchDest(instPC, inst);
1117 retAddr = instPC + 8;
1121 retAddr = instPC + 4;
1126 retAddr = instPC + 4;
1132 #if defined(DDB) || defined(DEBUG)
1134 * Print a stack backtrace.
1137 stacktrace(struct trapframe *regs)
1139 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1144 log_frame_dump(struct trapframe *frame)
1146 log(LOG_ERR, "Trapframe Register Dump:\n");
1147 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1148 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1150 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1151 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1153 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1154 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1156 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1157 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1159 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1160 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1162 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1163 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1165 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1166 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1168 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1169 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1171 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1172 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1175 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1176 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1178 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1179 (intmax_t)frame->cause, (intmax_t)frame->pc);
1185 trap_frame_dump(struct trapframe *frame)
1187 printf("Trapframe Register Dump:\n");
1188 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1189 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1191 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1192 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1194 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1195 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1197 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1198 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1200 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1201 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1203 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1204 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1206 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1207 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1209 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1210 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1212 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1213 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1216 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1217 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1219 printf("\tcause: %#jx\tpc: %#jx\n",
1220 (intmax_t)frame->cause, (intmax_t)frame->pc);
1228 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1232 struct proc *p = curproc;
1234 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1236 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1238 ptep = (pt_entry_t *)0;
1245 log_illegal_instruction(const char *msg, struct trapframe *frame)
1250 struct proc *p = curproc;
1254 printf("cpuid = %d\n", PCPU_GET(cpuid));
1256 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1257 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n",
1258 msg, p->p_pid, p->p_comm,
1259 p->p_ucred ? p->p_ucred->cr_uid : -1,
1261 (intmax_t)frame->ra);
1263 /* log registers in trap frame */
1264 log_frame_dump(frame);
1266 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1269 * Dump a few words around faulting instruction, if the addres is
1273 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1274 /* dump page table entry for faulting instruction */
1275 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1276 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1278 addr = (unsigned int *)(intptr_t)pc;
1279 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1281 log(LOG_ERR, "%08x %08x %08x %08x\n",
1282 addr[0], addr[1], addr[2], addr[3]);
1284 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1285 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1290 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1295 struct proc *p = curproc;
1296 char *read_or_write;
1299 trap_type &= ~T_USER;
1302 printf("cpuid = %d\n", PCPU_GET(cpuid));
1304 switch (trap_type) {
1307 read_or_write = "write";
1311 case T_BUS_ERR_IFETCH:
1312 read_or_write = "read";
1318 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1319 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n",
1320 msg, p->p_pid, p->p_comm,
1321 p->p_ucred ? p->p_ucred->cr_uid : -1,
1324 (intmax_t)frame->badvaddr);
1326 /* log registers in trap frame */
1327 log_frame_dump(frame);
1329 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1332 * Dump a few words around faulting instruction, if the addres is
1335 if (!(pc & 3) && (pc != frame->badvaddr) &&
1336 (trap_type != T_BUS_ERR_IFETCH) &&
1337 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1338 /* dump page table entry for faulting instruction */
1339 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1340 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1342 addr = (unsigned int *)(intptr_t)pc;
1343 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1345 log(LOG_ERR, "%08x %08x %08x %08x\n",
1346 addr[0], addr[1], addr[2], addr[3]);
1348 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1349 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1352 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1353 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1354 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1359 * Unaligned load/store emulation
1362 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1364 register_t *reg = (register_t *) frame;
1365 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1366 register_t value_msb, value;
1370 * ADDR_ERR faults have higher priority than TLB
1371 * Miss faults. Therefore, it is necessary to
1372 * verify that the faulting address is a valid
1373 * virtual address within the process' address space
1374 * before trying to emulate the unaligned access.
1376 switch (MIPS_INST_OPCODE(inst)) {
1377 case OP_LHU: case OP_LH:
1381 case OP_LWU: case OP_LW:
1390 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1394 if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1399 * Handle LL/SC LLD/SCD.
1401 switch (MIPS_INST_OPCODE(inst)) {
1403 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1404 lbu_macro(value_msb, addr);
1406 lbu_macro(value, addr);
1407 value |= value_msb << 8;
1408 reg[MIPS_INST_RT(inst)] = value;
1409 return (MIPS_LHU_ACCESS);
1412 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1413 lb_macro(value_msb, addr);
1415 lbu_macro(value, addr);
1416 value |= value_msb << 8;
1417 reg[MIPS_INST_RT(inst)] = value;
1418 return (MIPS_LH_ACCESS);
1421 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1422 lwl_macro(value, addr);
1424 lwr_macro(value, addr);
1425 value &= 0xffffffff;
1426 reg[MIPS_INST_RT(inst)] = value;
1427 return (MIPS_LWU_ACCESS);
1430 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1431 lwl_macro(value, addr);
1433 lwr_macro(value, addr);
1434 reg[MIPS_INST_RT(inst)] = value;
1435 return (MIPS_LW_ACCESS);
1437 #if defined(__mips_n32) || defined(__mips_n64)
1439 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1440 ldl_macro(value, addr);
1442 ldr_macro(value, addr);
1443 reg[MIPS_INST_RT(inst)] = value;
1444 return (MIPS_LD_ACCESS);
1448 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1449 value = reg[MIPS_INST_RT(inst)];
1450 value_msb = value >> 8;
1451 sb_macro(value_msb, addr);
1453 sb_macro(value, addr);
1454 return (MIPS_SH_ACCESS);
1457 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1458 value = reg[MIPS_INST_RT(inst)];
1459 swl_macro(value, addr);
1461 swr_macro(value, addr);
1462 return (MIPS_SW_ACCESS);
1464 #if defined(__mips_n32) || defined(__mips_n64)
1466 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1467 value = reg[MIPS_INST_RT(inst)];
1468 sdl_macro(value, addr);
1470 sdr_macro(value, addr);
1471 return (MIPS_SD_ACCESS);
1474 panic("%s: should not be reached.", __func__);
1479 emulate_unaligned_access(struct trapframe *frame, int mode)
1482 int access_type = 0;
1484 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1487 * Fall through if it's instruction fetch exception
1489 if (!((pc & 3) || (pc == frame->badvaddr))) {
1492 * Handle unaligned load and store
1496 * Return access type if the instruction was emulated.
1497 * Otherwise restore pc and fall through.
1499 access_type = mips_unaligned_load_store(frame,
1500 mode, frame->badvaddr, pc);
1503 if (DELAYBRANCH(frame->cause))
1504 frame->pc = MipsEmulateBranch(frame, frame->pc,
1509 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1510 access_name[access_type - 1], (intmax_t)pc,
1511 (intmax_t)frame->badvaddr);