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