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;
651 * note: PCPU_LAZY_INC() can only be used if we can
652 * afford occassional inaccuracy in the count.
654 PCPU_LAZY_INC(cnt.v_syscall);
655 if (td->td_ucred != p->p_ucred)
656 cred_update_thread(td);
658 if (p->p_flag & P_SA)
659 thread_user_enter(td);
661 /* compute next PC after syscall instruction */
662 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
663 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
664 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
667 locr0->pc += sizeof(int);
674 * Code is first argument, followed by
686 * Like syscall, but code is a quad, so as
687 * to maintain quad alignment for the rest
690 if (_QUAD_LOWWORD == 0) {
709 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
712 if (p->p_sysent->sv_mask)
713 code &= p->p_sysent->sv_mask;
715 if (code >= p->p_sysent->sv_size)
716 callp = &p->p_sysent->sv_table[0];
718 callp = &p->p_sysent->sv_table[code];
720 nargs = callp->sy_narg;
722 if (nargs > nsaved) {
723 i = copyin((caddr_t)(locr0->sp +
724 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
725 (u_int)(nargs - nsaved) * sizeof(register_t));
730 if (KTRPOINT(td, KTR_SYSCALL))
731 ktrsyscall(code, nargs, args);
737 if (KTRPOINT(td, KTR_SYSCALL))
738 ktrsyscall(code, nargs, args);
740 td->td_retval[0] = 0;
741 td->td_retval[1] = locr0->v1;
743 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
744 if (trp == trapdebug)
745 trapdebug[TRAPSIZE - 1].code = code;
749 STOPEVENT(p, S_SCE, nargs);
751 PTRACESTOP_SC(p, td, S_PT_SCE);
752 i = (*callp->sy_call) (td, args);
755 * Reinitialize proc pointer `p' as it may be
756 * different if this is a child returning from fork
760 locr0 = td->td_frame;
762 trapdebug_enter(locr0, -code);
763 cpu_set_syscall_retval(td, i);
766 * The sync'ing of I & D caches for SYS_ptrace() is
767 * done by procfs_domem() through procfs_rwmem()
768 * instead of being done here under a special check
773 * Check for misbehavior.
775 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
776 (code >= 0 && code < SYS_MAXSYSCALL) ?
777 syscallnames[code] : "???");
778 KASSERT(td->td_critnest == 0,
779 ("System call %s returning in a critical section",
780 (code >= 0 && code < SYS_MAXSYSCALL) ?
781 syscallnames[code] : "???"));
782 KASSERT(td->td_locks == 0,
783 ("System call %s returning with %d locks held",
784 (code >= 0 && code < SYS_MAXSYSCALL) ?
785 syscallnames[code] : "???",
787 userret(td, trapframe);
789 if (KTRPOINT(p, KTR_SYSRET))
790 ktrsysret(code, i, td->td_retval[0]);
793 * This works because errno is findable through the
794 * register set. If we ever support an emulation
795 * where this is not the case, this code will need
798 STOPEVENT(p, S_SCX, code);
800 PTRACESTOP_SC(p, td, S_PT_SCX);
802 mtx_assert(&Giant, MA_NOTOWNED);
803 return (trapframe->pc);
808 kdb_trap(type, 0, trapframe);
809 return (trapframe->pc);
812 case T_BREAK + T_USER:
814 unsigned int va, instr;
816 /* compute address of break instruction */
818 if (DELAYBRANCH(trapframe->cause))
821 /* read break instruction */
822 instr = fuword((caddr_t)va);
824 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
825 p->p_comm, p->p_pid, instr, trapframe->pc,
826 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
828 if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
830 addr = trapframe->pc;
834 * The restoration of the original instruction and
835 * the clearing of the berakpoint will be done later
836 * by the call to ptrace_clear_single_step() in
837 * issignal() when SIGTRAP is processed.
839 addr = trapframe->pc;
844 case T_IWATCH + T_USER:
845 case T_DWATCH + T_USER:
849 /* compute address of trapped instruction */
851 if (DELAYBRANCH(trapframe->cause))
853 printf("watch exception @ 0x%x\n", va);
859 case T_TRAP + T_USER:
861 unsigned int va, instr;
862 struct trapframe *locr0 = td->td_frame;
864 /* compute address of trap instruction */
866 if (DELAYBRANCH(trapframe->cause))
868 /* read break instruction */
869 instr = fuword((caddr_t)va);
871 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
872 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
875 locr0->pc += sizeof(int);
878 i = SIGEMT; /* Stuff it with something for now */
882 case T_RES_INST + T_USER:
884 addr = trapframe->pc;
893 case T_COP_UNUSABLE + T_USER:
894 #if defined(SOFTFLOAT)
895 /* FP (COP1) instruction */
896 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
901 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
902 i = SIGILL; /* only FPU instructions allowed */
905 addr = trapframe->pc;
906 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
907 PCPU_SET(fpcurthread, td);
908 td->td_frame->sr |= SR_COP_1_BIT;
909 td->td_md.md_flags |= MDTD_FPUSED;
913 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
916 printf("FPU Trap: PC %x CR %x SR %x\n",
917 trapframe->pc, trapframe->cause, trapframe->sr);
922 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
925 case T_OVFLOW + T_USER:
927 addr = trapframe->pc;
930 case T_ADDR_ERR_LD: /* misaligned access */
931 case T_ADDR_ERR_ST: /* misaligned access */
933 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
934 trapframe->badvaddr);
936 /* Only allow emulation on a user address */
937 if (allow_unaligned_acc &&
938 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
941 if (type == T_ADDR_ERR_LD)
944 mode = VM_PROT_WRITE;
947 * ADDR_ERR faults have higher priority than TLB
948 * Miss faults. Therefore, it is necessary to
949 * verify that the faulting address is a valid
950 * virtual address within the process' address space
951 * before trying to emulate the unaligned access.
953 if (useracc((caddr_t)
954 (((vm_offset_t)trapframe->badvaddr) &
955 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
956 access_type = emulate_unaligned_access(
958 if (access_type != 0) {
959 return (trapframe->pc);
965 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
966 if ((i = td->td_pcb->pcb_onfault) != 0) {
967 td->td_pcb->pcb_onfault = 0;
968 return (onfault_table[i]);
975 #if !defined(SMP) && defined(DEBUG)
976 stacktrace(!usermode ? trapframe : td->td_frame);
980 printf("cpu:%d-", PCPU_GET(cpuid));
982 printf("Trap cause = %d (%s - ", type,
983 trap_type[type & (~T_USER)]);
986 printf("user mode)\n");
988 printf("kernel mode)\n");
991 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
992 trapframe->badvaddr, trapframe->pc, trapframe->ra,
997 if (debugger_on_panic || kdb_active) {
998 kdb_trap(type, 0, trapframe);
1003 td->td_frame->pc = trapframe->pc;
1004 td->td_frame->cause = trapframe->cause;
1005 td->td_frame->badvaddr = trapframe->badvaddr;
1006 ksiginfo_init_trap(&ksi);
1008 ksi.ksi_code = ucode;
1009 ksi.ksi_addr = (void *)addr;
1010 ksi.ksi_trapno = type;
1011 trapsignal(td, &ksi);
1015 * Note: we should only get here if returning to user mode.
1017 userret(td, trapframe);
1018 mtx_assert(&Giant, MA_NOTOWNED);
1019 return (trapframe->pc);
1022 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1029 printf("trapDump(%s)\n", msg);
1030 for (i = 0; i < TRAPSIZE; i++) {
1031 if (trp == trapdebug) {
1032 trp = &trapdebug[TRAPSIZE - 1];
1037 if (trp->cause == 0)
1040 printf("%s: ADR %x PC %x CR %x SR %x\n",
1041 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
1042 trp->vadr, trp->pc, trp->cause, trp->status);
1044 printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
1053 * Return the resulting PC as if the branch was executed.
1056 MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR,
1060 register_t *regsPtr = (register_t *) framePtr;
1061 unsigned retAddr = 0;
1064 #define GetBranchDest(InstPtr, inst) \
1065 ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
1069 if (instptr < MIPS_KSEG0_START)
1070 inst.word = fuword((void *)instptr);
1072 inst = *(InstFmt *) instptr;
1074 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1075 inst.word = fuword((void *)instPC);
1077 inst = *(InstFmt *) instPC;
1080 switch ((int)inst.JType.op) {
1082 switch ((int)inst.RType.func) {
1085 retAddr = regsPtr[inst.RType.rs];
1089 retAddr = instPC + 4;
1095 switch ((int)inst.IType.rt) {
1100 if ((int)(regsPtr[inst.RType.rs]) < 0)
1101 retAddr = GetBranchDest(instPC, inst);
1103 retAddr = instPC + 8;
1110 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1111 retAddr = GetBranchDest(instPC, inst);
1113 retAddr = instPC + 8;
1122 retAddr = instPC + 4; /* Like syscall... */
1126 panic("MipsEmulateBranch: Bad branch cond");
1132 retAddr = (inst.JType.target << 2) |
1133 ((unsigned)instPC & 0xF0000000);
1138 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1139 retAddr = GetBranchDest(instPC, inst);
1141 retAddr = instPC + 8;
1146 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1147 retAddr = GetBranchDest(instPC, inst);
1149 retAddr = instPC + 8;
1154 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1155 retAddr = GetBranchDest(instPC, inst);
1157 retAddr = instPC + 8;
1162 if ((int)(regsPtr[inst.RType.rs]) > 0)
1163 retAddr = GetBranchDest(instPC, inst);
1165 retAddr = instPC + 8;
1169 switch (inst.RType.rs) {
1172 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1173 condition = fpcCSR & FPC_COND_BIT;
1175 condition = !(fpcCSR & FPC_COND_BIT);
1177 retAddr = GetBranchDest(instPC, inst);
1179 retAddr = instPC + 8;
1183 retAddr = instPC + 4;
1188 retAddr = instPC + 4;
1194 #if defined(DDB) || defined(DEBUG)
1195 #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
1198 char *fn_name(unsigned addr);
1201 * Print a stack backtrace.
1204 stacktrace(struct trapframe *regs)
1206 stacktrace_subr(regs, printf);
1210 stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...))
1213 unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr;
1214 unsigned instr, mask;
1215 unsigned int frames = 0;
1218 /* get initial values from the exception frame */
1222 ra = regs->ra; /* May be a 'leaf' function */
1228 /* Jump here when done with a frame, to start a new one */
1231 /* Jump here after a nonstandard (interrupt handler) frame */
1234 if (frames++ > 100) {
1235 (*printfn) ("\nstackframe count exceeded\n");
1236 /* return breaks stackframe-size heuristics with gcc -O2 */
1237 goto finish; /* XXX */
1239 /* check for bad SP: could foul up next frame */
1240 if (sp & 3 || sp < 0x80000000) {
1241 (*printfn) ("SP 0x%x: not in kernel\n", sp);
1246 #define Between(x, y, z) \
1247 ( ((x) <= (y)) && ((y) < (z)) )
1248 #define pcBetween(a,b) \
1249 Between((unsigned)a, pc, (unsigned)b)
1252 * Check for current PC in exception handler code that don't have a
1253 * preceding "j ra" at the tail of the preceding function. Depends
1254 * on relative ordering of functions in exception.S, swtch.S.
1256 if (pcBetween(MipsKernGenException, MipsUserGenException))
1257 subr = (unsigned)MipsKernGenException;
1258 else if (pcBetween(MipsUserGenException, MipsKernIntr))
1259 subr = (unsigned)MipsUserGenException;
1260 else if (pcBetween(MipsKernIntr, MipsUserIntr))
1261 subr = (unsigned)MipsKernIntr;
1262 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
1263 subr = (unsigned)MipsUserIntr;
1264 else if (pcBetween(MipsTLBInvalidException,
1265 MipsKernTLBInvalidException))
1266 subr = (unsigned)MipsTLBInvalidException;
1267 else if (pcBetween(MipsKernTLBInvalidException,
1268 MipsUserTLBInvalidException))
1269 subr = (unsigned)MipsKernTLBInvalidException;
1270 else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
1271 subr = (unsigned)MipsUserTLBInvalidException;
1272 else if (pcBetween(cpu_switch, MipsSwitchFPState))
1273 subr = (unsigned)cpu_switch;
1274 else if (pcBetween(_locore, _locoreEnd)) {
1275 subr = (unsigned)_locore;
1279 /* check for bad PC */
1280 if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) {
1281 (*printfn) ("PC 0x%x: not in kernel\n", pc);
1286 * Find the beginning of the current subroutine by scanning
1287 * backwards from the current PC for the end of the previous
1291 va = pc - sizeof(int);
1292 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
1294 va += 2 * sizeof(int); /* skip back over branch & delay slot */
1295 /* skip over nulls which might separate .o files */
1296 while ((instr = kdbpeek((int *)va)) == 0)
1300 /* scan forwards to find stack size and any saved registers */
1304 for (va = subr; more; va += sizeof(int),
1305 more = (more == 3) ? 3 : more - 1) {
1306 /* stop if hit our current position */
1309 instr = kdbpeek((int *)va);
1311 switch (i.JType.op) {
1313 switch (i.RType.func) {
1316 more = 2; /* stop after next instruction */
1321 more = 1; /* stop now */
1332 more = 2; /* stop after next instruction */
1339 switch (i.RType.rs) {
1342 more = 2; /* stop after next instruction */
1347 /* look for saved registers on the stack */
1348 if (i.IType.rs != 29)
1350 /* only restore the first one */
1351 if (mask & (1 << i.IType.rt))
1353 mask |= (1 << i.IType.rt);
1354 switch (i.IType.rt) {
1356 a0 = kdbpeek((int *)(sp + (short)i.IType.imm));
1360 a1 = kdbpeek((int *)(sp + (short)i.IType.imm));
1364 a2 = kdbpeek((int *)(sp + (short)i.IType.imm));
1368 a3 = kdbpeek((int *)(sp + (short)i.IType.imm));
1372 fp = kdbpeek((int *)(sp + (short)i.IType.imm));
1376 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
1381 /* look for saved registers on the stack */
1382 if (i.IType.rs != 29)
1384 /* only restore the first one */
1385 if (mask & (1 << i.IType.rt))
1387 mask |= (1 << i.IType.rt);
1388 switch (i.IType.rt) {
1390 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1394 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1398 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1402 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1406 fp = kdbpeekD((int *)(sp + (short)i.IType.imm));
1410 ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
1416 /* look for stack pointer adjustment */
1417 if (i.IType.rs != 29 || i.IType.rt != 29)
1419 stksize = -((short)i.IType.imm);
1424 (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
1425 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1428 if (pc == ra && stksize == 0)
1429 (*printfn) ("stacktrace: loop!\n");
1439 (*printfn) ("pid %d\n", curproc->p_pid);
1441 (*printfn) ("curproc NULL\n");
1446 * Functions ``special'' enough to print by name
1449 #define Name(_fn) { (void*)_fn, # _fn }
1451 #define Name(_fn) { _fn, "_fn"}
1459 Name(MipsKernGenException),
1460 Name(MipsUserGenException),
1470 * Map a function address to a string name, if known; or a hex string.
1473 fn_name(unsigned addr)
1475 static char buf[17];
1485 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
1486 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
1487 if (symname && diff == 0)
1491 for (i = 0; names[i].name; i++)
1492 if (names[i].addr == (void *)addr)
1493 return (names[i].name);
1494 sprintf(buf, "%x", addr);
1501 log_frame_dump(struct trapframe *frame)
1503 log(LOG_ERR, "Trapframe Register Dump:\n");
1504 log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1505 0, frame->ast, frame->v0, frame->v1);
1507 log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1508 frame->a0, frame->a1, frame->a2, frame->a3);
1510 log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1511 frame->t0, frame->t1, frame->t2, frame->t3);
1513 log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1514 frame->t4, frame->t5, frame->t6, frame->t7);
1516 log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1517 frame->t8, frame->t9, frame->s0, frame->s1);
1519 log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1520 frame->s2, frame->s3, frame->s4, frame->s5);
1522 log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1523 frame->s6, frame->s7, frame->k0, frame->k1);
1525 log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1526 frame->gp, frame->sp, frame->s8, frame->ra);
1528 log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1529 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1532 log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n",
1533 frame->cause, frame->pc, frame->ic);
1535 log(LOG_ERR, "\tcause: %08x\tpc: %08x\n",
1536 frame->cause, frame->pc);
1542 trap_frame_dump(struct trapframe *frame)
1544 printf("Trapframe Register Dump:\n");
1545 printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1546 0, frame->ast, frame->v0, frame->v1);
1548 printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1549 frame->a0, frame->a1, frame->a2, frame->a3);
1551 printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1552 frame->t0, frame->t1, frame->t2, frame->t3);
1554 printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1555 frame->t4, frame->t5, frame->t6, frame->t7);
1557 printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1558 frame->t8, frame->t9, frame->s0, frame->s1);
1560 printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1561 frame->s2, frame->s3, frame->s4, frame->s5);
1563 printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1564 frame->s6, frame->s7, frame->k0, frame->k1);
1566 printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1567 frame->gp, frame->sp, frame->s8, frame->ra);
1569 printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1570 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1573 printf("\tcause: %08x\tpc: %08x\tic: %08x\n",
1574 frame->cause, frame->pc, frame->ic);
1576 printf("\tcause: %08x\tpc: %08x\n",
1577 frame->cause, frame->pc);
1585 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1589 struct proc *p = curproc;
1591 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
1593 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1595 ptep = (pt_entry_t *)0;
1603 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1608 struct proc *p = curproc;
1609 char *read_or_write;
1612 trap_type &= ~T_USER;
1615 printf("cpuid = %d\n", PCPU_GET(cpuid));
1617 switch (trap_type) {
1620 read_or_write = "write";
1624 case T_BUS_ERR_IFETCH:
1625 read_or_write = "read";
1631 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1632 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n",
1633 msg, p->p_pid, p->p_comm,
1634 p->p_ucred ? p->p_ucred->cr_uid : -1,
1639 /* log registers in trap frame */
1640 log_frame_dump(frame);
1642 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1645 * Dump a few words around faulting instruction, if the addres is
1648 if (!(pc & 3) && (pc != frame->badvaddr) &&
1649 (trap_type != T_BUS_ERR_IFETCH) &&
1650 useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1651 /* dump page table entry for faulting instruction */
1652 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n",
1653 pc, *pdep, ptep ? *ptep : 0);
1655 addr = (unsigned int *)pc;
1656 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1658 log(LOG_ERR, "%08x %08x %08x %08x\n",
1659 addr[0], addr[1], addr[2], addr[3]);
1661 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n",
1662 pc, *pdep, ptep ? *ptep : 0);
1664 /* panic("Bad trap");*/
1669 * Unaligned load/store emulation
1672 mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
1674 register_t *reg = (register_t *) frame;
1675 u_int32_t inst = *((u_int32_t *) pc);
1676 u_int32_t value_msb, value;
1677 int access_type = 0;
1679 switch (MIPS_INST_OPCODE(inst)) {
1681 lbu_macro(value_msb, addr);
1683 lbu_macro(value, addr);
1684 value |= value_msb << 8;
1685 reg[MIPS_INST_RT(inst)] = value;
1686 access_type = MIPS_LHU_ACCESS;
1690 lb_macro(value_msb, addr);
1692 lbu_macro(value, addr);
1693 value |= value_msb << 8;
1694 reg[MIPS_INST_RT(inst)] = value;
1695 access_type = MIPS_LH_ACCESS;
1699 lwl_macro(value, addr);
1701 lwr_macro(value, addr);
1702 value &= 0xffffffff;
1703 reg[MIPS_INST_RT(inst)] = value;
1704 access_type = MIPS_LWU_ACCESS;
1708 lwl_macro(value, addr);
1710 lwr_macro(value, addr);
1711 reg[MIPS_INST_RT(inst)] = value;
1712 access_type = MIPS_LW_ACCESS;
1716 value = reg[MIPS_INST_RT(inst)];
1717 value_msb = value >> 8;
1718 sb_macro(value_msb, addr);
1720 sb_macro(value, addr);
1721 access_type = MIPS_SH_ACCESS;
1725 value = reg[MIPS_INST_RT(inst)];
1726 swl_macro(value, addr);
1728 swr_macro(value, addr);
1729 access_type = MIPS_SW_ACCESS;
1741 emulate_unaligned_access(struct trapframe *frame)
1744 int access_type = 0;
1746 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1749 * Fall through if it's instruction fetch exception
1751 if (!((pc & 3) || (pc == frame->badvaddr))) {
1754 * Handle unaligned load and store
1758 * Return access type if the instruction was emulated.
1759 * Otherwise restore pc and fall through.
1761 access_type = mips_unaligned_load_store(frame,
1762 frame->badvaddr, pc);
1765 if (DELAYBRANCH(frame->cause))
1766 frame->pc = MipsEmulateBranch(frame, frame->pc,
1771 log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n",
1772 access_name[access_type - 1], pc, frame->badvaddr);