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