1 /* $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $ */
4 * SPDX-License-Identifier: BSD-3-Clause
6 * Copyright (c) 1988 University of Utah.
7 * Copyright (c) 1992, 1993
8 * The Regents of the University of California. All rights reserved.
10 * This code is derived from software contributed to Berkeley by
11 * the Systems Programming Group of the University of Utah Computer
12 * Science Department and Ralph Campbell.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * from: Utah Hdr: trap.c 1.32 91/04/06
40 * from: @(#)trap.c 8.5 (Berkeley) 1/11/94
41 * JNPR: trap.c,v 1.13.2.2 2007/08/29 10:03:49 girish
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
47 #include "opt_ktrace.h"
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/sysent.h>
53 #include <sys/kernel.h>
55 #include <sys/signalvar.h>
56 #include <sys/syscall.h>
59 #include <vm/vm_extern.h>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_page.h>
62 #include <vm/vm_map.h>
63 #include <vm/vm_param.h>
64 #include <sys/vmmeter.h>
65 #include <sys/ptrace.h>
68 #include <sys/vnode.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/cpuinfo.h>
80 #include <machine/pte.h>
81 #include <machine/pmap.h>
82 #include <machine/md_var.h>
83 #include <machine/mips_opcode.h>
84 #include <machine/frame.h>
85 #include <machine/regnum.h>
86 #include <machine/tls.h>
89 #include <machine/db_machdep.h>
90 #include <ddb/db_sym.h>
96 #include <sys/dtrace_bsd.h>
101 SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
102 &trap_debug, 0, "Debug information on all traps");
105 #define lbu_macro(data, addr) \
106 __asm __volatile ("lbu %0, 0x0(%1)" \
107 : "=r" (data) /* outputs */ \
108 : "r" (addr)); /* inputs */
110 #define lb_macro(data, addr) \
111 __asm __volatile ("lb %0, 0x0(%1)" \
112 : "=r" (data) /* outputs */ \
113 : "r" (addr)); /* inputs */
115 #define lwl_macro(data, addr) \
116 __asm __volatile ("lwl %0, 0x0(%1)" \
117 : "+r" (data) /* outputs */ \
118 : "r" (addr)); /* inputs */
120 #define lwr_macro(data, addr) \
121 __asm __volatile ("lwr %0, 0x0(%1)" \
122 : "+r" (data) /* outputs */ \
123 : "r" (addr)); /* inputs */
125 #define ldl_macro(data, addr) \
126 __asm __volatile ("ldl %0, 0x0(%1)" \
127 : "+r" (data) /* outputs */ \
128 : "r" (addr)); /* inputs */
130 #define ldr_macro(data, addr) \
131 __asm __volatile ("ldr %0, 0x0(%1)" \
132 : "+r" (data) /* outputs */ \
133 : "r" (addr)); /* inputs */
135 #define sb_macro(data, addr) \
136 __asm __volatile ("sb %0, 0x0(%1)" \
138 : "r" (data), "r" (addr)); /* inputs */
140 #define swl_macro(data, addr) \
141 __asm __volatile ("swl %0, 0x0(%1)" \
143 : "r" (data), "r" (addr)); /* inputs */
145 #define swr_macro(data, addr) \
146 __asm __volatile ("swr %0, 0x0(%1)" \
148 : "r" (data), "r" (addr)); /* inputs */
150 #define sdl_macro(data, addr) \
151 __asm __volatile ("sdl %0, 0x0(%1)" \
153 : "r" (data), "r" (addr)); /* inputs */
155 #define sdr_macro(data, addr) \
156 __asm __volatile ("sdr %0, 0x0(%1)" \
158 : "r" (data), "r" (addr)); /* inputs */
160 static void log_illegal_instruction(const char *, struct trapframe *);
161 static void log_bad_page_fault(char *, struct trapframe *, int);
162 static void log_frame_dump(struct trapframe *frame);
163 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
165 int (*dtrace_invop_jump_addr)(struct trapframe *);
168 static void trap_frame_dump(struct trapframe *frame);
171 void (*machExceptionTable[]) (void)= {
173 * The kernel exception handlers.
175 MipsKernIntr, /* external interrupt */
176 MipsKernGenException, /* TLB modification */
177 MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
178 MipsTLBInvalidException,/* TLB miss (store) */
179 MipsKernGenException, /* address error (load or I-fetch) */
180 MipsKernGenException, /* address error (store) */
181 MipsKernGenException, /* bus error (I-fetch) */
182 MipsKernGenException, /* bus error (load or store) */
183 MipsKernGenException, /* system call */
184 MipsKernGenException, /* breakpoint */
185 MipsKernGenException, /* reserved instruction */
186 MipsKernGenException, /* coprocessor unusable */
187 MipsKernGenException, /* arithmetic overflow */
188 MipsKernGenException, /* trap exception */
189 MipsKernGenException, /* virtual coherence exception inst */
190 MipsKernGenException, /* floating point exception */
191 MipsKernGenException, /* reserved */
192 MipsKernGenException, /* reserved */
193 MipsKernGenException, /* reserved */
194 MipsKernGenException, /* reserved */
195 MipsKernGenException, /* reserved */
196 MipsKernGenException, /* reserved */
197 MipsKernGenException, /* reserved */
198 MipsKernGenException, /* watch exception */
199 MipsKernGenException, /* reserved */
200 MipsKernGenException, /* reserved */
201 MipsKernGenException, /* reserved */
202 MipsKernGenException, /* reserved */
203 MipsKernGenException, /* reserved */
204 MipsKernGenException, /* reserved */
205 MipsKernGenException, /* reserved */
206 MipsKernGenException, /* virtual coherence exception data */
208 * The user exception handlers.
210 MipsUserIntr, /* 0 */
211 MipsUserGenException, /* 1 */
212 MipsTLBInvalidException,/* 2 */
213 MipsTLBInvalidException,/* 3 */
214 MipsUserGenException, /* 4 */
215 MipsUserGenException, /* 5 */
216 MipsUserGenException, /* 6 */
217 MipsUserGenException, /* 7 */
218 MipsUserGenException, /* 8 */
219 MipsUserGenException, /* 9 */
220 MipsUserGenException, /* 10 */
221 MipsUserGenException, /* 11 */
222 MipsUserGenException, /* 12 */
223 MipsUserGenException, /* 13 */
224 MipsUserGenException, /* 14 */
225 MipsUserGenException, /* 15 */
226 MipsUserGenException, /* 16 */
227 MipsUserGenException, /* 17 */
228 MipsUserGenException, /* 18 */
229 MipsUserGenException, /* 19 */
230 MipsUserGenException, /* 20 */
231 MipsUserGenException, /* 21 */
232 MipsUserGenException, /* 22 */
233 MipsUserGenException, /* 23 */
234 MipsUserGenException, /* 24 */
235 MipsUserGenException, /* 25 */
236 MipsUserGenException, /* 26 */
237 MipsUserGenException, /* 27 */
238 MipsUserGenException, /* 28 */
239 MipsUserGenException, /* 29 */
240 MipsUserGenException, /* 20 */
241 MipsUserGenException, /* 31 */
244 char *trap_type[] = {
245 "external interrupt",
247 "TLB miss (load or instr. fetch)",
249 "address error (load or I-fetch)",
250 "address error (store)",
251 "bus error (I-fetch)",
252 "bus error (load or store)",
255 "reserved instruction",
256 "coprocessor unusable",
257 "arithmetic overflow",
259 "virtual coherency instruction",
276 "virtual coherency data",
279 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
280 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
283 #define KERNLAND(x) ((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS)
284 #define DELAYBRANCH(x) ((x) & MIPS_CR_BR_DELAY)
287 * MIPS load/store access type
300 char *access_name[] = {
301 "Load Halfword Unsigned",
303 "Load Word Unsigned",
312 #include <machine/octeon_cop2.h>
315 static int allow_unaligned_acc = 1;
317 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
318 &allow_unaligned_acc, 0, "Allow unaligned accesses");
321 * FP emulation is assumed to work on O32, but the code is outdated and crufty
322 * enough that it's a more sensible default to have it disabled when using
323 * other ABIs. At the very least, it needs a lot of help in using
324 * type-semantic ABI-oblivious macros for everything it does.
326 #if defined(__mips_o32)
327 static int emulate_fp = 1;
329 static int emulate_fp = 0;
331 SYSCTL_INT(_machdep, OID_AUTO, emulate_fp, CTLFLAG_RW,
332 &emulate_fp, 0, "Emulate unimplemented FPU instructions");
334 static int emulate_unaligned_access(struct trapframe *frame, int mode);
336 extern void fswintrberr(void); /* XXX */
339 cpu_fetch_syscall_args(struct thread *td)
341 struct trapframe *locr0;
342 struct sysentvec *se;
343 struct syscall_args *sa;
346 locr0 = td->td_frame;
349 bzero(sa->args, sizeof(sa->args));
351 /* compute next PC after syscall instruction */
352 td->td_pcb->pcb_tpc = sa->trapframe->pc; /* Remember if restart */
353 if (DELAYBRANCH(sa->trapframe->cause)) /* Check BD bit */
354 locr0->pc = MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0);
356 locr0->pc += sizeof(int);
357 sa->code = locr0->v0;
363 * This is an indirect syscall, in which the code is the first argument.
365 #if (!defined(__mips_n32) && !defined(__mips_n64)) || defined(COMPAT_FREEBSD32)
366 if (sa->code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
368 * Like syscall, but code is a quad, so as to maintain alignment
369 * for the rest of the arguments.
371 if (_QUAD_LOWWORD == 0)
372 sa->code = locr0->a0;
374 sa->code = locr0->a1;
375 sa->args[0] = locr0->a2;
376 sa->args[1] = locr0->a3;
382 * This is either not a quad syscall, or is a quad syscall with a
383 * new ABI in which quads fit in a single register.
385 sa->code = locr0->a0;
386 sa->args[0] = locr0->a1;
387 sa->args[1] = locr0->a2;
388 sa->args[2] = locr0->a3;
390 #if defined(__mips_n32) || defined(__mips_n64)
391 #ifdef COMPAT_FREEBSD32
392 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
395 * Non-o32 ABIs support more arguments in registers.
397 sa->args[3] = locr0->a4;
398 sa->args[4] = locr0->a5;
399 sa->args[5] = locr0->a6;
400 sa->args[6] = locr0->a7;
402 #ifdef COMPAT_FREEBSD32
409 * A direct syscall, arguments are just parameters to the syscall.
411 sa->args[0] = locr0->a0;
412 sa->args[1] = locr0->a1;
413 sa->args[2] = locr0->a2;
414 sa->args[3] = locr0->a3;
416 #if defined (__mips_n32) || defined(__mips_n64)
417 #ifdef COMPAT_FREEBSD32
418 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
421 * Non-o32 ABIs support more arguments in registers.
423 sa->args[4] = locr0->a4;
424 sa->args[5] = locr0->a5;
425 sa->args[6] = locr0->a6;
426 sa->args[7] = locr0->a7;
428 #ifdef COMPAT_FREEBSD32
437 printf("SYSCALL #%d pid:%u\n", sa->code, td->td_proc->p_pid);
440 se = td->td_proc->p_sysent;
443 * Shouldn't this go before switching on the code?
446 if (sa->code >= se->sv_size)
447 sa->callp = &se->sv_table[0];
449 sa->callp = &se->sv_table[sa->code];
451 if (sa->callp->sy_narg > nsaved) {
452 #if defined(__mips_n32) || defined(__mips_n64)
455 * Is this right for new ABIs? I think the 4 there
456 * should be 8, size there are 8 registers to skip,
457 * not 4, but I'm not certain.
459 #ifdef COMPAT_FREEBSD32
460 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32))
462 printf("SYSCALL #%u pid:%u, narg (%u) > nsaved (%u).\n",
463 sa->code, td->td_proc->p_pid, sa->callp->sy_narg, nsaved);
465 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
466 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
470 error = 0; /* XXX GCC is awful. */
471 for (i = nsaved; i < sa->callp->sy_narg; i++) {
472 error = copyin((caddr_t)(intptr_t)(locr0->sp +
473 (4 + (i - nsaved)) * sizeof(int32_t)),
474 (caddr_t)&arg, sizeof arg);
481 error = copyin((caddr_t)(intptr_t)(locr0->sp +
482 4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
483 (u_int)(sa->callp->sy_narg - nsaved) * sizeof(register_t));
492 td->td_retval[0] = 0;
493 td->td_retval[1] = locr0->v1;
501 #include "../../kern/subr_syscall.c"
504 * Handle an exception.
505 * Called from MipsKernGenException() or MipsUserGenException()
506 * when a processor trap occurs.
507 * In the case of a kernel trap, we return the pc where to resume if
508 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
511 trap(struct trapframe *trapframe)
516 struct thread *td = curthread;
517 struct proc *p = curproc;
526 register_t *frame_regs;
528 trapdebug_enter(trapframe, 0);
535 type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
536 if (TRAPF_USERMODE(trapframe)) {
544 * Enable hardware interrupts if they were on before the trap. If it
545 * was off disable all so we don't accidently enable it when doing a
546 * return to userland.
548 if (trapframe->sr & MIPS_SR_INT_IE) {
549 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
557 static vm_offset_t last_badvaddr = 0;
558 static vm_offset_t this_badvaddr = 0;
559 static int count = 0;
562 printf("trap type %x (%s - ", type,
563 trap_type[type & (~T_USER)]);
566 printf("user mode)\n");
568 printf("kernel mode)\n");
571 printf("cpuid = %d\n", PCPU_GET(cpuid));
573 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
574 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
575 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
576 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
577 (curproc ? curproc->p_pid : -1), pid);
579 switch (type & ~T_USER) {
585 this_badvaddr = trapframe->badvaddr;
588 this_badvaddr = trapframe->ra;
591 this_badvaddr = trapframe->pc;
594 if ((last_badvaddr == this_badvaddr) &&
595 ((type & ~T_USER) != T_SYSCALL) &&
596 ((type & ~T_USER) != T_COP_UNUSABLE)) {
598 trap_frame_dump(trapframe);
599 panic("too many faults at %p\n", (void *)last_badvaddr);
602 last_badvaddr = this_badvaddr;
610 * A trap can occur while DTrace executes a probe. Before
611 * executing the probe, DTrace blocks re-scheduling and sets
612 * a flag in its per-cpu flags to indicate that it doesn't
613 * want to fault. On returning from the probe, the no-fault
614 * flag is cleared and finally re-scheduling is enabled.
616 * If the DTrace kernel module has registered a trap handler,
617 * call it and if it returns non-zero, assume that it has
618 * handled the trap and modified the trap frame so that this
619 * function can return normally.
622 * XXXDTRACE: add pid probe handler here (if ever)
625 if (dtrace_trap_func != NULL &&
626 (*dtrace_trap_func)(trapframe, type) != 0)
627 return (trapframe->pc);
634 kdb_trap(type, 0, trapframe);
639 /* check for kernel address */
640 if (KERNLAND(trapframe->badvaddr)) {
641 if (pmap_emulate_modified(kernel_pmap,
642 trapframe->badvaddr) != 0) {
643 ftype = VM_PROT_WRITE;
646 return (trapframe->pc);
650 case T_TLB_MOD + T_USER:
651 pmap = &p->p_vmspace->vm_pmap;
652 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
653 ftype = VM_PROT_WRITE;
657 return (trapframe->pc);
662 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
663 /* check for kernel address */
664 if (KERNLAND(trapframe->badvaddr)) {
669 va = (vm_offset_t)trapframe->badvaddr;
670 rv = vm_fault_trap(kernel_map, va, ftype,
671 VM_FAULT_NORMAL, NULL, NULL);
672 if (rv == KERN_SUCCESS)
673 return (trapframe->pc);
674 if (td->td_pcb->pcb_onfault != NULL) {
675 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
676 td->td_pcb->pcb_onfault = NULL;
683 * It is an error for the kernel to access user space except
684 * through the copyin/copyout routines.
686 if (td->td_pcb->pcb_onfault == NULL)
691 case T_TLB_LD_MISS + T_USER:
692 ftype = VM_PROT_READ;
695 case T_TLB_ST_MISS + T_USER:
696 ftype = VM_PROT_WRITE;
706 va = (vm_offset_t)trapframe->badvaddr;
707 if (KERNLAND(trapframe->badvaddr)) {
709 * Don't allow user-mode faults in kernel
715 rv = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL,
718 * XXXDTRACE: add dtrace_doubletrap_func here?
721 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
722 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
723 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
726 if (rv == KERN_SUCCESS) {
728 return (trapframe->pc);
734 if (td->td_pcb->pcb_onfault != NULL) {
735 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
736 td->td_pcb->pcb_onfault = NULL;
741 addr = trapframe->badvaddr;
743 msg = "BAD_PAGE_FAULT";
744 log_bad_page_fault(msg, trapframe, type);
749 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
750 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
751 if (trapframe->badvaddr < 0 ||
752 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
753 msg = "ADDRESS_SPACE_ERR";
754 } else if (allow_unaligned_acc) {
757 if (type == (T_ADDR_ERR_LD + T_USER))
760 mode = VM_PROT_WRITE;
762 access_type = emulate_unaligned_access(trapframe, mode);
763 if (access_type != 0)
765 msg = "ALIGNMENT_FIX_ERR";
772 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
773 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
774 ucode = 0; /* XXX should be VM_PROT_something */
776 addr = trapframe->pc;
779 log_bad_page_fault(msg, trapframe, type);
782 case T_SYSCALL + T_USER:
784 td->td_sa.trapframe = trapframe;
787 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
788 if (trp == trapdebug)
789 trapdebug[TRAPSIZE - 1].code = td->td_sa.code;
791 trp[-1].code = td->td_sa.code;
793 trapdebug_enter(td->td_frame, -td->td_sa.code);
796 * The sync'ing of I & D caches for SYS_ptrace() is
797 * done by procfs_domem() through procfs_rwmem()
798 * instead of being done here under a special check
802 return (trapframe->pc);
805 #if defined(KDTRACE_HOOKS) || defined(DDB)
808 if (!usermode && dtrace_invop_jump_addr != NULL &&
809 dtrace_invop_jump_addr(trapframe) == 0)
810 return (trapframe->pc);
813 kdb_trap(type, 0, trapframe);
814 return (trapframe->pc);
818 case T_BREAK + T_USER:
826 /* compute address of break instruction */
828 if (DELAYBRANCH(trapframe->cause))
832 if (td->td_md.md_ss_addr != va)
835 /* read break instruction */
836 instr = fuword32((caddr_t)va);
838 if (instr != MIPS_BREAK_SSTEP)
842 "trap: tid %d, single step at %#lx: %#08x",
843 td->td_tid, va, instr);
846 error = ptrace_clear_single_step(td);
854 case T_IWATCH + T_USER:
855 case T_DWATCH + T_USER:
859 /* compute address of trapped instruction */
861 if (DELAYBRANCH(trapframe->cause))
863 printf("watch exception @ %p\n", (void *)va);
870 case T_TRAP + T_USER:
873 struct trapframe *locr0 = td->td_frame;
875 /* compute address of trap instruction */
877 if (DELAYBRANCH(trapframe->cause))
880 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
881 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
884 locr0->pc += sizeof(int);
887 i = SIGEMT; /* Stuff it with something for now */
891 case T_RES_INST + T_USER:
894 inst = *(InstFmt *)(intptr_t)trapframe->pc;
895 switch (inst.RType.op) {
897 switch (inst.RType.func) {
899 /* Register 29 used for TLS */
900 if (inst.RType.rd == 29) {
901 frame_regs = &(trapframe->zero);
902 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
903 frame_regs[inst.RType.rt] += td->td_proc->p_md.md_tls_tcb_offset;
904 trapframe->pc += sizeof(int);
912 log_illegal_instruction("RES_INST", trapframe);
914 addr = trapframe->pc;
923 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
924 /* Handle only COP2 exception */
928 addr = trapframe->pc;
929 /* save userland cop2 context if it has been touched */
930 if ((td->td_md.md_flags & MDTD_COP2USED) &&
931 (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
932 if (td->td_md.md_ucop2)
933 octeon_cop2_save(td->td_md.md_ucop2);
935 panic("COP2 was used in user mode but md_ucop2 is NULL");
938 if (td->td_md.md_cop2 == NULL) {
939 td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
940 if (td->td_md.md_cop2 == NULL)
941 panic("Failed to allocate COP2 context");
942 memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
945 octeon_cop2_restore(td->td_md.md_cop2);
947 /* Make userland re-request its context */
948 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
949 td->td_md.md_flags |= MDTD_COP2USED;
950 td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
951 /* Enable COP2, it will be disabled in cpu_switch */
952 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
953 return (trapframe->pc);
959 case T_COP_UNUSABLE + T_USER:
960 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
962 /* FP (COP1) instruction */
963 if (cpuinfo.fpu_id == 0) {
964 log_illegal_instruction("COP1_UNUSABLE",
969 addr = trapframe->pc;
970 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
971 PCPU_SET(fpcurthread, td);
972 #if defined(__mips_n32) || defined(__mips_n64)
973 td->td_frame->sr |= MIPS_SR_COP_1_BIT | MIPS_SR_FR;
975 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
977 td->td_md.md_flags |= MDTD_FPUSED;
982 addr = trapframe->pc;
983 if ((td->td_md.md_flags & MDTD_COP2USED) &&
984 (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
985 if (td->td_md.md_cop2)
986 octeon_cop2_save(td->td_md.md_cop2);
988 panic("COP2 was used in kernel mode but md_cop2 is NULL");
991 if (td->td_md.md_ucop2 == NULL) {
992 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
993 if (td->td_md.md_ucop2 == NULL)
994 panic("Failed to allocate userland COP2 context");
995 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
998 octeon_cop2_restore(td->td_md.md_ucop2);
1000 td->td_frame->sr |= MIPS_SR_COP_2_BIT;
1001 td->td_md.md_flags |= MDTD_COP2USED;
1002 td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
1007 log_illegal_instruction("COPn_UNUSABLE", trapframe);
1008 i = SIGILL; /* only FPU instructions allowed */
1013 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1016 printf("FPU Trap: PC %#jx CR %x SR %x\n",
1017 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
1021 case T_FPE + T_USER:
1024 addr = trapframe->pc;
1027 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
1030 case T_OVFLOW + T_USER:
1032 addr = trapframe->pc;
1035 case T_ADDR_ERR_LD: /* misaligned access */
1036 case T_ADDR_ERR_ST: /* misaligned access */
1039 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
1040 (intmax_t)trapframe->badvaddr);
1043 /* Only allow emulation on a user address */
1044 if (allow_unaligned_acc &&
1045 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
1048 if (type == T_ADDR_ERR_LD)
1049 mode = VM_PROT_READ;
1051 mode = VM_PROT_WRITE;
1053 access_type = emulate_unaligned_access(trapframe, mode);
1054 if (access_type != 0)
1055 return (trapframe->pc);
1059 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
1060 if (td->td_pcb->pcb_onfault != NULL) {
1061 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
1062 td->td_pcb->pcb_onfault = NULL;
1071 #if !defined(SMP) && defined(DEBUG)
1075 printf("cpu:%d-", PCPU_GET(cpuid));
1077 printf("Trap cause = %d (%s - ", type,
1078 trap_type[type & (~T_USER)]);
1081 printf("user mode)\n");
1083 printf("kernel mode)\n");
1087 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
1088 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
1089 (intmax_t)trapframe->sr);
1093 if (debugger_on_trap) {
1094 kdb_why = KDB_WHY_TRAP;
1095 kdb_trap(type, 0, trapframe);
1096 kdb_why = KDB_WHY_UNSET;
1101 td->td_frame->pc = trapframe->pc;
1102 td->td_frame->cause = trapframe->cause;
1103 td->td_frame->badvaddr = trapframe->badvaddr;
1104 ksiginfo_init_trap(&ksi);
1106 ksi.ksi_code = ucode;
1107 ksi.ksi_addr = (void *)addr;
1108 ksi.ksi_trapno = type & ~T_USER;
1109 trapsignal(td, &ksi);
1113 * Note: we should only get here if returning to user mode.
1115 userret(td, trapframe);
1116 return (trapframe->pc);
1119 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1127 printf("trapDump(%s)\n", msg);
1128 for (i = 0; i < TRAPSIZE; i++) {
1129 if (trp == trapdebug) {
1130 trp = &trapdebug[TRAPSIZE - 1];
1135 if (trp->cause == 0)
1138 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
1139 trap_type[(trp->cause & MIPS_CR_EXC_CODE) >>
1140 MIPS_CR_EXC_CODE_SHIFT],
1141 (intmax_t)trp->vadr, (intmax_t)trp->pc,
1142 (intmax_t)trp->cause, (intmax_t)trp->status);
1144 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
1145 (intmax_t)trp->sp, (int)trp->code);
1152 * Return the resulting PC as if the branch was executed.
1155 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1159 register_t *regsPtr = (register_t *) framePtr;
1160 uintptr_t retAddr = 0;
1163 #define GetBranchDest(InstPtr, inst) \
1164 (InstPtr + 4 + ((short)inst.IType.imm << 2))
1167 if (instptr < MIPS_KSEG0_START)
1168 inst.word = fuword32((void *)instptr);
1170 inst = *(InstFmt *) instptr;
1172 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1173 inst.word = fuword32((void *)instPC);
1175 inst = *(InstFmt *) instPC;
1178 switch ((int)inst.JType.op) {
1180 switch ((int)inst.RType.func) {
1183 retAddr = regsPtr[inst.RType.rs];
1187 retAddr = instPC + 4;
1193 switch ((int)inst.IType.rt) {
1198 if ((int)(regsPtr[inst.RType.rs]) < 0)
1199 retAddr = GetBranchDest(instPC, inst);
1201 retAddr = instPC + 8;
1208 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1209 retAddr = GetBranchDest(instPC, inst);
1211 retAddr = instPC + 8;
1220 retAddr = instPC + 4; /* Like syscall... */
1224 panic("MipsEmulateBranch: Bad branch cond");
1230 retAddr = (inst.JType.target << 2) |
1231 ((unsigned)(instPC + 4) & 0xF0000000);
1236 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1237 retAddr = GetBranchDest(instPC, inst);
1239 retAddr = instPC + 8;
1244 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1245 retAddr = GetBranchDest(instPC, inst);
1247 retAddr = instPC + 8;
1252 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1253 retAddr = GetBranchDest(instPC, inst);
1255 retAddr = instPC + 8;
1260 if ((int)(regsPtr[inst.RType.rs]) > 0)
1261 retAddr = GetBranchDest(instPC, inst);
1263 retAddr = instPC + 8;
1267 switch (inst.RType.rs) {
1270 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1271 condition = fpcCSR & MIPS_FPU_COND_BIT;
1273 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1275 retAddr = GetBranchDest(instPC, inst);
1277 retAddr = instPC + 8;
1281 retAddr = instPC + 4;
1286 retAddr = instPC + 4;
1292 log_frame_dump(struct trapframe *frame)
1294 log(LOG_ERR, "Trapframe Register Dump:\n");
1295 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1296 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1298 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1299 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1301 #if defined(__mips_n32) || defined(__mips_n64)
1302 log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
1303 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1305 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1306 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1308 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1309 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1311 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1312 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1314 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1315 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1317 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1318 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1320 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1321 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1323 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1324 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1326 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1327 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1329 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1330 (intmax_t)frame->cause, (intmax_t)frame->pc);
1335 trap_frame_dump(struct trapframe *frame)
1337 printf("Trapframe Register Dump:\n");
1338 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1339 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1341 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1342 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1343 #if defined(__mips_n32) || defined(__mips_n64)
1344 printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
1345 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1347 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1348 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1350 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1351 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1353 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1354 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1356 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1357 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1359 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1360 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1362 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1363 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1365 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1366 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1368 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1369 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1371 printf("\tcause: %#jx\tpc: %#jx\n",
1372 (intmax_t)frame->cause, (intmax_t)frame->pc);
1378 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1382 struct proc *p = curproc;
1384 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1386 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1388 ptep = (pt_entry_t *)0;
1395 log_illegal_instruction(const char *msg, struct trapframe *frame)
1399 unsigned int *addr, instr[4];
1408 printf("cpuid = %d\n", PCPU_GET(cpuid));
1410 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1411 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
1412 msg, p->p_pid, (long)td->td_tid, p->p_comm,
1413 p->p_ucred ? p->p_ucred->cr_uid : -1,
1415 (intmax_t)frame->ra);
1417 /* log registers in trap frame */
1418 log_frame_dump(frame);
1420 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1423 * Dump a few words around faulting instruction, if the addres is
1426 addr = (unsigned int *)(intptr_t)pc;
1427 if ((pc & 3) == 0 && copyin(addr, instr, sizeof(instr)) == 0) {
1428 /* dump page table entry for faulting instruction */
1429 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1430 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1432 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1434 log(LOG_ERR, "%08x %08x %08x %08x\n",
1435 instr[0], instr[1], instr[2], instr[3]);
1437 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1438 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1443 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1447 unsigned int *addr, instr[4];
1450 char *read_or_write;
1453 trap_type &= ~T_USER;
1459 printf("cpuid = %d\n", PCPU_GET(cpuid));
1461 switch (trap_type) {
1465 read_or_write = "write";
1469 case T_BUS_ERR_IFETCH:
1470 read_or_write = "read";
1473 read_or_write = "unknown";
1476 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1477 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
1478 "(type %#x) at %#jx\n",
1479 msg, p->p_pid, (long)td->td_tid, p->p_comm,
1480 p->p_ucred ? p->p_ucred->cr_uid : -1,
1484 (intmax_t)frame->badvaddr);
1486 /* log registers in trap frame */
1487 log_frame_dump(frame);
1489 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1492 * Dump a few words around faulting instruction, if the addres is
1495 addr = (unsigned int *)(intptr_t)pc;
1496 if ((pc & 3) == 0 && pc != frame->badvaddr &&
1497 trap_type != T_BUS_ERR_IFETCH &&
1498 copyin((caddr_t)(intptr_t)pc, instr, sizeof(instr)) == 0) {
1499 /* dump page table entry for faulting instruction */
1500 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1501 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1503 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1505 log(LOG_ERR, "%08x %08x %08x %08x\n",
1506 instr[0], instr[1], instr[2], instr[3]);
1508 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1509 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1512 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1513 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1514 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1518 * Unaligned load/store emulation
1521 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1523 register_t *reg = (register_t *) frame;
1524 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1525 register_t value_msb = 0, value = 0;
1529 * ADDR_ERR faults have higher priority than TLB
1530 * Miss faults. Therefore, it is necessary to
1531 * verify that the faulting address is a valid
1532 * virtual address within the process' address space
1533 * before trying to emulate the unaligned access.
1535 switch (MIPS_INST_OPCODE(inst)) {
1536 case OP_LHU: case OP_LH:
1540 case OP_LWU: case OP_LW:
1549 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1553 if (!useracc((void *)rounddown2((vm_offset_t)addr, size), size * 2, mode))
1558 * Handle LL/SC LLD/SCD.
1560 switch (MIPS_INST_OPCODE(inst)) {
1562 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1563 lbu_macro(value_msb, addr);
1565 lbu_macro(value, addr);
1566 value |= value_msb << 8;
1567 reg[MIPS_INST_RT(inst)] = value;
1568 return (MIPS_LHU_ACCESS);
1571 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1572 lb_macro(value_msb, addr);
1574 lbu_macro(value, addr);
1575 value |= value_msb << 8;
1576 reg[MIPS_INST_RT(inst)] = value;
1577 return (MIPS_LH_ACCESS);
1580 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1581 lwl_macro(value, addr);
1583 lwr_macro(value, addr);
1584 value &= 0xffffffff;
1585 reg[MIPS_INST_RT(inst)] = value;
1586 return (MIPS_LWU_ACCESS);
1589 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1590 lwl_macro(value, addr);
1592 lwr_macro(value, addr);
1593 reg[MIPS_INST_RT(inst)] = value;
1594 return (MIPS_LW_ACCESS);
1596 #if defined(__mips_n32) || defined(__mips_n64)
1598 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1599 ldl_macro(value, addr);
1601 ldr_macro(value, addr);
1602 reg[MIPS_INST_RT(inst)] = value;
1603 return (MIPS_LD_ACCESS);
1607 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1608 value = reg[MIPS_INST_RT(inst)];
1609 value_msb = value >> 8;
1610 sb_macro(value_msb, addr);
1612 sb_macro(value, addr);
1613 return (MIPS_SH_ACCESS);
1616 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1617 value = reg[MIPS_INST_RT(inst)];
1618 swl_macro(value, addr);
1620 swr_macro(value, addr);
1621 return (MIPS_SW_ACCESS);
1623 #if defined(__mips_n32) || defined(__mips_n64)
1625 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1626 value = reg[MIPS_INST_RT(inst)];
1627 sdl_macro(value, addr);
1629 sdr_macro(value, addr);
1630 return (MIPS_SD_ACCESS);
1633 panic("%s: should not be reached.", __func__);
1639 static struct timeval unaligned_lasterr;
1640 static int unaligned_curerr;
1642 static int unaligned_pps_log_limit = 4;
1644 SYSCTL_INT(_machdep, OID_AUTO, unaligned_log_pps_limit, CTLFLAG_RWTUN,
1645 &unaligned_pps_log_limit, 0,
1646 "limit number of userland unaligned log messages per second");
1649 emulate_unaligned_access(struct trapframe *frame, int mode)
1652 int access_type = 0;
1653 struct thread *td = curthread;
1654 struct proc *p = curproc;
1656 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1659 * Fall through if it's instruction fetch exception
1661 if (!((pc & 3) || (pc == frame->badvaddr))) {
1663 * Handle unaligned load and store
1667 * Return access type if the instruction was emulated.
1668 * Otherwise restore pc and fall through.
1670 access_type = mips_unaligned_load_store(frame,
1671 mode, frame->badvaddr, pc);
1674 if (DELAYBRANCH(frame->cause))
1675 frame->pc = MipsEmulateBranch(frame, frame->pc,
1680 if (ppsratecheck(&unaligned_lasterr,
1681 &unaligned_curerr, unaligned_pps_log_limit)) {
1682 /* XXX TODO: keep global/tid/pid counters? */
1684 "Unaligned %s: pid=%ld (%s), tid=%ld, "
1685 "pc=%#jx, badvaddr=%#jx\n",
1686 access_name[access_type - 1],
1691 (intmax_t)frame->badvaddr);