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 cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
267 struct trapframe *locr0 = td->td_frame;
268 struct sysentvec *se;
271 bzero(sa->args, sizeof(sa->args));
273 /* compute next PC after syscall instruction */
274 td->td_pcb->pcb_tpc = sa->trapframe->pc; /* Remember if restart */
275 if (DELAYBRANCH(sa->trapframe->cause)) /* Check BD bit */
276 locr0->pc = MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0);
278 locr0->pc += sizeof(int);
279 sa->code = locr0->v0;
282 #if defined(__mips_n32) || defined(__mips_n64)
285 * Quads fit in a single register in
293 * Code is first argument, followed by
296 sa->code = locr0->a0;
297 sa->args[0] = locr0->a1;
298 sa->args[1] = locr0->a2;
299 sa->args[2] = locr0->a3;
301 #if defined(__mips_n32) || defined(__mips_n64)
302 sa->args[3] = locr0->t4;
303 sa->args[4] = locr0->t5;
304 sa->args[5] = locr0->t6;
305 sa->args[6] = locr0->t7;
310 #if defined(__mips_o32)
313 * Like syscall, but code is a quad, so as
314 * to maintain quad alignment for the rest
317 if (_QUAD_LOWWORD == 0)
318 sa->code = locr0->a0;
320 sa->code = locr0->a1;
321 sa->args[0] = locr0->a2;
322 sa->args[1] = locr0->a3;
328 sa->args[0] = locr0->a0;
329 sa->args[1] = locr0->a1;
330 sa->args[2] = locr0->a2;
331 sa->args[3] = locr0->a3;
333 #if defined (__mips_n32) || defined(__mips_n64)
334 sa->args[4] = locr0->t4;
335 sa->args[5] = locr0->t5;
336 sa->args[6] = locr0->t6;
337 sa->args[7] = locr0->t7;
344 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
347 se = td->td_proc->p_sysent;
349 sa->code &= se->sv_mask;
351 if (sa->code >= se->sv_size)
352 sa->callp = &se->sv_table[0];
354 sa->callp = &se->sv_table[sa->code];
356 sa->narg = sa->callp->sy_narg;
358 if (sa->narg > nsaved) {
359 #if defined(__mips_n32) || defined(__mips_n64)
362 * Is this right for new ABIs? I think the 4 there
363 * should be 8, size there are 8 registers to skip,
364 * not 4, but I'm not certain.
366 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", sa->code,
369 error = copyin((caddr_t)(intptr_t)(locr0->sp +
370 4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
371 (u_int)(sa->narg - nsaved) * sizeof(register_t));
380 td->td_retval[0] = 0;
381 td->td_retval[1] = locr0->v1;
389 #include "../../kern/subr_syscall.c"
392 * Handle an exception.
393 * Called from MipsKernGenException() or MipsUserGenException()
394 * when a processor trap occurs.
395 * In the case of a kernel trap, we return the pc where to resume if
396 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
399 trap(struct trapframe *trapframe)
404 struct thread *td = curthread;
405 struct proc *p = curproc;
414 trapdebug_enter(trapframe, 0);
416 type = (trapframe->cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
417 if (TRAPF_USERMODE(trapframe)) {
425 * Enable hardware interrupts if they were on before the trap. If it
426 * was off disable all so we don't accidently enable it when doing a
427 * return to userland.
429 if (trapframe->sr & MIPS_SR_INT_IE) {
430 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
438 static vm_offset_t last_badvaddr = 0;
439 static vm_offset_t this_badvaddr = 0;
440 static int count = 0;
443 printf("trap type %x (%s - ", type,
444 trap_type[type & (~T_USER)]);
447 printf("user mode)\n");
449 printf("kernel mode)\n");
452 printf("cpuid = %d\n", PCPU_GET(cpuid));
454 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
455 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
456 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
457 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
458 (curproc ? curproc->p_pid : -1), pid);
460 switch (type & ~T_USER) {
466 this_badvaddr = trapframe->badvaddr;
469 this_badvaddr = trapframe->ra;
472 this_badvaddr = trapframe->pc;
475 if ((last_badvaddr == this_badvaddr) &&
476 ((type & ~T_USER) != T_SYSCALL)) {
478 trap_frame_dump(trapframe);
479 panic("too many faults at %p\n", (void *)last_badvaddr);
482 last_badvaddr = this_badvaddr;
490 kdb_trap(type, 0, trapframe);
495 /* check for kernel address */
496 if (KERNLAND(trapframe->badvaddr)) {
497 if (pmap_emulate_modified(kernel_pmap,
498 trapframe->badvaddr) != 0) {
499 ftype = VM_PROT_WRITE;
502 return (trapframe->pc);
506 case T_TLB_MOD + T_USER:
507 pmap = &p->p_vmspace->vm_pmap;
508 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
509 ftype = VM_PROT_WRITE;
513 return (trapframe->pc);
518 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
519 /* check for kernel address */
520 if (KERNLAND(trapframe->badvaddr)) {
525 va = trunc_page((vm_offset_t)trapframe->badvaddr);
526 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
527 if (rv == KERN_SUCCESS)
528 return (trapframe->pc);
529 if (td->td_pcb->pcb_onfault != NULL) {
530 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
531 td->td_pcb->pcb_onfault = NULL;
538 * It is an error for the kernel to access user space except
539 * through the copyin/copyout routines.
541 if (td->td_pcb->pcb_onfault == NULL)
544 /* check for fuswintr() or suswintr() getting a page fault */
545 /* XXX There must be a nicer way to do this. */
546 if (td->td_pcb->pcb_onfault == fswintrberr) {
547 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
548 td->td_pcb->pcb_onfault = NULL;
554 case T_TLB_LD_MISS + T_USER:
555 ftype = VM_PROT_READ;
558 case T_TLB_ST_MISS + T_USER:
559 ftype = VM_PROT_WRITE;
569 va = trunc_page((vm_offset_t)trapframe->badvaddr);
570 if (KERNLAND(trapframe->badvaddr)) {
572 * Don't allow user-mode faults in kernel
579 * Keep swapout from messing with us during this
586 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
592 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
593 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
594 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
597 if (rv == KERN_SUCCESS) {
599 return (trapframe->pc);
605 if (td->td_pcb->pcb_onfault != NULL) {
606 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
607 td->td_pcb->pcb_onfault = NULL;
613 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
614 addr = trapframe->pc;
616 msg = "BAD_PAGE_FAULT";
617 log_bad_page_fault(msg, trapframe, type);
622 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
623 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
624 if (trapframe->badvaddr < 0 ||
625 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
626 msg = "ADDRESS_SPACE_ERR";
627 } else if (allow_unaligned_acc) {
630 if (type == (T_ADDR_ERR_LD + T_USER))
633 mode = VM_PROT_WRITE;
635 access_type = emulate_unaligned_access(trapframe, mode);
636 if (access_type != 0)
638 msg = "ALIGNMENT_FIX_ERR";
645 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
646 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
647 ucode = 0; /* XXX should be VM_PROT_something */
649 addr = trapframe->pc;
652 log_bad_page_fault(msg, trapframe, type);
655 case T_SYSCALL + T_USER:
657 struct syscall_args sa;
660 sa.trapframe = trapframe;
661 error = syscallenter(td, &sa);
663 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
664 if (trp == trapdebug)
665 trapdebug[TRAPSIZE - 1].code = sa.code;
667 trp[-1].code = sa.code;
669 trapdebug_enter(td->td_frame, -sa.code);
672 * The sync'ing of I & D caches for SYS_ptrace() is
673 * done by procfs_domem() through procfs_rwmem()
674 * instead of being done here under a special check
677 syscallret(td, error, &sa);
678 return (trapframe->pc);
683 kdb_trap(type, 0, trapframe);
684 return (trapframe->pc);
687 case T_BREAK + T_USER:
692 /* compute address of break instruction */
694 if (DELAYBRANCH(trapframe->cause))
697 /* read break instruction */
698 instr = fuword32((caddr_t)va);
700 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
701 p->p_comm, p->p_pid, instr, trapframe->pc,
702 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
704 if (td->td_md.md_ss_addr != va ||
705 instr != MIPS_BREAK_SSTEP) {
707 addr = trapframe->pc;
711 * The restoration of the original instruction and
712 * the clearing of the berakpoint will be done later
713 * by the call to ptrace_clear_single_step() in
714 * issignal() when SIGTRAP is processed.
716 addr = trapframe->pc;
721 case T_IWATCH + T_USER:
722 case T_DWATCH + T_USER:
726 /* compute address of trapped instruction */
728 if (DELAYBRANCH(trapframe->cause))
730 printf("watch exception @ %p\n", (void *)va);
736 case T_TRAP + T_USER:
740 struct trapframe *locr0 = td->td_frame;
742 /* compute address of trap instruction */
744 if (DELAYBRANCH(trapframe->cause))
746 /* read break instruction */
747 instr = fuword32((caddr_t)va);
749 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
750 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
753 locr0->pc += sizeof(int);
756 i = SIGEMT; /* Stuff it with something for now */
760 case T_RES_INST + T_USER:
761 log_illegal_instruction("RES_INST", trapframe);
763 addr = trapframe->pc;
772 case T_COP_UNUSABLE + T_USER:
773 #if !defined(CPU_HAVEFPU)
774 /* FP (COP1) instruction */
775 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) {
776 log_illegal_instruction("COP1_UNUSABLE", trapframe);
781 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) {
782 log_illegal_instruction("COPn_UNUSABLE", trapframe);
783 i = SIGILL; /* only FPU instructions allowed */
786 addr = trapframe->pc;
787 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
788 PCPU_SET(fpcurthread, td);
789 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
790 td->td_md.md_flags |= MDTD_FPUSED;
794 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
797 printf("FPU Trap: PC %#jx CR %x SR %x\n",
798 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
803 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
806 case T_OVFLOW + T_USER:
808 addr = trapframe->pc;
811 case T_ADDR_ERR_LD: /* misaligned access */
812 case T_ADDR_ERR_ST: /* misaligned access */
815 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
816 (intmax_t)trapframe->badvaddr);
819 /* Only allow emulation on a user address */
820 if (allow_unaligned_acc &&
821 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
824 if (type == T_ADDR_ERR_LD)
827 mode = VM_PROT_WRITE;
829 access_type = emulate_unaligned_access(trapframe, mode);
830 if (access_type != 0)
831 return (trapframe->pc);
835 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
836 if (td->td_pcb->pcb_onfault != NULL) {
837 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
838 td->td_pcb->pcb_onfault = NULL;
847 #if !defined(SMP) && defined(DEBUG)
848 stacktrace(!usermode ? trapframe : td->td_frame);
852 printf("cpu:%d-", PCPU_GET(cpuid));
854 printf("Trap cause = %d (%s - ", type,
855 trap_type[type & (~T_USER)]);
858 printf("user mode)\n");
860 printf("kernel mode)\n");
864 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
865 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
866 (intmax_t)trapframe->sr);
870 if (debugger_on_panic || kdb_active) {
871 kdb_trap(type, 0, trapframe);
876 td->td_frame->pc = trapframe->pc;
877 td->td_frame->cause = trapframe->cause;
878 td->td_frame->badvaddr = trapframe->badvaddr;
879 ksiginfo_init_trap(&ksi);
881 ksi.ksi_code = ucode;
882 ksi.ksi_addr = (void *)addr;
883 ksi.ksi_trapno = type;
884 trapsignal(td, &ksi);
888 * Note: we should only get here if returning to user mode.
890 userret(td, trapframe);
891 mtx_assert(&Giant, MA_NOTOWNED);
892 return (trapframe->pc);
895 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
903 printf("trapDump(%s)\n", msg);
904 for (i = 0; i < TRAPSIZE; i++) {
905 if (trp == trapdebug) {
906 trp = &trapdebug[TRAPSIZE - 1];
914 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
915 trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >>
916 MIPS_CR_EXC_CODE_SHIFT],
917 (intmax_t)trp->vadr, (intmax_t)trp->pc,
918 (intmax_t)trp->cause, (intmax_t)trp->status);
920 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
921 (intmax_t)trp->sp, (int)trp->code);
929 * Return the resulting PC as if the branch was executed.
932 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
936 register_t *regsPtr = (register_t *) framePtr;
937 uintptr_t retAddr = 0;
940 #define GetBranchDest(InstPtr, inst) \
941 (InstPtr + 4 + ((short)inst.IType.imm << 2))
945 if (instptr < MIPS_KSEG0_START)
946 inst.word = fuword32((void *)instptr);
948 inst = *(InstFmt *) instptr;
950 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
951 inst.word = fuword32((void *)instPC);
953 inst = *(InstFmt *) instPC;
956 switch ((int)inst.JType.op) {
958 switch ((int)inst.RType.func) {
961 retAddr = regsPtr[inst.RType.rs];
965 retAddr = instPC + 4;
971 switch ((int)inst.IType.rt) {
976 if ((int)(regsPtr[inst.RType.rs]) < 0)
977 retAddr = GetBranchDest(instPC, inst);
979 retAddr = instPC + 8;
986 if ((int)(regsPtr[inst.RType.rs]) >= 0)
987 retAddr = GetBranchDest(instPC, inst);
989 retAddr = instPC + 8;
998 retAddr = instPC + 4; /* Like syscall... */
1002 panic("MipsEmulateBranch: Bad branch cond");
1008 retAddr = (inst.JType.target << 2) |
1009 ((unsigned)(instPC + 4) & 0xF0000000);
1014 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1015 retAddr = GetBranchDest(instPC, inst);
1017 retAddr = instPC + 8;
1022 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1023 retAddr = GetBranchDest(instPC, inst);
1025 retAddr = instPC + 8;
1030 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1031 retAddr = GetBranchDest(instPC, inst);
1033 retAddr = instPC + 8;
1038 if ((int)(regsPtr[inst.RType.rs]) > 0)
1039 retAddr = GetBranchDest(instPC, inst);
1041 retAddr = instPC + 8;
1045 switch (inst.RType.rs) {
1048 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1049 condition = fpcCSR & MIPS_FPU_COND_BIT;
1051 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1053 retAddr = GetBranchDest(instPC, inst);
1055 retAddr = instPC + 8;
1059 retAddr = instPC + 4;
1064 retAddr = instPC + 4;
1070 #if defined(DDB) || defined(DEBUG)
1072 * Print a stack backtrace.
1075 stacktrace(struct trapframe *regs)
1077 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1082 log_frame_dump(struct trapframe *frame)
1084 log(LOG_ERR, "Trapframe Register Dump:\n");
1085 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1086 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1088 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1089 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1091 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1092 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1094 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1095 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1097 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1098 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1100 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1101 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1103 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1104 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1106 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1107 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1109 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1110 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1113 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1114 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1116 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1117 (intmax_t)frame->cause, (intmax_t)frame->pc);
1123 trap_frame_dump(struct trapframe *frame)
1125 printf("Trapframe Register Dump:\n");
1126 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1127 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1129 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1130 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1132 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1133 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1135 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1136 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1138 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1139 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1141 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1142 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1144 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1145 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1147 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1148 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1150 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1151 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1154 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1155 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1157 printf("\tcause: %#jx\tpc: %#jx\n",
1158 (intmax_t)frame->cause, (intmax_t)frame->pc);
1166 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1170 struct proc *p = curproc;
1172 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1174 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1176 ptep = (pt_entry_t *)0;
1183 log_illegal_instruction(const char *msg, struct trapframe *frame)
1188 struct proc *p = curproc;
1192 printf("cpuid = %d\n", PCPU_GET(cpuid));
1194 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1195 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n",
1196 msg, p->p_pid, p->p_comm,
1197 p->p_ucred ? p->p_ucred->cr_uid : -1,
1199 (intmax_t)frame->ra);
1201 /* log registers in trap frame */
1202 log_frame_dump(frame);
1204 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1207 * Dump a few words around faulting instruction, if the addres is
1211 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1212 /* dump page table entry for faulting instruction */
1213 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1214 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1216 addr = (unsigned int *)(intptr_t)pc;
1217 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1219 log(LOG_ERR, "%08x %08x %08x %08x\n",
1220 addr[0], addr[1], addr[2], addr[3]);
1222 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1223 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1228 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1233 struct proc *p = curproc;
1234 char *read_or_write;
1237 trap_type &= ~T_USER;
1240 printf("cpuid = %d\n", PCPU_GET(cpuid));
1242 switch (trap_type) {
1245 read_or_write = "write";
1249 case T_BUS_ERR_IFETCH:
1250 read_or_write = "read";
1256 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1257 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n",
1258 msg, p->p_pid, p->p_comm,
1259 p->p_ucred ? p->p_ucred->cr_uid : -1,
1262 (intmax_t)frame->badvaddr);
1264 /* log registers in trap frame */
1265 log_frame_dump(frame);
1267 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1270 * Dump a few words around faulting instruction, if the addres is
1273 if (!(pc & 3) && (pc != frame->badvaddr) &&
1274 (trap_type != T_BUS_ERR_IFETCH) &&
1275 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1276 /* dump page table entry for faulting instruction */
1277 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1278 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1280 addr = (unsigned int *)(intptr_t)pc;
1281 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1283 log(LOG_ERR, "%08x %08x %08x %08x\n",
1284 addr[0], addr[1], addr[2], addr[3]);
1286 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1287 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1290 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1291 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1292 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1297 * Unaligned load/store emulation
1300 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1302 register_t *reg = (register_t *) frame;
1303 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1304 register_t value_msb, value;
1308 * ADDR_ERR faults have higher priority than TLB
1309 * Miss faults. Therefore, it is necessary to
1310 * verify that the faulting address is a valid
1311 * virtual address within the process' address space
1312 * before trying to emulate the unaligned access.
1314 switch (MIPS_INST_OPCODE(inst)) {
1315 case OP_LHU: case OP_LH:
1319 case OP_LWU: case OP_LW:
1328 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1332 if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1337 * Handle LL/SC LLD/SCD.
1339 switch (MIPS_INST_OPCODE(inst)) {
1341 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1342 lbu_macro(value_msb, addr);
1344 lbu_macro(value, addr);
1345 value |= value_msb << 8;
1346 reg[MIPS_INST_RT(inst)] = value;
1347 return (MIPS_LHU_ACCESS);
1350 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1351 lb_macro(value_msb, addr);
1353 lbu_macro(value, addr);
1354 value |= value_msb << 8;
1355 reg[MIPS_INST_RT(inst)] = value;
1356 return (MIPS_LH_ACCESS);
1359 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1360 lwl_macro(value, addr);
1362 lwr_macro(value, addr);
1363 value &= 0xffffffff;
1364 reg[MIPS_INST_RT(inst)] = value;
1365 return (MIPS_LWU_ACCESS);
1368 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1369 lwl_macro(value, addr);
1371 lwr_macro(value, addr);
1372 reg[MIPS_INST_RT(inst)] = value;
1373 return (MIPS_LW_ACCESS);
1375 #if defined(__mips_n32) || defined(__mips_n64)
1377 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1378 ldl_macro(value, addr);
1380 ldr_macro(value, addr);
1381 reg[MIPS_INST_RT(inst)] = value;
1382 return (MIPS_LD_ACCESS);
1386 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1387 value = reg[MIPS_INST_RT(inst)];
1388 value_msb = value >> 8;
1389 sb_macro(value_msb, addr);
1391 sb_macro(value, addr);
1392 return (MIPS_SH_ACCESS);
1395 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1396 value = reg[MIPS_INST_RT(inst)];
1397 swl_macro(value, addr);
1399 swr_macro(value, addr);
1400 return (MIPS_SW_ACCESS);
1402 #if defined(__mips_n32) || defined(__mips_n64)
1404 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1405 value = reg[MIPS_INST_RT(inst)];
1406 sdl_macro(value, addr);
1408 sdr_macro(value, addr);
1409 return (MIPS_SD_ACCESS);
1412 panic("%s: should not be reached.", __func__);
1417 emulate_unaligned_access(struct trapframe *frame, int mode)
1420 int access_type = 0;
1422 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1425 * Fall through if it's instruction fetch exception
1427 if (!((pc & 3) || (pc == frame->badvaddr))) {
1430 * Handle unaligned load and store
1434 * Return access type if the instruction was emulated.
1435 * Otherwise restore pc and fall through.
1437 access_type = mips_unaligned_load_store(frame,
1438 mode, frame->badvaddr, pc);
1441 if (DELAYBRANCH(frame->cause))
1442 frame->pc = MipsEmulateBranch(frame, frame->pc,
1447 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1448 access_name[access_type - 1], (intmax_t)pc,
1449 (intmax_t)frame->badvaddr);