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