trap.c revision 206695
1/*	$OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $	*/
2/* tracked to 1.23 */
3/*-
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1992, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
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.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
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.
23 *
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
34 * SUCH DAMAGE.
35 *
36 * from: Utah Hdr: trap.c 1.32 91/04/06
37 *
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
40 */
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/mips/mips/trap.c 206695 2010-04-16 02:56:24Z jmallett $");
43
44#include "opt_ddb.h"
45#include "opt_global.h"
46#include "opt_ktrace.h"
47
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>
52#include <sys/proc.h>
53#include <sys/kernel.h>
54#include <sys/signalvar.h>
55#include <sys/syscall.h>
56#include <sys/lock.h>
57#include <vm/vm.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>
65#include <sys/user.h>
66#include <sys/buf.h>
67#include <sys/vnode.h>
68#include <sys/pioctl.h>
69#include <sys/sysctl.h>
70#include <sys/syslog.h>
71#include <sys/bus.h>
72#ifdef KTRACE
73#include <sys/ktrace.h>
74#endif
75#include <net/netisr.h>
76
77#include <machine/trap.h>
78#include <machine/psl.h>
79#include <machine/cpu.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/asm.h>
87
88#ifdef DDB
89#include <machine/db_machdep.h>
90#include <ddb/db_sym.h>
91#include <ddb/ddb.h>
92#include <sys/kdb.h>
93#endif
94
95#include <sys/cdefs.h>
96#include <sys/syslog.h>
97
98
99#ifdef TRAP_DEBUG
100int trap_debug = 1;
101#endif
102
103extern unsigned onfault_table[];
104
105static void log_bad_page_fault(char *, struct trapframe *, int);
106static void log_frame_dump(struct trapframe *frame);
107static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
108
109#ifdef TRAP_DEBUG
110static void trap_frame_dump(struct trapframe *frame);
111#endif
112
113void (*machExceptionTable[]) (void)= {
114/*
115 * The kernel exception handlers.
116 */
117	MipsKernIntr,		/* external interrupt */
118	MipsKernGenException,	/* TLB modification */
119	MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
120	MipsTLBInvalidException,/* TLB miss (store) */
121	MipsKernGenException,	/* address error (load or I-fetch) */
122	MipsKernGenException,	/* address error (store) */
123	MipsKernGenException,	/* bus error (I-fetch) */
124	MipsKernGenException,	/* bus error (load or store) */
125	MipsKernGenException,	/* system call */
126	MipsKernGenException,	/* breakpoint */
127	MipsKernGenException,	/* reserved instruction */
128	MipsKernGenException,	/* coprocessor unusable */
129	MipsKernGenException,	/* arithmetic overflow */
130	MipsKernGenException,	/* trap exception */
131	MipsKernGenException,	/* virtual coherence exception inst */
132	MipsKernGenException,	/* floating point exception */
133	MipsKernGenException,	/* reserved */
134	MipsKernGenException,	/* reserved */
135	MipsKernGenException,	/* reserved */
136	MipsKernGenException,	/* reserved */
137	MipsKernGenException,	/* reserved */
138	MipsKernGenException,	/* reserved */
139	MipsKernGenException,	/* reserved */
140	MipsKernGenException,	/* watch exception */
141	MipsKernGenException,	/* reserved */
142	MipsKernGenException,	/* reserved */
143	MipsKernGenException,	/* reserved */
144	MipsKernGenException,	/* reserved */
145	MipsKernGenException,	/* reserved */
146	MipsKernGenException,	/* reserved */
147	MipsKernGenException,	/* reserved */
148	MipsKernGenException,	/* virtual coherence exception data */
149/*
150 * The user exception handlers.
151 */
152	MipsUserIntr,		/* 0 */
153	MipsUserGenException,	/* 1 */
154	MipsTLBInvalidException,/* 2 */
155	MipsTLBInvalidException,/* 3 */
156	MipsUserGenException,	/* 4 */
157	MipsUserGenException,	/* 5 */
158	MipsUserGenException,	/* 6 */
159	MipsUserGenException,	/* 7 */
160	MipsUserGenException,	/* 8 */
161	MipsUserGenException,	/* 9 */
162	MipsUserGenException,	/* 10 */
163	MipsUserGenException,	/* 11 */
164	MipsUserGenException,	/* 12 */
165	MipsUserGenException,	/* 13 */
166	MipsUserGenException,	/* 14 */
167	MipsUserGenException,	/* 15 */
168	MipsUserGenException,	/* 16 */
169	MipsUserGenException,	/* 17 */
170	MipsUserGenException,	/* 18 */
171	MipsUserGenException,	/* 19 */
172	MipsUserGenException,	/* 20 */
173	MipsUserGenException,	/* 21 */
174	MipsUserGenException,	/* 22 */
175	MipsUserGenException,	/* 23 */
176	MipsUserGenException,	/* 24 */
177	MipsUserGenException,	/* 25 */
178	MipsUserGenException,	/* 26 */
179	MipsUserGenException,	/* 27 */
180	MipsUserGenException,	/* 28 */
181	MipsUserGenException,	/* 29 */
182	MipsUserGenException,	/* 20 */
183	MipsUserGenException,	/* 31 */
184};
185
186char *trap_type[] = {
187	"external interrupt",
188	"TLB modification",
189	"TLB miss (load or instr. fetch)",
190	"TLB miss (store)",
191	"address error (load or I-fetch)",
192	"address error (store)",
193	"bus error (I-fetch)",
194	"bus error (load or store)",
195	"system call",
196	"breakpoint",
197	"reserved instruction",
198	"coprocessor unusable",
199	"arithmetic overflow",
200	"trap",
201	"virtual coherency instruction",
202	"floating point",
203	"reserved 16",
204	"reserved 17",
205	"reserved 18",
206	"reserved 19",
207	"reserved 20",
208	"reserved 21",
209	"reserved 22",
210	"watch",
211	"reserved 24",
212	"reserved 25",
213	"reserved 26",
214	"reserved 27",
215	"reserved 28",
216	"reserved 29",
217	"reserved 30",
218	"virtual coherency data",
219};
220
221#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
222struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
223#endif
224
225#if defined(DDB) || defined(DEBUG)
226void stacktrace(struct trapframe *);
227void logstacktrace(struct trapframe *);
228#endif
229
230#define	KERNLAND(x) ((int)(x) < 0)
231#define	DELAYBRANCH(x) ((int)(x) < 0)
232
233/*
234 * MIPS load/store access type
235 */
236enum {
237	MIPS_LHU_ACCESS = 1,
238	MIPS_LH_ACCESS,
239	MIPS_LWU_ACCESS,
240	MIPS_LW_ACCESS,
241	MIPS_LD_ACCESS,
242	MIPS_SH_ACCESS,
243	MIPS_SW_ACCESS,
244	MIPS_SD_ACCESS
245};
246
247char *access_name[] = {
248	"Load Halfword Unsigned",
249	"Load Halfword",
250	"Load Word Unsigned",
251	"Load Word",
252	"Load Doubleword",
253	"Store Halfword",
254	"Store Word",
255	"Store Doubleword"
256};
257
258
259static int allow_unaligned_acc = 1;
260
261SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
262    &allow_unaligned_acc, 0, "Allow unaligned accesses");
263
264static int emulate_unaligned_access(struct trapframe *frame);
265
266extern char *syscallnames[];
267
268/*
269 * Handle an exception.
270 * Called from MipsKernGenException() or MipsUserGenException()
271 * when a processor trap occurs.
272 * In the case of a kernel trap, we return the pc where to resume if
273 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
274 */
275u_int
276trap(struct trapframe *trapframe)
277{
278	int type, usermode;
279	int i = 0;
280	unsigned ucode = 0;
281	struct thread *td = curthread;
282	struct proc *p = curproc;
283	vm_prot_t ftype;
284	pt_entry_t *pte;
285	unsigned int entry;
286	pmap_t pmap;
287	int quad_syscall = 0;
288	int access_type;
289	ksiginfo_t ksi;
290	char *msg = NULL;
291	register_t addr = 0;
292
293	trapdebug_enter(trapframe, 0);
294
295	type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
296	if (USERMODE(trapframe->sr)) {
297		type |= T_USER;
298		usermode = 1;
299	} else {
300		usermode = 0;
301	}
302
303	/*
304	 * Enable hardware interrupts if they were on before the trap. If it
305	 * was off disable all so we don't accidently enable it when doing a
306	 * return to userland.
307	 */
308	if (trapframe->sr & SR_INT_ENAB) {
309		set_intr_mask(~(trapframe->sr & ALL_INT_MASK));
310		enableintr();
311	} else {
312		disableintr();
313	}
314
315#ifdef TRAP_DEBUG
316	if (trap_debug) {
317		static vm_offset_t last_badvaddr = 0;
318		static vm_offset_t this_badvaddr = 0;
319		static int count = 0;
320		u_int32_t pid;
321
322		printf("trap type %x (%s - ", type,
323		    trap_type[type & (~T_USER)]);
324
325		if (type & T_USER)
326			printf("user mode)\n");
327		else
328			printf("kernel mode)\n");
329
330#ifdef SMP
331		printf("cpuid = %d\n", PCPU_GET(cpuid));
332#endif
333		MachTLBGetPID(pid);
334		printf("badaddr = 0x%0x, pc = 0x%0x, ra = 0x%0x, sp = 0x%0x, sr = 0x%x, pid = %d, ASID = 0x%x\n",
335		    trapframe->badvaddr, trapframe->pc, trapframe->ra,
336		    trapframe->sp, trapframe->sr,
337		    (curproc ? curproc->p_pid : -1), pid);
338
339		switch (type & ~T_USER) {
340		case T_TLB_MOD:
341		case T_TLB_LD_MISS:
342		case T_TLB_ST_MISS:
343		case T_ADDR_ERR_LD:
344		case T_ADDR_ERR_ST:
345			this_badvaddr = trapframe->badvaddr;
346			break;
347		case T_SYSCALL:
348			this_badvaddr = trapframe->ra;
349			break;
350		default:
351			this_badvaddr = trapframe->pc;
352			break;
353		}
354		if ((last_badvaddr == this_badvaddr) &&
355		    ((type & ~T_USER) != T_SYSCALL)) {
356			if (++count == 3) {
357				trap_frame_dump(trapframe);
358				panic("too many faults at %x\n", last_badvaddr);
359			}
360		} else {
361			last_badvaddr = this_badvaddr;
362			count = 0;
363		}
364	}
365#endif
366	switch (type) {
367	case T_MCHECK:
368#ifdef DDB
369		kdb_trap(type, 0, trapframe);
370#endif
371		panic("MCHECK\n");
372		break;
373	case T_TLB_MOD:
374		/* check for kernel address */
375		if (KERNLAND(trapframe->badvaddr)) {
376			vm_offset_t pa;
377
378			PMAP_LOCK(kernel_pmap);
379			if (!(pte = pmap_segmap(kernel_pmap,
380			    trapframe->badvaddr)))
381				panic("trap: ktlbmod: invalid segmap");
382			pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
383			entry = *pte;
384#ifdef SMP
385			/* It is possible that some other CPU changed m-bit */
386			if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
387				trapframe->badvaddr &= ~PGOFSET;
388				pmap_update_page(kernel_pmap,
389				    trapframe->badvaddr, entry);
390				PMAP_UNLOCK(kernel_pmap);
391				return (trapframe->pc);
392			}
393#else
394			if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
395				panic("trap: ktlbmod: invalid pte");
396#endif
397			if (entry & mips_pg_ro_bit()) {
398				/* write to read only page in the kernel */
399				ftype = VM_PROT_WRITE;
400				PMAP_UNLOCK(kernel_pmap);
401				goto kernel_fault;
402			}
403			entry |= mips_pg_m_bit();
404			*pte = entry;
405			trapframe->badvaddr &= ~PGOFSET;
406			pmap_update_page(kernel_pmap, trapframe->badvaddr, entry);
407			pa = mips_tlbpfn_to_paddr(entry);
408			if (!page_is_managed(pa))
409				panic("trap: ktlbmod: unmanaged page");
410			pmap_set_modified(pa);
411			PMAP_UNLOCK(kernel_pmap);
412			return (trapframe->pc);
413		}
414		/* FALLTHROUGH */
415
416	case T_TLB_MOD + T_USER:
417		{
418			vm_offset_t pa;
419
420			pmap = &p->p_vmspace->vm_pmap;
421
422			PMAP_LOCK(pmap);
423			if (!(pte = pmap_segmap(pmap, trapframe->badvaddr)))
424				panic("trap: utlbmod: invalid segmap");
425			pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
426			entry = *pte;
427#ifdef SMP
428			/* It is possible that some other CPU changed m-bit */
429			if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
430				trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
431				pmap_update_page(pmap, trapframe->badvaddr, entry);
432				PMAP_UNLOCK(pmap);
433				goto out;
434			}
435#else
436			if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
437				panic("trap: utlbmod: invalid pte");
438			}
439#endif
440
441			if (entry & mips_pg_ro_bit()) {
442				/* write to read only page */
443				ftype = VM_PROT_WRITE;
444				PMAP_UNLOCK(pmap);
445				goto dofault;
446			}
447			entry |= mips_pg_m_bit();
448			*pte = entry;
449			trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
450			pmap_update_page(pmap, trapframe->badvaddr, entry);
451			trapframe->badvaddr |= (pmap->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT);
452			pa = mips_tlbpfn_to_paddr(entry);
453			if (!page_is_managed(pa))
454				panic("trap: utlbmod: unmanaged page");
455			pmap_set_modified(pa);
456
457			PMAP_UNLOCK(pmap);
458			if (!usermode) {
459				return (trapframe->pc);
460			}
461			goto out;
462		}
463
464	case T_TLB_LD_MISS:
465	case T_TLB_ST_MISS:
466		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
467		/* check for kernel address */
468		if (KERNLAND(trapframe->badvaddr)) {
469			vm_offset_t va;
470			int rv;
471
472	kernel_fault:
473			va = trunc_page((vm_offset_t)trapframe->badvaddr);
474			rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
475			if (rv == KERN_SUCCESS)
476				return (trapframe->pc);
477			if ((i = td->td_pcb->pcb_onfault) != 0) {
478				td->td_pcb->pcb_onfault = 0;
479				return (onfault_table[i]);
480			}
481			goto err;
482		}
483		/*
484		 * It is an error for the kernel to access user space except
485		 * through the copyin/copyout routines.
486		 */
487		if ((i = td->td_pcb->pcb_onfault) == 0)
488			goto err;
489		/* check for fuswintr() or suswintr() getting a page fault */
490		if (i == 4) {
491			return (onfault_table[i]);
492		}
493		goto dofault;
494
495	case T_TLB_LD_MISS + T_USER:
496		ftype = VM_PROT_READ;
497		goto dofault;
498
499	case T_TLB_ST_MISS + T_USER:
500		ftype = VM_PROT_WRITE;
501dofault:
502		{
503			vm_offset_t va;
504			struct vmspace *vm;
505			vm_map_t map;
506			int rv = 0;
507
508			vm = p->p_vmspace;
509			map = &vm->vm_map;
510			va = trunc_page((vm_offset_t)trapframe->badvaddr);
511			if ((vm_offset_t)trapframe->badvaddr >= VM_MIN_KERNEL_ADDRESS) {
512				/*
513				 * Don't allow user-mode faults in kernel
514				 * address space.
515				 */
516				goto nogo;
517			}
518
519			/*
520			 * Keep swapout from messing with us during this
521			 * critical time.
522			 */
523			PROC_LOCK(p);
524			++p->p_lock;
525			PROC_UNLOCK(p);
526
527			rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
528
529			PROC_LOCK(p);
530			--p->p_lock;
531			PROC_UNLOCK(p);
532#ifdef VMFAULT_TRACE
533			printf("vm_fault(%p (pmap %p), %x (%x), %x, %d) -> %x at pc %x\n",
534			    map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, VM_FAULT_NORMAL,
535			    rv, trapframe->pc);
536#endif
537
538			if (rv == KERN_SUCCESS) {
539				if (!usermode) {
540					return (trapframe->pc);
541				}
542				goto out;
543			}
544	nogo:
545			if (!usermode) {
546				if ((i = td->td_pcb->pcb_onfault) != 0) {
547					td->td_pcb->pcb_onfault = 0;
548					return (onfault_table[i]);
549				}
550				goto err;
551			}
552			ucode = ftype;
553			i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
554			addr = trapframe->pc;
555
556			msg = "BAD_PAGE_FAULT";
557			log_bad_page_fault(msg, trapframe, type);
558
559			break;
560		}
561
562	case T_ADDR_ERR_LD + T_USER:	/* misaligned or kseg access */
563	case T_ADDR_ERR_ST + T_USER:	/* misaligned or kseg access */
564		if (allow_unaligned_acc) {
565			int mode;
566
567			if (type == (T_ADDR_ERR_LD + T_USER))
568				mode = VM_PROT_READ;
569			else
570				mode = VM_PROT_WRITE;
571
572			/*
573			 * ADDR_ERR faults have higher priority than TLB
574			 * Miss faults.  Therefore, it is necessary to
575			 * verify that the faulting address is a valid
576			 * virtual address within the process' address space
577			 * before trying to emulate the unaligned access.
578			 */
579			if (useracc((caddr_t)
580			    (((vm_offset_t)trapframe->badvaddr) &
581			    ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
582				access_type = emulate_unaligned_access(
583				    trapframe);
584				if (access_type != 0)
585					goto out;
586			}
587		}
588		msg = "ADDRESS_ERR";
589
590		/* FALL THROUGH */
591
592	case T_BUS_ERR_IFETCH + T_USER:	/* BERR asserted to cpu */
593	case T_BUS_ERR_LD_ST + T_USER:	/* BERR asserted to cpu */
594		ucode = 0;	/* XXX should be VM_PROT_something */
595		i = SIGBUS;
596		addr = trapframe->pc;
597		if (!msg)
598			msg = "BUS_ERR";
599		log_bad_page_fault(msg, trapframe, type);
600		break;
601
602	case T_SYSCALL + T_USER:
603		{
604			struct trapframe *locr0 = td->td_frame;
605			struct sysent *callp;
606			unsigned int code;
607			int nargs, nsaved;
608			register_t args[8];
609
610			/*
611			 * note: PCPU_LAZY_INC() can only be used if we can
612			 * afford occassional inaccuracy in the count.
613			 */
614			PCPU_LAZY_INC(cnt.v_syscall);
615			if (td->td_ucred != p->p_ucred)
616				cred_update_thread(td);
617#ifdef KSE
618			if (p->p_flag & P_SA)
619				thread_user_enter(td);
620#endif
621			/* compute next PC after syscall instruction */
622			td->td_pcb->pcb_tpc = trapframe->pc;	/* Remember if restart */
623			if (DELAYBRANCH(trapframe->cause)) {	/* Check BD bit */
624				locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
625				    0);
626			} else {
627				locr0->pc += sizeof(int);
628			}
629			code = locr0->v0;
630
631			switch (code) {
632			case SYS_syscall:
633				/*
634				 * Code is first argument, followed by
635				 * actual args.
636				 */
637				code = locr0->a0;
638				args[0] = locr0->a1;
639				args[1] = locr0->a2;
640				args[2] = locr0->a3;
641				nsaved = 3;
642				break;
643
644			case SYS___syscall:
645				/*
646				 * Like syscall, but code is a quad, so as
647				 * to maintain quad alignment for the rest
648				 * of the arguments.
649				 */
650				if (_QUAD_LOWWORD == 0) {
651					code = locr0->a0;
652				} else {
653					code = locr0->a1;
654				}
655				args[0] = locr0->a2;
656				args[1] = locr0->a3;
657				nsaved = 2;
658				quad_syscall = 1;
659				break;
660
661			default:
662				args[0] = locr0->a0;
663				args[1] = locr0->a1;
664				args[2] = locr0->a2;
665				args[3] = locr0->a3;
666				nsaved = 4;
667			}
668#ifdef TRAP_DEBUG
669			printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
670#endif
671
672			if (p->p_sysent->sv_mask)
673				code &= p->p_sysent->sv_mask;
674
675			if (code >= p->p_sysent->sv_size)
676				callp = &p->p_sysent->sv_table[0];
677			else
678				callp = &p->p_sysent->sv_table[code];
679
680			nargs = callp->sy_narg;
681
682			if (nargs > nsaved) {
683				i = copyin((caddr_t)(locr0->sp +
684				    4 * sizeof(register_t)), (caddr_t)&args[nsaved],
685				    (u_int)(nargs - nsaved) * sizeof(register_t));
686				if (i) {
687					locr0->v0 = i;
688					locr0->a3 = 1;
689#ifdef KTRACE
690					if (KTRPOINT(td, KTR_SYSCALL))
691						ktrsyscall(code, nargs, args);
692#endif
693					goto done;
694				}
695			}
696#ifdef KTRACE
697			if (KTRPOINT(td, KTR_SYSCALL))
698				ktrsyscall(code, nargs, args);
699#endif
700			td->td_retval[0] = 0;
701			td->td_retval[1] = locr0->v1;
702
703#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
704			if (trp == trapdebug)
705				trapdebug[TRAPSIZE - 1].code = code;
706			else
707				trp[-1].code = code;
708#endif
709			STOPEVENT(p, S_SCE, nargs);
710
711			PTRACESTOP_SC(p, td, S_PT_SCE);
712			i = (*callp->sy_call) (td, args);
713#if 0
714			/*
715			 * Reinitialize proc pointer `p' as it may be
716			 * different if this is a child returning from fork
717			 * syscall.
718			 */
719			td = curthread;
720			locr0 = td->td_frame;
721#endif
722			trapdebug_enter(locr0, -code);
723			cpu_set_syscall_retval(td, i);
724
725			/*
726			 * The sync'ing of I & D caches for SYS_ptrace() is
727			 * done by procfs_domem() through procfs_rwmem()
728			 * instead of being done here under a special check
729			 * for SYS_ptrace().
730			 */
731	done:
732			/*
733			 * Check for misbehavior.
734			 */
735			WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
736			    (code >= 0 && code < SYS_MAXSYSCALL) ?
737			    syscallnames[code] : "???");
738			KASSERT(td->td_critnest == 0,
739			    ("System call %s returning in a critical section",
740			    (code >= 0 && code < SYS_MAXSYSCALL) ?
741			    syscallnames[code] : "???"));
742			KASSERT(td->td_locks == 0,
743			    ("System call %s returning with %d locks held",
744			    (code >= 0 && code < SYS_MAXSYSCALL) ?
745			    syscallnames[code] : "???",
746			    td->td_locks));
747			userret(td, trapframe);
748#ifdef KTRACE
749			if (KTRPOINT(td, KTR_SYSRET))
750				ktrsysret(code, i, td->td_retval[0]);
751#endif
752			/*
753			 * This works because errno is findable through the
754			 * register set.  If we ever support an emulation
755			 * where this is not the case, this code will need
756			 * to be revisited.
757			 */
758			STOPEVENT(p, S_SCX, code);
759
760			PTRACESTOP_SC(p, td, S_PT_SCX);
761
762			mtx_assert(&Giant, MA_NOTOWNED);
763			return (trapframe->pc);
764		}
765
766#ifdef DDB
767	case T_BREAK:
768		kdb_trap(type, 0, trapframe);
769		return (trapframe->pc);
770#endif
771
772	case T_BREAK + T_USER:
773		{
774			uintptr_t va, instr;
775
776			/* compute address of break instruction */
777			va = trapframe->pc;
778			if (DELAYBRANCH(trapframe->cause))
779				va += sizeof(int);
780
781			/* read break instruction */
782			instr = fuword((caddr_t)va);
783#if 0
784			printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
785			    p->p_comm, p->p_pid, instr, trapframe->pc,
786			    p->p_md.md_ss_addr, p->p_md.md_ss_instr);	/* XXX */
787#endif
788			if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
789				i = SIGTRAP;
790				addr = trapframe->pc;
791				break;
792			}
793			/*
794			 * The restoration of the original instruction and
795			 * the clearing of the berakpoint will be done later
796			 * by the call to ptrace_clear_single_step() in
797			 * issignal() when SIGTRAP is processed.
798			 */
799			addr = trapframe->pc;
800			i = SIGTRAP;
801			break;
802		}
803
804	case T_IWATCH + T_USER:
805	case T_DWATCH + T_USER:
806		{
807			uintptr_t va;
808
809			/* compute address of trapped instruction */
810			va = trapframe->pc;
811			if (DELAYBRANCH(trapframe->cause))
812				va += sizeof(int);
813			printf("watch exception @ %p\n", (void *)va);
814			i = SIGTRAP;
815			addr = va;
816			break;
817		}
818
819	case T_TRAP + T_USER:
820		{
821			uintptr_t va, instr;
822			struct trapframe *locr0 = td->td_frame;
823
824			/* compute address of trap instruction */
825			va = trapframe->pc;
826			if (DELAYBRANCH(trapframe->cause))
827				va += sizeof(int);
828			/* read break instruction */
829			instr = fuword((caddr_t)va);
830
831			if (DELAYBRANCH(trapframe->cause)) {	/* Check BD bit */
832				locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
833				    0);
834			} else {
835				locr0->pc += sizeof(int);
836			}
837			addr = va;
838			i = SIGEMT;	/* Stuff it with something for now */
839			break;
840		}
841
842	case T_RES_INST + T_USER:
843		i = SIGILL;
844		addr = trapframe->pc;
845		break;
846	case T_C2E:
847	case T_C2E + T_USER:
848		goto err;
849		break;
850	case T_COP_UNUSABLE:
851		goto err;
852		break;
853	case T_COP_UNUSABLE + T_USER:
854#if !defined(CPU_HAVEFPU)
855		/* FP (COP1) instruction */
856		if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
857			i = SIGILL;
858			break;
859		}
860#endif
861		if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
862			i = SIGILL;	/* only FPU instructions allowed */
863			break;
864		}
865		addr = trapframe->pc;
866		MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
867		PCPU_SET(fpcurthread, td);
868		td->td_frame->sr |= SR_COP_1_BIT;
869		td->td_md.md_flags |= MDTD_FPUSED;
870		goto out;
871
872	case T_FPE:
873#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
874		trapDump("fpintr");
875#else
876		printf("FPU Trap: PC %x CR %x SR %x\n",
877		    trapframe->pc, trapframe->cause, trapframe->sr);
878		goto err;
879#endif
880
881	case T_FPE + T_USER:
882		MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
883		goto out;
884
885	case T_OVFLOW + T_USER:
886		i = SIGFPE;
887		addr = trapframe->pc;
888		break;
889
890	case T_ADDR_ERR_LD:	/* misaligned access */
891	case T_ADDR_ERR_ST:	/* misaligned access */
892#ifdef TRAP_DEBUG
893		printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
894		    trapframe->badvaddr);
895#endif
896		/* Only allow emulation on a user address */
897		if (allow_unaligned_acc &&
898		    ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
899			int mode;
900
901			if (type == T_ADDR_ERR_LD)
902				mode = VM_PROT_READ;
903			else
904				mode = VM_PROT_WRITE;
905
906			/*
907			 * ADDR_ERR faults have higher priority than TLB
908			 * Miss faults.  Therefore, it is necessary to
909			 * verify that the faulting address is a valid
910			 * virtual address within the process' address space
911			 * before trying to emulate the unaligned access.
912			 */
913			if (useracc((caddr_t)
914			    (((vm_offset_t)trapframe->badvaddr) &
915			    ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
916				access_type = emulate_unaligned_access(
917				    trapframe);
918				if (access_type != 0) {
919					return (trapframe->pc);
920				}
921			}
922		}
923		/* FALLTHROUGH */
924
925	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
926		if ((i = td->td_pcb->pcb_onfault) != 0) {
927			td->td_pcb->pcb_onfault = 0;
928			return (onfault_table[i]);
929		}
930		/* FALLTHROUGH */
931
932	default:
933err:
934
935#if !defined(SMP) && defined(DEBUG)
936		stacktrace(!usermode ? trapframe : td->td_frame);
937		trapDump("trap");
938#endif
939#ifdef SMP
940		printf("cpu:%d-", PCPU_GET(cpuid));
941#endif
942		printf("Trap cause = %d (%s - ", type,
943		    trap_type[type & (~T_USER)]);
944
945		if (type & T_USER)
946			printf("user mode)\n");
947		else
948			printf("kernel mode)\n");
949
950#ifdef TRAP_DEBUG
951		printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
952		       trapframe->badvaddr, trapframe->pc, trapframe->ra,
953		       trapframe->sr);
954#endif
955
956#ifdef KDB
957		if (debugger_on_panic || kdb_active) {
958			kdb_trap(type, 0, trapframe);
959		}
960#endif
961		panic("trap");
962	}
963	td->td_frame->pc = trapframe->pc;
964	td->td_frame->cause = trapframe->cause;
965	td->td_frame->badvaddr = trapframe->badvaddr;
966	ksiginfo_init_trap(&ksi);
967	ksi.ksi_signo = i;
968	ksi.ksi_code = ucode;
969	ksi.ksi_addr = (void *)addr;
970	ksi.ksi_trapno = type;
971	trapsignal(td, &ksi);
972out:
973
974	/*
975	 * Note: we should only get here if returning to user mode.
976	 */
977	userret(td, trapframe);
978	mtx_assert(&Giant, MA_NOTOWNED);
979	return (trapframe->pc);
980}
981
982#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
983void
984trapDump(char *msg)
985{
986	int i, s;
987
988	s = disableintr();
989	printf("trapDump(%s)\n", msg);
990	for (i = 0; i < TRAPSIZE; i++) {
991		if (trp == trapdebug) {
992			trp = &trapdebug[TRAPSIZE - 1];
993		} else {
994			trp--;
995		}
996
997		if (trp->cause == 0)
998			break;
999
1000		printf("%s: ADR %x PC %x CR %x SR %x\n",
1001		    trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
1002		    trp->vadr, trp->pc, trp->cause, trp->status);
1003
1004		printf("   RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
1005	}
1006	restoreintr(s);
1007}
1008
1009#endif
1010
1011
1012/*
1013 * Return the resulting PC as if the branch was executed.
1014 */
1015uintptr_t
1016MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1017    uintptr_t instptr)
1018{
1019	InstFmt inst;
1020	register_t *regsPtr = (register_t *) framePtr;
1021	uintptr_t retAddr = 0;
1022	int condition;
1023
1024#define	GetBranchDest(InstPtr, inst) \
1025	(InstPtr + 4 + ((short)inst.IType.imm << 2))
1026
1027
1028	if (instptr) {
1029		if (instptr < MIPS_KSEG0_START)
1030			inst.word = fuword32((void *)instptr);
1031		else
1032			inst = *(InstFmt *) instptr;
1033	} else {
1034		if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1035			inst.word = fuword32((void *)instPC);
1036		else
1037			inst = *(InstFmt *) instPC;
1038	}
1039
1040	switch ((int)inst.JType.op) {
1041	case OP_SPECIAL:
1042		switch ((int)inst.RType.func) {
1043		case OP_JR:
1044		case OP_JALR:
1045			retAddr = regsPtr[inst.RType.rs];
1046			break;
1047
1048		default:
1049			retAddr = instPC + 4;
1050			break;
1051		}
1052		break;
1053
1054	case OP_BCOND:
1055		switch ((int)inst.IType.rt) {
1056		case OP_BLTZ:
1057		case OP_BLTZL:
1058		case OP_BLTZAL:
1059		case OP_BLTZALL:
1060			if ((int)(regsPtr[inst.RType.rs]) < 0)
1061				retAddr = GetBranchDest(instPC, inst);
1062			else
1063				retAddr = instPC + 8;
1064			break;
1065
1066		case OP_BGEZ:
1067		case OP_BGEZL:
1068		case OP_BGEZAL:
1069		case OP_BGEZALL:
1070			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1071				retAddr = GetBranchDest(instPC, inst);
1072			else
1073				retAddr = instPC + 8;
1074			break;
1075
1076		case OP_TGEI:
1077		case OP_TGEIU:
1078		case OP_TLTI:
1079		case OP_TLTIU:
1080		case OP_TEQI:
1081		case OP_TNEI:
1082			retAddr = instPC + 4;	/* Like syscall... */
1083			break;
1084
1085		default:
1086			panic("MipsEmulateBranch: Bad branch cond");
1087		}
1088		break;
1089
1090	case OP_J:
1091	case OP_JAL:
1092		retAddr = (inst.JType.target << 2) |
1093		    ((unsigned)(instPC + 4) & 0xF0000000);
1094		break;
1095
1096	case OP_BEQ:
1097	case OP_BEQL:
1098		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1099			retAddr = GetBranchDest(instPC, inst);
1100		else
1101			retAddr = instPC + 8;
1102		break;
1103
1104	case OP_BNE:
1105	case OP_BNEL:
1106		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1107			retAddr = GetBranchDest(instPC, inst);
1108		else
1109			retAddr = instPC + 8;
1110		break;
1111
1112	case OP_BLEZ:
1113	case OP_BLEZL:
1114		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1115			retAddr = GetBranchDest(instPC, inst);
1116		else
1117			retAddr = instPC + 8;
1118		break;
1119
1120	case OP_BGTZ:
1121	case OP_BGTZL:
1122		if ((int)(regsPtr[inst.RType.rs]) > 0)
1123			retAddr = GetBranchDest(instPC, inst);
1124		else
1125			retAddr = instPC + 8;
1126		break;
1127
1128	case OP_COP1:
1129		switch (inst.RType.rs) {
1130		case OP_BCx:
1131		case OP_BCy:
1132			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1133				condition = fpcCSR & FPC_COND_BIT;
1134			else
1135				condition = !(fpcCSR & FPC_COND_BIT);
1136			if (condition)
1137				retAddr = GetBranchDest(instPC, inst);
1138			else
1139				retAddr = instPC + 8;
1140			break;
1141
1142		default:
1143			retAddr = instPC + 4;
1144		}
1145		break;
1146
1147	default:
1148		retAddr = instPC + 4;
1149	}
1150	return (retAddr);
1151}
1152
1153
1154#if defined(DDB) || defined(DEBUG)
1155/*
1156 * Print a stack backtrace.
1157 */
1158void
1159stacktrace(struct trapframe *regs)
1160{
1161	stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1162}
1163#endif
1164
1165static void
1166log_frame_dump(struct trapframe *frame)
1167{
1168	log(LOG_ERR, "Trapframe Register Dump:\n");
1169	log(LOG_ERR, "\tzero: %p\tat: %p\tv0: %p\tv1: %p\n",
1170	    (void *)0, (void *)frame->ast, (void *)frame->v0, (void *)frame->v1);
1171
1172	log(LOG_ERR, "\ta0: %p\ta1: %p\ta2: %p\ta3: %p\n",
1173	    (void *)frame->a0, (void *)frame->a1, (void *)frame->a2, (void *)frame->a3);
1174
1175	log(LOG_ERR, "\tt0: %p\tt1: %p\tt2: %p\tt3: %p\n",
1176	    (void *)frame->t0, (void *)frame->t1, (void *)frame->t2, (void *)frame->t3);
1177
1178	log(LOG_ERR, "\tt4: %p\tt5: %p\tt6: %p\tt7: %p\n",
1179	    (void *)frame->t4, (void *)frame->t5, (void *)frame->t6, (void *)frame->t7);
1180
1181	log(LOG_ERR, "\tt8: %p\tt9: %p\ts0: %p\ts1: %p\n",
1182	    (void *)frame->t8, (void *)frame->t9, (void *)frame->s0, (void *)frame->s1);
1183
1184	log(LOG_ERR, "\ts2: %p\ts3: %p\ts4: %p\ts5: %p\n",
1185	    (void *)frame->s2, (void *)frame->s3, (void *)frame->s4, (void *)frame->s5);
1186
1187	log(LOG_ERR, "\ts6: %p\ts7: %p\tk0: %p\tk1: %p\n",
1188	    (void *)frame->s6, (void *)frame->s7, (void *)frame->k0, (void *)frame->k1);
1189
1190	log(LOG_ERR, "\tgp: %p\tsp: %p\ts8: %p\tra: %p\n",
1191	    (void *)frame->gp, (void *)frame->sp, (void *)frame->s8, (void *)frame->ra);
1192
1193	log(LOG_ERR, "\tsr: %p\tmullo: %p\tmulhi: %p\tbadvaddr: %p\n",
1194	    (void *)frame->sr, (void *)frame->mullo, (void *)frame->mulhi, (void *)frame->badvaddr);
1195
1196#ifdef IC_REG
1197	log(LOG_ERR, "\tcause: %p\tpc: %p\tic: %p\n",
1198	    (void *)frame->cause, (void *)frame->pc, (void *)frame->ic);
1199#else
1200	log(LOG_ERR, "\tcause: %p\tpc: %p\n",
1201	    (void *)frame->cause, (void *)frame->pc);
1202#endif
1203}
1204
1205#ifdef TRAP_DEBUG
1206static void
1207trap_frame_dump(struct trapframe *frame)
1208{
1209	printf("Trapframe Register Dump:\n");
1210	printf("\tzero: %p\tat: %p\tv0: %p\tv1: %p\n",
1211	    (void *)0, (void *)frame->ast, (void *)frame->v0, (void *)frame->v1);
1212
1213	printf("\ta0: %p\ta1: %p\ta2: %p\ta3: %p\n",
1214	    (void *)frame->a0, (void *)frame->a1, (void *)frame->a2, (void *)frame->a3);
1215
1216	printf("\tt0: %p\tt1: %p\tt2: %p\tt3: %p\n",
1217	    (void *)frame->t0, (void *)frame->t1, (void *)frame->t2, (void *)frame->t3);
1218
1219	printf("\tt4: %p\tt5: %p\tt6: %p\tt7: %p\n",
1220	    (void *)frame->t4, (void *)frame->t5, (void *)frame->t6, (void *)frame->t7);
1221
1222	printf("\tt8: %p\tt9: %p\ts0: %p\ts1: %p\n",
1223	    (void *)frame->t8, (void *)frame->t9, (void *)frame->s0, (void *)frame->s1);
1224
1225	printf("\ts2: %p\ts3: %p\ts4: %p\ts5: %p\n",
1226	    (void *)frame->s2, (void *)frame->s3, (void *)frame->s4, (void *)frame->s5);
1227
1228	printf("\ts6: %p\ts7: %p\tk0: %p\tk1: %p\n",
1229	    (void *)frame->s6, (void *)frame->s7, (void *)frame->k0, (void *)frame->k1);
1230
1231	printf("\tgp: %p\tsp: %p\ts8: %p\tra: %p\n",
1232	    (void *)frame->gp, (void *)frame->sp, (void *)frame->s8, (void *)frame->ra);
1233
1234	printf("\tsr: %p\tmullo: %p\tmulhi: %p\tbadvaddr: %p\n",
1235	    (void *)frame->sr, (void *)frame->mullo, (void *)frame->mulhi, (void *)frame->badvaddr);
1236
1237#ifdef IC_REG
1238	printf("\tcause: %p\tpc: %p\tic: %p\n",
1239	    (void *)frame->cause, (void *)frame->pc, (void *)frame->ic);
1240#else
1241	printf("\tcause: %p\tpc: %p\n",
1242	    (void *)frame->cause, (void *)frame->pc);
1243#endif
1244}
1245
1246#endif
1247
1248
1249static void
1250get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1251{
1252	pt_entry_t *ptep;
1253	pd_entry_t *pdep;
1254	struct proc *p = curproc;
1255
1256	pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
1257	if (*pdep)
1258		ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1259	else
1260		ptep = (pt_entry_t *)0;
1261
1262	*pdepp = pdep;
1263	*ptepp = ptep;
1264}
1265
1266
1267static void
1268log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1269{
1270	pt_entry_t *ptep;
1271	pd_entry_t *pdep;
1272	unsigned int *addr;
1273	struct proc *p = curproc;
1274	char *read_or_write;
1275	register_t pc;
1276
1277	trap_type &= ~T_USER;
1278
1279#ifdef SMP
1280	printf("cpuid = %d\n", PCPU_GET(cpuid));
1281#endif
1282	switch (trap_type) {
1283	case T_TLB_ST_MISS:
1284	case T_ADDR_ERR_ST:
1285		read_or_write = "write";
1286		break;
1287	case T_TLB_LD_MISS:
1288	case T_ADDR_ERR_LD:
1289	case T_BUS_ERR_IFETCH:
1290		read_or_write = "read";
1291		break;
1292	default:
1293		read_or_write = "";
1294	}
1295
1296	pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1297	log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %p got a %s fault at %p\n",
1298	    msg, p->p_pid, p->p_comm,
1299	    p->p_ucred ? p->p_ucred->cr_uid : -1,
1300	    (void *)pc,
1301	    read_or_write,
1302	    (void *)frame->badvaddr);
1303
1304	/* log registers in trap frame */
1305	log_frame_dump(frame);
1306
1307	get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1308
1309	/*
1310	 * Dump a few words around faulting instruction, if the addres is
1311	 * valid.
1312	 */
1313	if (!(pc & 3) && (pc != frame->badvaddr) &&
1314	    (trap_type != T_BUS_ERR_IFETCH) &&
1315	    useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1316		/* dump page table entry for faulting instruction */
1317		log(LOG_ERR, "Page table info for pc address %p: pde = %p, pte = 0x%lx\n",
1318		    (void *)pc, *pdep, ptep ? *ptep : 0);
1319
1320		addr = (unsigned int *)pc;
1321		log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1322		    addr);
1323		log(LOG_ERR, "%08x %08x %08x %08x\n",
1324		    addr[0], addr[1], addr[2], addr[3]);
1325	} else {
1326		log(LOG_ERR, "pc address %p is inaccessible, pde = 0x%p, pte = 0x%lx\n",
1327		    (void *)pc, *pdep, ptep ? *ptep : 0);
1328	}
1329	/*	panic("Bad trap");*/
1330}
1331
1332
1333/*
1334 * Unaligned load/store emulation
1335 */
1336static int
1337mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
1338{
1339	register_t *reg = (register_t *) frame;
1340	u_int32_t inst = *((u_int32_t *) pc);
1341	u_int32_t value_msb, value;
1342	int access_type = 0;
1343
1344	switch (MIPS_INST_OPCODE(inst)) {
1345	case OP_LHU:
1346		lbu_macro(value_msb, addr);
1347		addr += 1;
1348		lbu_macro(value, addr);
1349		value |= value_msb << 8;
1350		reg[MIPS_INST_RT(inst)] = value;
1351		access_type = MIPS_LHU_ACCESS;
1352		break;
1353
1354	case OP_LH:
1355		lb_macro(value_msb, addr);
1356		addr += 1;
1357		lbu_macro(value, addr);
1358		value |= value_msb << 8;
1359		reg[MIPS_INST_RT(inst)] = value;
1360		access_type = MIPS_LH_ACCESS;
1361		break;
1362
1363	case OP_LWU:
1364		lwl_macro(value, addr);
1365		addr += 3;
1366		lwr_macro(value, addr);
1367		value &= 0xffffffff;
1368		reg[MIPS_INST_RT(inst)] = value;
1369		access_type = MIPS_LWU_ACCESS;
1370		break;
1371
1372	case OP_LW:
1373		lwl_macro(value, addr);
1374		addr += 3;
1375		lwr_macro(value, addr);
1376		reg[MIPS_INST_RT(inst)] = value;
1377		access_type = MIPS_LW_ACCESS;
1378		break;
1379
1380	case OP_SH:
1381		value = reg[MIPS_INST_RT(inst)];
1382		value_msb = value >> 8;
1383		sb_macro(value_msb, addr);
1384		addr += 1;
1385		sb_macro(value, addr);
1386		access_type = MIPS_SH_ACCESS;
1387		break;
1388
1389	case OP_SW:
1390		value = reg[MIPS_INST_RT(inst)];
1391		swl_macro(value, addr);
1392		addr += 3;
1393		swr_macro(value, addr);
1394		access_type = MIPS_SW_ACCESS;
1395		break;
1396
1397	default:
1398		break;
1399	}
1400
1401	return access_type;
1402}
1403
1404
1405static int
1406emulate_unaligned_access(struct trapframe *frame)
1407{
1408	register_t pc;
1409	int access_type = 0;
1410
1411	pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1412
1413	/*
1414	 * Fall through if it's instruction fetch exception
1415	 */
1416	if (!((pc & 3) || (pc == frame->badvaddr))) {
1417
1418		/*
1419		 * Handle unaligned load and store
1420		 */
1421
1422		/*
1423		 * Return access type if the instruction was emulated.
1424		 * Otherwise restore pc and fall through.
1425		 */
1426		access_type = mips_unaligned_load_store(frame,
1427		    frame->badvaddr, pc);
1428
1429		if (access_type) {
1430			if (DELAYBRANCH(frame->cause))
1431				frame->pc = MipsEmulateBranch(frame, frame->pc,
1432				    0, 0);
1433			else
1434				frame->pc += 4;
1435
1436			log(LOG_INFO, "Unaligned %s: pc=%p, badvaddr=%p\n",
1437			    access_name[access_type - 1], (void *)pc,
1438			    (void *)frame->badvaddr);
1439		}
1440	}
1441	return access_type;
1442}
1443