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"
47 #define NO_REG_DEFS 1 /* Prevent asm.h from including regdef.h */
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/sysent.h>
52 #include <sys/kernel.h>
53 #include <sys/signalvar.h>
54 #include <sys/syscall.h>
57 #include <vm/vm_extern.h>
58 #include <vm/vm_kern.h>
59 #include <vm/vm_page.h>
60 #include <vm/vm_map.h>
61 #include <vm/vm_param.h>
62 #include <sys/vmmeter.h>
63 #include <sys/ptrace.h>
66 #include <sys/vnode.h>
67 #include <sys/pioctl.h>
68 #include <sys/sysctl.h>
69 #include <sys/syslog.h>
72 #include <sys/ktrace.h>
74 #include <net/netisr.h>
76 #include <machine/trap.h>
77 #include <machine/psl.h>
78 #include <machine/cpu.h>
79 #include <machine/intr.h>
80 #include <machine/pte.h>
81 #include <machine/pmap.h>
82 #include <machine/mips_opcode.h>
83 #include <machine/frame.h>
84 #include <machine/regnum.h>
85 #include <machine/rm7000.h>
86 #include <machine/archtype.h>
87 #include <machine/asm.h>
90 #include <machine/db_machdep.h>
91 #include <ddb/db_sym.h>
96 #include <sys/cdefs.h>
97 #include <sys/syslog.h>
105 extern unsigned onfault_table[];
107 extern void MipsKernGenException(void);
108 extern void MipsUserGenException(void);
109 extern void MipsKernIntr(void);
110 extern void MipsUserIntr(void);
111 extern void MipsTLBInvalidException(void);
112 extern void MipsKernTLBInvalidException(void);
113 extern void MipsUserTLBInvalidException(void);
114 extern void MipsTLBMissException(void);
115 static void log_bad_page_fault(char *, struct trapframe *, int);
116 static void log_frame_dump(struct trapframe *frame);
117 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
120 static void trap_frame_dump(struct trapframe *frame);
125 void (*machExceptionTable[]) (void)= {
127 * The kernel exception handlers.
129 MipsKernIntr, /* external interrupt */
130 MipsKernGenException, /* TLB modification */
131 MipsKernTLBInvalidException, /* TLB miss (load or instr. fetch) */
132 MipsKernTLBInvalidException, /* TLB miss (store) */
133 MipsKernGenException, /* address error (load or I-fetch) */
134 MipsKernGenException, /* address error (store) */
135 MipsKernGenException, /* bus error (I-fetch) */
136 MipsKernGenException, /* bus error (load or store) */
137 MipsKernGenException, /* system call */
138 MipsKernGenException, /* breakpoint */
139 MipsKernGenException, /* reserved instruction */
140 MipsKernGenException, /* coprocessor unusable */
141 MipsKernGenException, /* arithmetic overflow */
142 MipsKernGenException, /* trap exception */
143 MipsKernGenException, /* virtual coherence exception inst */
144 MipsKernGenException, /* floating point exception */
145 MipsKernGenException, /* reserved */
146 MipsKernGenException, /* reserved */
147 MipsKernGenException, /* reserved */
148 MipsKernGenException, /* reserved */
149 MipsKernGenException, /* reserved */
150 MipsKernGenException, /* reserved */
151 MipsKernGenException, /* reserved */
152 MipsKernGenException, /* watch exception */
153 MipsKernGenException, /* reserved */
154 MipsKernGenException, /* reserved */
155 MipsKernGenException, /* reserved */
156 MipsKernGenException, /* reserved */
157 MipsKernGenException, /* reserved */
158 MipsKernGenException, /* reserved */
159 MipsKernGenException, /* reserved */
160 MipsKernGenException, /* virtual coherence exception data */
162 * The user exception handlers.
164 MipsUserIntr, /* 0 */
165 MipsUserGenException, /* 1 */
166 MipsUserTLBInvalidException, /* 2 */
167 MipsUserTLBInvalidException, /* 3 */
168 MipsUserGenException, /* 4 */
169 MipsUserGenException, /* 5 */
170 MipsUserGenException, /* 6 */
171 MipsUserGenException, /* 7 */
172 MipsUserGenException, /* 8 */
173 MipsUserGenException, /* 9 */
174 MipsUserGenException, /* 10 */
175 MipsUserGenException, /* 11 */
176 MipsUserGenException, /* 12 */
177 MipsUserGenException, /* 13 */
178 MipsUserGenException, /* 14 */
179 MipsUserGenException, /* 15 */
180 MipsUserGenException, /* 16 */
181 MipsUserGenException, /* 17 */
182 MipsUserGenException, /* 18 */
183 MipsUserGenException, /* 19 */
184 MipsUserGenException, /* 20 */
185 MipsUserGenException, /* 21 */
186 MipsUserGenException, /* 22 */
187 MipsUserGenException, /* 23 */
188 MipsUserGenException, /* 24 */
189 MipsUserGenException, /* 25 */
190 MipsUserGenException, /* 26 */
191 MipsUserGenException, /* 27 */
192 MipsUserGenException, /* 28 */
193 MipsUserGenException, /* 29 */
194 MipsUserGenException, /* 20 */
195 MipsUserGenException, /* 31 */
198 char *trap_type[] = {
199 "external interrupt",
201 "TLB miss (load or instr. fetch)",
203 "address error (load or I-fetch)",
204 "address error (store)",
205 "bus error (I-fetch)",
206 "bus error (load or store)",
209 "reserved instruction",
210 "coprocessor unusable",
211 "arithmetic overflow",
213 "virtual coherency instruction",
230 "virtual coherency data",
233 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
234 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
238 #if defined(DDB) || defined(DEBUG)
239 void stacktrace(struct trapframe *);
240 void logstacktrace(struct trapframe *);
243 /* extern functions printed by name in stack backtraces */
244 extern void MipsTLBMiss(void);
245 extern void MipsUserSyscallException(void);
246 extern char _locore[];
247 extern char _locoreEnd[];
249 #endif /* DDB || DEBUG */
251 extern void MipsSwitchFPState(struct thread *, struct trapframe *);
252 extern void MipsFPTrap(u_int, u_int, u_int);
254 u_int trap(struct trapframe *);
255 u_int MipsEmulateBranch(struct trapframe *, int, int, u_int);
257 #define KERNLAND(x) ((int)(x) < 0)
258 #define DELAYBRANCH(x) ((int)(x) < 0)
261 * kdbpeekD(addr) - skip one word starting at 'addr', then read the second word
263 #define kdbpeekD(addr) kdbpeek(((int *)(addr)) + 1)
267 * MIPS load/store access type
280 char *access_name[] = {
281 "Load Halfword Unsigned",
283 "Load Word Unsigned",
292 static int allow_unaligned_acc = 1;
294 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
295 &allow_unaligned_acc, 0, "Allow unaligned accesses");
297 static int emulate_unaligned_access(struct trapframe *frame);
299 extern char *syscallnames[];
302 * Handle an exception.
303 * Called from MipsKernGenException() or MipsUserGenException()
304 * when a processor trap occurs.
305 * In the case of a kernel trap, we return the pc where to resume if
306 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
310 struct trapframe *trapframe;
315 struct thread *td = curthread;
316 struct proc *p = curproc;
321 int quad_syscall = 0;
327 trapdebug_enter(trapframe, 0);
329 type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
330 if (USERMODE(trapframe->sr)) {
338 * Enable hardware interrupts if they were on before the trap. If it
339 * was off disable all so we don't accidently enable it when doing a
340 * return to userland.
342 if (trapframe->sr & SR_INT_ENAB) {
343 set_intr_mask(~(trapframe->sr & ALL_INT_MASK));
351 static vm_offset_t last_badvaddr = 0;
352 static vm_offset_t this_badvaddr = 0;
353 static int count = 0;
356 printf("trap type %x (%s - ", type,
357 trap_type[type & (~T_USER)]);
360 printf("user mode)\n");
362 printf("kernel mode)\n");
365 printf("cpuid = %d\n", PCPU_GET(cpuid));
368 printf("badaddr = %p, pc = %p, ra = %p, sp = %p, sr = 0x%x, pid = %d, ASID = 0x%x\n",
369 trapframe->badvaddr, trapframe->pc, trapframe->ra,
370 trapframe->sp, trapframe->sr,
371 (curproc ? curproc->p_pid : -1), pid);
373 switch (type & ~T_USER) {
379 this_badvaddr = trapframe->badvaddr;
382 this_badvaddr = trapframe->ra;
385 this_badvaddr = trapframe->pc;
388 if ((last_badvaddr == this_badvaddr) &&
389 ((type & ~T_USER) != T_SYSCALL)) {
391 trap_frame_dump(trapframe);
392 panic("too many faults at %p\n", last_badvaddr);
395 last_badvaddr = this_badvaddr;
403 kdb_trap(type, 0, trapframe);
408 /* check for kernel address */
409 if (KERNLAND(trapframe->badvaddr)) {
412 PMAP_LOCK(kernel_pmap);
413 if (!(pte = pmap_segmap(kernel_pmap,
414 trapframe->badvaddr)))
415 panic("trap: ktlbmod: invalid segmap");
416 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
419 /* It is possible that some other CPU changed m-bit */
420 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
421 trapframe->badvaddr &= ~PGOFSET;
422 pmap_update_page(kernel_pmap,
423 trapframe->badvaddr, entry);
424 PMAP_UNLOCK(kernel_pmap);
425 return (trapframe->pc);
428 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
429 panic("trap: ktlbmod: invalid pte");
431 if (entry & mips_pg_ro_bit()) {
432 /* write to read only page in the kernel */
433 ftype = VM_PROT_WRITE;
434 PMAP_UNLOCK(kernel_pmap);
437 entry |= mips_pg_m_bit();
439 trapframe->badvaddr &= ~PGOFSET;
440 pmap_update_page(kernel_pmap, trapframe->badvaddr, entry);
441 pa = mips_tlbpfn_to_paddr(entry);
442 if (!page_is_managed(pa))
443 panic("trap: ktlbmod: unmanaged page");
444 pmap_set_modified(pa);
445 PMAP_UNLOCK(kernel_pmap);
446 return (trapframe->pc);
450 case T_TLB_MOD + T_USER:
454 pmap = &p->p_vmspace->vm_pmap;
457 if (!(pte = pmap_segmap(pmap, trapframe->badvaddr)))
458 panic("trap: utlbmod: invalid segmap");
459 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
462 /* It is possible that some other CPU changed m-bit */
463 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
464 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
465 pmap_update_page(pmap, trapframe->badvaddr, entry);
470 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
471 panic("trap: utlbmod: invalid pte");
475 if (entry & mips_pg_ro_bit()) {
476 /* write to read only page */
477 ftype = VM_PROT_WRITE;
481 entry |= mips_pg_m_bit();
483 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
484 pmap_update_page(pmap, trapframe->badvaddr, entry);
485 trapframe->badvaddr |= (pmap->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT);
486 pa = mips_tlbpfn_to_paddr(entry);
487 if (!page_is_managed(pa))
488 panic("trap: utlbmod: unmanaged page");
489 pmap_set_modified(pa);
493 return (trapframe->pc);
500 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
501 /* check for kernel address */
502 if (KERNLAND(trapframe->badvaddr)) {
507 va = trunc_page((vm_offset_t)trapframe->badvaddr);
508 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
509 if (rv == KERN_SUCCESS)
510 return (trapframe->pc);
511 if ((i = td->td_pcb->pcb_onfault) != 0) {
512 td->td_pcb->pcb_onfault = 0;
513 return (onfault_table[i]);
518 * It is an error for the kernel to access user space except
519 * through the copyin/copyout routines.
521 if ((i = td->td_pcb->pcb_onfault) == 0)
523 /* check for fuswintr() or suswintr() getting a page fault */
525 return (onfault_table[i]);
529 case T_TLB_LD_MISS + T_USER:
530 ftype = VM_PROT_READ;
533 case T_TLB_ST_MISS + T_USER:
534 ftype = VM_PROT_WRITE;
545 va = trunc_page((vm_offset_t)trapframe->badvaddr);
546 if ((vm_offset_t)trapframe->badvaddr < VM_MIN_KERNEL_ADDRESS) {
547 if (ftype & VM_PROT_WRITE)
548 flag = VM_FAULT_DIRTY;
550 flag = VM_FAULT_NORMAL;
553 * Don't allow user-mode faults in kernel
560 * Keep swapout from messing with us during this
567 rv = vm_fault(map, va, ftype, flag);
573 printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
574 map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, flag,
578 if (rv == KERN_SUCCESS) {
580 return (trapframe->pc);
586 if ((i = td->td_pcb->pcb_onfault) != 0) {
587 td->td_pcb->pcb_onfault = 0;
588 return (onfault_table[i]);
593 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
594 addr = trapframe->pc;
596 msg = "BAD_PAGE_FAULT";
597 log_bad_page_fault(msg, trapframe, type);
602 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
603 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
604 if (allow_unaligned_acc) {
607 if (type == (T_ADDR_ERR_LD + T_USER))
610 mode = VM_PROT_WRITE;
613 * ADDR_ERR faults have higher priority than TLB
614 * Miss faults. Therefore, it is necessary to
615 * verify that the faulting address is a valid
616 * virtual address within the process' address space
617 * before trying to emulate the unaligned access.
619 if (useracc((caddr_t)
620 (((vm_offset_t)trapframe->badvaddr) &
621 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
622 access_type = emulate_unaligned_access(
624 if (access_type != 0)
632 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
633 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
634 ucode = 0; /* XXX should be VM_PROT_something */
636 addr = trapframe->pc;
639 log_bad_page_fault(msg, trapframe, type);
642 case T_SYSCALL + T_USER:
644 struct trapframe *locr0 = td->td_frame;
645 struct sysent *callp;
652 * note: PCPU_LAZY_INC() can only be used if we can
653 * afford occassional inaccuracy in the count.
655 PCPU_LAZY_INC(cnt.v_syscall);
656 if (td->td_ucred != p->p_ucred)
657 cred_update_thread(td);
659 if (p->p_flag & P_SA)
660 thread_user_enter(td);
662 /* compute next PC after syscall instruction */
663 tpc = trapframe->pc; /* Remember if restart */
664 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
665 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
668 locr0->pc += sizeof(int);
675 * Code is first argument, followed by
687 * Like syscall, but code is a quad, so as
688 * to maintain quad alignment for the rest
691 if (_QUAD_LOWWORD == 0) {
710 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
713 if (p->p_sysent->sv_mask)
714 code &= p->p_sysent->sv_mask;
716 if (code >= p->p_sysent->sv_size)
717 callp = &p->p_sysent->sv_table[0];
719 callp = &p->p_sysent->sv_table[code];
721 nargs = callp->sy_narg;
723 if (nargs > nsaved) {
724 i = copyin((caddr_t)(locr0->sp +
725 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
726 (u_int)(nargs - nsaved) * sizeof(register_t));
731 if (KTRPOINT(td, KTR_SYSCALL))
732 ktrsyscall(code, nargs, args);
738 if (KTRPOINT(td, KTR_SYSCALL))
739 ktrsyscall(code, nargs, args);
741 td->td_retval[0] = 0;
742 td->td_retval[1] = locr0->v1;
744 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
745 if (trp == trapdebug)
746 trapdebug[TRAPSIZE - 1].code = code;
750 STOPEVENT(p, S_SCE, nargs);
752 PTRACESTOP_SC(p, td, S_PT_SCE);
753 i = (*callp->sy_call) (td, args);
756 * Reinitialize proc pointer `p' as it may be
757 * different if this is a child returning from fork
761 locr0 = td->td_frame;
763 trapdebug_enter(locr0, -code);
766 if (quad_syscall && code != SYS_lseek) {
768 * System call invoked through the
769 * SYS___syscall interface but the
770 * return value is really just 32
773 locr0->v0 = td->td_retval[0];
775 locr0->v1 = td->td_retval[0];
778 locr0->v0 = td->td_retval[0];
779 locr0->v1 = td->td_retval[1];
789 break; /* nothing to do */
792 if (quad_syscall && code != SYS_lseek) {
804 * The sync'ing of I & D caches for SYS_ptrace() is
805 * done by procfs_domem() through procfs_rwmem()
806 * instead of being done here under a special check
811 * Check for misbehavior.
813 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
814 (code >= 0 && code < SYS_MAXSYSCALL) ?
815 syscallnames[code] : "???");
816 KASSERT(td->td_critnest == 0,
817 ("System call %s returning in a critical section",
818 (code >= 0 && code < SYS_MAXSYSCALL) ?
819 syscallnames[code] : "???"));
820 KASSERT(td->td_locks == 0,
821 ("System call %s returning with %d locks held",
822 (code >= 0 && code < SYS_MAXSYSCALL) ?
823 syscallnames[code] : "???",
825 userret(td, trapframe);
827 if (KTRPOINT(p, KTR_SYSRET))
828 ktrsysret(code, i, td->td_retval[0]);
831 * This works because errno is findable through the
832 * register set. If we ever support an emulation
833 * where this is not the case, this code will need
836 STOPEVENT(p, S_SCX, code);
838 PTRACESTOP_SC(p, td, S_PT_SCX);
840 mtx_assert(&Giant, MA_NOTOWNED);
841 return (trapframe->pc);
846 kdb_trap(type, 0, trapframe);
847 return (trapframe->pc);
850 case T_BREAK + T_USER:
852 unsigned int va, instr;
854 /* compute address of break instruction */
856 if (DELAYBRANCH(trapframe->cause))
859 /* read break instruction */
860 instr = fuword((caddr_t)va);
862 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
863 p->p_comm, p->p_pid, instr, trapframe->pc,
864 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
866 if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
868 addr = trapframe->pc;
872 * The restoration of the original instruction and
873 * the clearing of the berakpoint will be done later
874 * by the call to ptrace_clear_single_step() in
875 * issignal() when SIGTRAP is processed.
877 addr = trapframe->pc;
882 case T_IWATCH + T_USER:
883 case T_DWATCH + T_USER:
887 /* compute address of trapped instruction */
889 if (DELAYBRANCH(trapframe->cause))
891 printf("watch exception @ 0x%x\n", va);
897 case T_TRAP + T_USER:
899 unsigned int va, instr;
900 struct trapframe *locr0 = td->td_frame;
902 /* compute address of trap instruction */
904 if (DELAYBRANCH(trapframe->cause))
906 /* read break instruction */
907 instr = fuword((caddr_t)va);
909 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
910 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
913 locr0->pc += sizeof(int);
916 i = SIGEMT; /* Stuff it with something for now */
920 case T_RES_INST + T_USER:
922 addr = trapframe->pc;
931 case T_COP_UNUSABLE + T_USER:
932 #if defined(SOFTFLOAT)
933 /* FP (COP1) instruction */
934 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
939 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
940 i = SIGILL; /* only FPU instructions allowed */
943 addr = trapframe->pc;
944 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
945 PCPU_SET(fpcurthread, td);
946 td->td_frame->sr |= SR_COP_1_BIT;
947 td->td_md.md_flags |= MDTD_FPUSED;
951 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
954 printf("FPU Trap: PC %x CR %x SR %x\n",
955 trapframe->pc, trapframe->cause, trapframe->sr);
960 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
963 case T_OVFLOW + T_USER:
965 addr = trapframe->pc;
968 case T_ADDR_ERR_LD: /* misaligned access */
969 case T_ADDR_ERR_ST: /* misaligned access */
971 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
972 trapframe->badvaddr);
974 /* Only allow emulation on a user address */
975 if (allow_unaligned_acc &&
976 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
979 if (type == T_ADDR_ERR_LD)
982 mode = VM_PROT_WRITE;
985 * ADDR_ERR faults have higher priority than TLB
986 * Miss faults. Therefore, it is necessary to
987 * verify that the faulting address is a valid
988 * virtual address within the process' address space
989 * before trying to emulate the unaligned access.
991 if (useracc((caddr_t)
992 (((vm_offset_t)trapframe->badvaddr) &
993 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
994 access_type = emulate_unaligned_access(
996 if (access_type != 0) {
997 return (trapframe->pc);
1003 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
1004 if ((i = td->td_pcb->pcb_onfault) != 0) {
1005 td->td_pcb->pcb_onfault = 0;
1006 return (onfault_table[i]);
1013 #if !defined(SMP) && defined(DEBUG)
1014 stacktrace(!usermode ? trapframe : td->td_frame);
1018 printf("cpu:%d-", PCPU_GET(cpuid));
1020 printf("Trap cause = %d (%s - ", type,
1021 trap_type[type & (~T_USER)]);
1024 printf("user mode)\n");
1026 printf("kernel mode)\n");
1029 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
1030 trapframe->badvaddr, trapframe->pc, trapframe->ra,
1035 if (debugger_on_panic || kdb_active) {
1036 kdb_trap(type, 0, trapframe);
1041 td->td_frame->pc = trapframe->pc;
1042 td->td_frame->cause = trapframe->cause;
1043 td->td_frame->badvaddr = trapframe->badvaddr;
1044 ksiginfo_init_trap(&ksi);
1046 ksi.ksi_code = ucode;
1047 ksi.ksi_addr = (void *)addr;
1048 ksi.ksi_trapno = type;
1049 trapsignal(td, &ksi);
1053 * Note: we should only get here if returning to user mode.
1055 userret(td, trapframe);
1056 mtx_assert(&Giant, MA_NOTOWNED);
1057 return (trapframe->pc);
1060 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1067 printf("trapDump(%s)\n", msg);
1068 for (i = 0; i < TRAPSIZE; i++) {
1069 if (trp == trapdebug) {
1070 trp = &trapdebug[TRAPSIZE - 1];
1075 if (trp->cause == 0)
1078 printf("%s: ADR %x PC %x CR %x SR %x\n",
1079 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
1080 trp->vadr, trp->pc, trp->cause, trp->status);
1082 printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
1091 * Return the resulting PC as if the branch was executed.
1094 MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR,
1098 register_t *regsPtr = (register_t *) framePtr;
1099 unsigned retAddr = 0;
1102 #define GetBranchDest(InstPtr, inst) \
1103 ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
1107 if (instptr < MIPS_KSEG0_START)
1108 inst.word = fuword((void *)instptr);
1110 inst = *(InstFmt *) instptr;
1112 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1113 inst.word = fuword((void *)instPC);
1115 inst = *(InstFmt *) instPC;
1118 switch ((int)inst.JType.op) {
1120 switch ((int)inst.RType.func) {
1123 retAddr = regsPtr[inst.RType.rs];
1127 retAddr = instPC + 4;
1133 switch ((int)inst.IType.rt) {
1138 if ((int)(regsPtr[inst.RType.rs]) < 0)
1139 retAddr = GetBranchDest(instPC, inst);
1141 retAddr = instPC + 8;
1148 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1149 retAddr = GetBranchDest(instPC, inst);
1151 retAddr = instPC + 8;
1160 retAddr = instPC + 4; /* Like syscall... */
1164 panic("MipsEmulateBranch: Bad branch cond");
1170 retAddr = (inst.JType.target << 2) |
1171 ((unsigned)instPC & 0xF0000000);
1176 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1177 retAddr = GetBranchDest(instPC, inst);
1179 retAddr = instPC + 8;
1184 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1185 retAddr = GetBranchDest(instPC, inst);
1187 retAddr = instPC + 8;
1192 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1193 retAddr = GetBranchDest(instPC, inst);
1195 retAddr = instPC + 8;
1200 if ((int)(regsPtr[inst.RType.rs]) > 0)
1201 retAddr = GetBranchDest(instPC, inst);
1203 retAddr = instPC + 8;
1207 switch (inst.RType.rs) {
1210 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1211 condition = fpcCSR & FPC_COND_BIT;
1213 condition = !(fpcCSR & FPC_COND_BIT);
1215 retAddr = GetBranchDest(instPC, inst);
1217 retAddr = instPC + 8;
1221 retAddr = instPC + 4;
1226 retAddr = instPC + 4;
1232 #if defined(DDB) || defined(DEBUG)
1233 #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
1236 char *fn_name(unsigned addr);
1239 * Print a stack backtrace.
1242 stacktrace(struct trapframe *regs)
1244 stacktrace_subr(regs, printf);
1248 stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...))
1251 unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr;
1252 unsigned instr, mask;
1253 unsigned int frames = 0;
1256 /* get initial values from the exception frame */
1260 ra = regs->ra; /* May be a 'leaf' function */
1266 /* Jump here when done with a frame, to start a new one */
1269 /* Jump here after a nonstandard (interrupt handler) frame */
1272 if (frames++ > 100) {
1273 (*printfn) ("\nstackframe count exceeded\n");
1274 /* return breaks stackframe-size heuristics with gcc -O2 */
1275 goto finish; /* XXX */
1277 /* check for bad SP: could foul up next frame */
1278 if (sp & 3 || sp < 0x80000000) {
1279 (*printfn) ("SP 0x%x: not in kernel\n", sp);
1284 #define Between(x, y, z) \
1285 ( ((x) <= (y)) && ((y) < (z)) )
1286 #define pcBetween(a,b) \
1287 Between((unsigned)a, pc, (unsigned)b)
1290 * Check for current PC in exception handler code that don't have a
1291 * preceding "j ra" at the tail of the preceding function. Depends
1292 * on relative ordering of functions in exception.S, swtch.S.
1294 if (pcBetween(MipsKernGenException, MipsUserGenException))
1295 subr = (unsigned)MipsKernGenException;
1296 else if (pcBetween(MipsUserGenException, MipsKernIntr))
1297 subr = (unsigned)MipsUserGenException;
1298 else if (pcBetween(MipsKernIntr, MipsUserIntr))
1299 subr = (unsigned)MipsKernIntr;
1300 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
1301 subr = (unsigned)MipsUserIntr;
1302 else if (pcBetween(MipsTLBInvalidException,
1303 MipsKernTLBInvalidException))
1304 subr = (unsigned)MipsTLBInvalidException;
1305 else if (pcBetween(MipsKernTLBInvalidException,
1306 MipsUserTLBInvalidException))
1307 subr = (unsigned)MipsKernTLBInvalidException;
1308 else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
1309 subr = (unsigned)MipsUserTLBInvalidException;
1310 else if (pcBetween(cpu_switch, MipsSwitchFPState))
1311 subr = (unsigned)cpu_switch;
1312 else if (pcBetween(_locore, _locoreEnd)) {
1313 subr = (unsigned)_locore;
1317 /* check for bad PC */
1318 if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) {
1319 (*printfn) ("PC 0x%x: not in kernel\n", pc);
1324 * Find the beginning of the current subroutine by scanning
1325 * backwards from the current PC for the end of the previous
1329 va = pc - sizeof(int);
1330 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
1332 va += 2 * sizeof(int); /* skip back over branch & delay slot */
1333 /* skip over nulls which might separate .o files */
1334 while ((instr = kdbpeek((int *)va)) == 0)
1338 /* scan forwards to find stack size and any saved registers */
1342 for (va = subr; more; va += sizeof(int),
1343 more = (more == 3) ? 3 : more - 1) {
1344 /* stop if hit our current position */
1347 instr = kdbpeek((int *)va);
1349 switch (i.JType.op) {
1351 switch (i.RType.func) {
1354 more = 2; /* stop after next instruction */
1359 more = 1; /* stop now */
1370 more = 2; /* stop after next instruction */
1377 switch (i.RType.rs) {
1380 more = 2; /* stop after next instruction */
1385 /* look for saved registers on the stack */
1386 if (i.IType.rs != 29)
1388 /* only restore the first one */
1389 if (mask & (1 << i.IType.rt))
1391 mask |= (1 << i.IType.rt);
1392 switch (i.IType.rt) {
1394 a0 = kdbpeek((int *)(sp + (short)i.IType.imm));
1398 a1 = kdbpeek((int *)(sp + (short)i.IType.imm));
1402 a2 = kdbpeek((int *)(sp + (short)i.IType.imm));
1406 a3 = kdbpeek((int *)(sp + (short)i.IType.imm));
1410 fp = kdbpeek((int *)(sp + (short)i.IType.imm));
1414 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
1419 /* look for saved registers on the stack */
1420 if (i.IType.rs != 29)
1422 /* only restore the first one */
1423 if (mask & (1 << i.IType.rt))
1425 mask |= (1 << i.IType.rt);
1426 switch (i.IType.rt) {
1428 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1432 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1436 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1440 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1444 fp = kdbpeekD((int *)(sp + (short)i.IType.imm));
1448 ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
1454 /* look for stack pointer adjustment */
1455 if (i.IType.rs != 29 || i.IType.rt != 29)
1457 stksize = -((short)i.IType.imm);
1462 (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
1463 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1466 if (pc == ra && stksize == 0)
1467 (*printfn) ("stacktrace: loop!\n");
1477 (*printfn) ("pid %d\n", curproc->p_pid);
1479 (*printfn) ("curproc NULL\n");
1484 * Functions ``special'' enough to print by name
1487 #define Name(_fn) { (void*)_fn, # _fn }
1489 #define Name(_fn) { _fn, "_fn"}
1497 Name(MipsKernGenException),
1498 Name(MipsUserGenException),
1508 * Map a function address to a string name, if known; or a hex string.
1511 fn_name(unsigned addr)
1513 static char buf[17];
1523 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
1524 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
1525 if (symname && diff == 0)
1529 for (i = 0; names[i].name; i++)
1530 if (names[i].addr == (void *)addr)
1531 return (names[i].name);
1532 sprintf(buf, "%x", addr);
1539 log_frame_dump(struct trapframe *frame)
1541 log(LOG_ERR, "Trapframe Register Dump:\n");
1542 log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1543 0, frame->ast, frame->v0, frame->v1);
1545 log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1546 frame->a0, frame->a1, frame->a2, frame->a3);
1548 log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1549 frame->t0, frame->t1, frame->t2, frame->t3);
1551 log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1552 frame->t4, frame->t5, frame->t6, frame->t7);
1554 log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1555 frame->t8, frame->t9, frame->s0, frame->s1);
1557 log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1558 frame->s2, frame->s3, frame->s4, frame->s5);
1560 log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1561 frame->s6, frame->s7, frame->k0, frame->k1);
1563 log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1564 frame->gp, frame->sp, frame->s8, frame->ra);
1566 log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1567 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1570 log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n",
1571 frame->cause, frame->pc, frame->ic);
1573 log(LOG_ERR, "\tcause: %08x\tpc: %08x\n",
1574 frame->cause, frame->pc);
1580 trap_frame_dump(struct trapframe *frame)
1582 printf("Trapframe Register Dump:\n");
1583 printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1584 0, frame->ast, frame->v0, frame->v1);
1586 printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1587 frame->a0, frame->a1, frame->a2, frame->a3);
1589 printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1590 frame->t0, frame->t1, frame->t2, frame->t3);
1592 printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1593 frame->t4, frame->t5, frame->t6, frame->t7);
1595 printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1596 frame->t8, frame->t9, frame->s0, frame->s1);
1598 printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1599 frame->s2, frame->s3, frame->s4, frame->s5);
1601 printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1602 frame->s6, frame->s7, frame->k0, frame->k1);
1604 printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1605 frame->gp, frame->sp, frame->s8, frame->ra);
1607 printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1608 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1611 printf("\tcause: %08x\tpc: %08x\tic: %08x\n",
1612 frame->cause, frame->pc, frame->ic);
1614 printf("\tcause: %08x\tpc: %08x\n",
1615 frame->cause, frame->pc);
1623 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1627 struct proc *p = curproc;
1629 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
1631 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1633 ptep = (pt_entry_t *)0;
1641 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1646 struct proc *p = curproc;
1647 char *read_or_write;
1650 trap_type &= ~T_USER;
1653 printf("cpuid = %d\n", PCPU_GET(cpuid));
1655 switch (trap_type) {
1658 read_or_write = "write";
1662 case T_BUS_ERR_IFETCH:
1663 read_or_write = "read";
1669 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1670 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n",
1671 msg, p->p_pid, p->p_comm,
1672 p->p_ucred ? p->p_ucred->cr_uid : -1,
1677 /* log registers in trap frame */
1678 log_frame_dump(frame);
1680 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1683 * Dump a few words around faulting instruction, if the addres is
1686 if (!(pc & 3) && (pc != frame->badvaddr) &&
1687 (trap_type != T_BUS_ERR_IFETCH) &&
1688 useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1689 /* dump page table entry for faulting instruction */
1690 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n",
1691 pc, *pdep, ptep ? *ptep : 0);
1693 addr = (unsigned int *)pc;
1694 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1696 log(LOG_ERR, "%08x %08x %08x %08x\n",
1697 addr[0], addr[1], addr[2], addr[3]);
1699 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n",
1700 pc, *pdep, ptep ? *ptep : 0);
1702 /* panic("Bad trap");*/
1707 * Unaligned load/store emulation
1710 mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
1712 register_t *reg = (register_t *) frame;
1713 u_int32_t inst = *((u_int32_t *) pc);
1714 u_int32_t value_msb, value;
1715 int access_type = 0;
1717 switch (MIPS_INST_OPCODE(inst)) {
1719 lbu_macro(value_msb, addr);
1721 lbu_macro(value, addr);
1722 value |= value_msb << 8;
1723 reg[MIPS_INST_RT(inst)] = value;
1724 access_type = MIPS_LHU_ACCESS;
1728 lb_macro(value_msb, addr);
1730 lbu_macro(value, addr);
1731 value |= value_msb << 8;
1732 reg[MIPS_INST_RT(inst)] = value;
1733 access_type = MIPS_LH_ACCESS;
1737 lwl_macro(value, addr);
1739 lwr_macro(value, addr);
1740 value &= 0xffffffff;
1741 reg[MIPS_INST_RT(inst)] = value;
1742 access_type = MIPS_LWU_ACCESS;
1746 lwl_macro(value, addr);
1748 lwr_macro(value, addr);
1749 reg[MIPS_INST_RT(inst)] = value;
1750 access_type = MIPS_LW_ACCESS;
1754 value = reg[MIPS_INST_RT(inst)];
1755 value_msb = value >> 8;
1756 sb_macro(value_msb, addr);
1758 sb_macro(value, addr);
1759 access_type = MIPS_SH_ACCESS;
1763 value = reg[MIPS_INST_RT(inst)];
1764 swl_macro(value, addr);
1766 swr_macro(value, addr);
1767 access_type = MIPS_SW_ACCESS;
1779 emulate_unaligned_access(struct trapframe *frame)
1782 int access_type = 0;
1784 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1787 * Fall through if it's instruction fetch exception
1789 if (!((pc & 3) || (pc == frame->badvaddr))) {
1792 * Handle unaligned load and store
1796 * Return access type if the instruction was emulated.
1797 * Otherwise restore pc and fall through.
1799 access_type = mips_unaligned_load_store(frame,
1800 frame->badvaddr, pc);
1803 if (DELAYBRANCH(frame->cause))
1804 frame->pc = MipsEmulateBranch(frame, frame->pc,
1809 log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n",
1810 access_name[access_type - 1], pc, frame->badvaddr);