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