trap.c revision 262042
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: stable/10/sys/mips/mips/trap.c 262042 2014-02-17 12:57:13Z avg $");
43
44#include "opt_compat.h"
45#include "opt_ddb.h"
46#include "opt_global.h"
47#include "opt_ktrace.h"
48#include "opt_kdtrace.h"
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/sysent.h>
53#include <sys/proc.h>
54#include <sys/kernel.h>
55#include <sys/signalvar.h>
56#include <sys/syscall.h>
57#include <sys/lock.h>
58#include <vm/vm.h>
59#include <vm/vm_extern.h>
60#include <vm/vm_kern.h>
61#include <vm/vm_page.h>
62#include <vm/vm_map.h>
63#include <vm/vm_param.h>
64#include <sys/vmmeter.h>
65#include <sys/ptrace.h>
66#include <sys/user.h>
67#include <sys/buf.h>
68#include <sys/vnode.h>
69#include <sys/pioctl.h>
70#include <sys/sysctl.h>
71#include <sys/syslog.h>
72#include <sys/bus.h>
73#ifdef KTRACE
74#include <sys/ktrace.h>
75#endif
76#include <net/netisr.h>
77
78#include <machine/trap.h>
79#include <machine/cpu.h>
80#include <machine/pte.h>
81#include <machine/pmap.h>
82#include <machine/md_var.h>
83#include <machine/mips_opcode.h>
84#include <machine/frame.h>
85#include <machine/regnum.h>
86#include <machine/tls.h>
87
88#ifdef DDB
89#include <machine/db_machdep.h>
90#include <ddb/db_sym.h>
91#include <ddb/ddb.h>
92#include <sys/kdb.h>
93#endif
94
95#ifdef KDTRACE_HOOKS
96#include <sys/dtrace_bsd.h>
97
98/*
99 * This is a hook which is initialised by the dtrace module
100 * to handle traps which might occur during DTrace probe
101 * execution.
102 */
103dtrace_trap_func_t	dtrace_trap_func;
104
105dtrace_doubletrap_func_t	dtrace_doubletrap_func;
106
107/*
108 * This is a hook which is initialised by the systrace module
109 * when it is loaded. This keeps the DTrace syscall provider
110 * implementation opaque.
111 */
112systrace_probe_func_t	systrace_probe_func;
113
114/*
115 * These hooks are necessary for the pid and usdt providers.
116 */
117dtrace_pid_probe_ptr_t		dtrace_pid_probe_ptr;
118dtrace_return_probe_ptr_t	dtrace_return_probe_ptr;
119#endif
120
121#ifdef TRAP_DEBUG
122int trap_debug = 0;
123SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
124    &trap_debug, 0, "Debug information on all traps");
125#endif
126
127#define	lbu_macro(data, addr)						\
128	__asm __volatile ("lbu %0, 0x0(%1)"				\
129			: "=r" (data)	/* outputs */			\
130			: "r" (addr));	/* inputs */
131
132#define	lb_macro(data, addr)						\
133	__asm __volatile ("lb %0, 0x0(%1)"				\
134			: "=r" (data)	/* outputs */			\
135			: "r" (addr));	/* inputs */
136
137#define	lwl_macro(data, addr)						\
138	__asm __volatile ("lwl %0, 0x0(%1)"				\
139			: "=r" (data)	/* outputs */			\
140			: "r" (addr));	/* inputs */
141
142#define	lwr_macro(data, addr)						\
143	__asm __volatile ("lwr %0, 0x0(%1)"				\
144			: "=r" (data)	/* outputs */			\
145			: "r" (addr));	/* inputs */
146
147#define	ldl_macro(data, addr)						\
148	__asm __volatile ("ldl %0, 0x0(%1)"				\
149			: "=r" (data)	/* outputs */			\
150			: "r" (addr));	/* inputs */
151
152#define	ldr_macro(data, addr)						\
153	__asm __volatile ("ldr %0, 0x0(%1)"				\
154			: "=r" (data)	/* outputs */			\
155			: "r" (addr));	/* inputs */
156
157#define	sb_macro(data, addr)						\
158	__asm __volatile ("sb %0, 0x0(%1)"				\
159			:				/* outputs */	\
160			: "r" (data), "r" (addr));	/* inputs */
161
162#define	swl_macro(data, addr)						\
163	__asm __volatile ("swl %0, 0x0(%1)"				\
164			: 				/* outputs */	\
165			: "r" (data), "r" (addr));	/* inputs */
166
167#define	swr_macro(data, addr)						\
168	__asm __volatile ("swr %0, 0x0(%1)"				\
169			: 				/* outputs */	\
170			: "r" (data), "r" (addr));	/* inputs */
171
172#define	sdl_macro(data, addr)						\
173	__asm __volatile ("sdl %0, 0x0(%1)"				\
174			: 				/* outputs */	\
175			: "r" (data), "r" (addr));	/* inputs */
176
177#define	sdr_macro(data, addr)						\
178	__asm __volatile ("sdr %0, 0x0(%1)"				\
179			:				/* outputs */	\
180			: "r" (data), "r" (addr));	/* inputs */
181
182static void log_illegal_instruction(const char *, struct trapframe *);
183static void log_bad_page_fault(char *, struct trapframe *, int);
184static void log_frame_dump(struct trapframe *frame);
185static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
186
187#ifdef TRAP_DEBUG
188static void trap_frame_dump(struct trapframe *frame);
189#endif
190
191void (*machExceptionTable[]) (void)= {
192/*
193 * The kernel exception handlers.
194 */
195	MipsKernIntr,		/* external interrupt */
196	MipsKernGenException,	/* TLB modification */
197	MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
198	MipsTLBInvalidException,/* TLB miss (store) */
199	MipsKernGenException,	/* address error (load or I-fetch) */
200	MipsKernGenException,	/* address error (store) */
201	MipsKernGenException,	/* bus error (I-fetch) */
202	MipsKernGenException,	/* bus error (load or store) */
203	MipsKernGenException,	/* system call */
204	MipsKernGenException,	/* breakpoint */
205	MipsKernGenException,	/* reserved instruction */
206	MipsKernGenException,	/* coprocessor unusable */
207	MipsKernGenException,	/* arithmetic overflow */
208	MipsKernGenException,	/* trap exception */
209	MipsKernGenException,	/* virtual coherence exception inst */
210	MipsKernGenException,	/* floating point exception */
211	MipsKernGenException,	/* reserved */
212	MipsKernGenException,	/* reserved */
213	MipsKernGenException,	/* reserved */
214	MipsKernGenException,	/* reserved */
215	MipsKernGenException,	/* reserved */
216	MipsKernGenException,	/* reserved */
217	MipsKernGenException,	/* reserved */
218	MipsKernGenException,	/* watch exception */
219	MipsKernGenException,	/* reserved */
220	MipsKernGenException,	/* reserved */
221	MipsKernGenException,	/* reserved */
222	MipsKernGenException,	/* reserved */
223	MipsKernGenException,	/* reserved */
224	MipsKernGenException,	/* reserved */
225	MipsKernGenException,	/* reserved */
226	MipsKernGenException,	/* virtual coherence exception data */
227/*
228 * The user exception handlers.
229 */
230	MipsUserIntr,		/* 0 */
231	MipsUserGenException,	/* 1 */
232	MipsTLBInvalidException,/* 2 */
233	MipsTLBInvalidException,/* 3 */
234	MipsUserGenException,	/* 4 */
235	MipsUserGenException,	/* 5 */
236	MipsUserGenException,	/* 6 */
237	MipsUserGenException,	/* 7 */
238	MipsUserGenException,	/* 8 */
239	MipsUserGenException,	/* 9 */
240	MipsUserGenException,	/* 10 */
241	MipsUserGenException,	/* 11 */
242	MipsUserGenException,	/* 12 */
243	MipsUserGenException,	/* 13 */
244	MipsUserGenException,	/* 14 */
245	MipsUserGenException,	/* 15 */
246	MipsUserGenException,	/* 16 */
247	MipsUserGenException,	/* 17 */
248	MipsUserGenException,	/* 18 */
249	MipsUserGenException,	/* 19 */
250	MipsUserGenException,	/* 20 */
251	MipsUserGenException,	/* 21 */
252	MipsUserGenException,	/* 22 */
253	MipsUserGenException,	/* 23 */
254	MipsUserGenException,	/* 24 */
255	MipsUserGenException,	/* 25 */
256	MipsUserGenException,	/* 26 */
257	MipsUserGenException,	/* 27 */
258	MipsUserGenException,	/* 28 */
259	MipsUserGenException,	/* 29 */
260	MipsUserGenException,	/* 20 */
261	MipsUserGenException,	/* 31 */
262};
263
264char *trap_type[] = {
265	"external interrupt",
266	"TLB modification",
267	"TLB miss (load or instr. fetch)",
268	"TLB miss (store)",
269	"address error (load or I-fetch)",
270	"address error (store)",
271	"bus error (I-fetch)",
272	"bus error (load or store)",
273	"system call",
274	"breakpoint",
275	"reserved instruction",
276	"coprocessor unusable",
277	"arithmetic overflow",
278	"trap",
279	"virtual coherency instruction",
280	"floating point",
281	"reserved 16",
282	"reserved 17",
283	"reserved 18",
284	"reserved 19",
285	"reserved 20",
286	"reserved 21",
287	"reserved 22",
288	"watch",
289	"reserved 24",
290	"reserved 25",
291	"reserved 26",
292	"reserved 27",
293	"reserved 28",
294	"reserved 29",
295	"reserved 30",
296	"virtual coherency data",
297};
298
299#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
300struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
301#endif
302
303#if defined(DDB) || defined(DEBUG)
304void stacktrace(struct trapframe *);
305void logstacktrace(struct trapframe *);
306#endif
307
308#define	KERNLAND(x)	((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS)
309#define	DELAYBRANCH(x)	((int)(x) < 0)
310
311/*
312 * MIPS load/store access type
313 */
314enum {
315	MIPS_LHU_ACCESS = 1,
316	MIPS_LH_ACCESS,
317	MIPS_LWU_ACCESS,
318	MIPS_LW_ACCESS,
319	MIPS_LD_ACCESS,
320	MIPS_SH_ACCESS,
321	MIPS_SW_ACCESS,
322	MIPS_SD_ACCESS
323};
324
325char *access_name[] = {
326	"Load Halfword Unsigned",
327	"Load Halfword",
328	"Load Word Unsigned",
329	"Load Word",
330	"Load Doubleword",
331	"Store Halfword",
332	"Store Word",
333	"Store Doubleword"
334};
335
336#ifdef	CPU_CNMIPS
337#include <machine/octeon_cop2.h>
338#endif
339
340static int allow_unaligned_acc = 1;
341
342SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
343    &allow_unaligned_acc, 0, "Allow unaligned accesses");
344
345/*
346 * FP emulation is assumed to work on O32, but the code is outdated and crufty
347 * enough that it's a more sensible default to have it disabled when using
348 * other ABIs.  At the very least, it needs a lot of help in using
349 * type-semantic ABI-oblivious macros for everything it does.
350 */
351#if defined(__mips_o32)
352static int emulate_fp = 1;
353#else
354static int emulate_fp = 0;
355#endif
356SYSCTL_INT(_machdep, OID_AUTO, emulate_fp, CTLFLAG_RW,
357    &emulate_fp, 0, "Emulate unimplemented FPU instructions");
358
359static int emulate_unaligned_access(struct trapframe *frame, int mode);
360
361extern void fswintrberr(void); /* XXX */
362
363int
364cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
365{
366	struct trapframe *locr0 = td->td_frame;
367	struct sysentvec *se;
368	int error, nsaved;
369
370	bzero(sa->args, sizeof(sa->args));
371
372	/* compute next PC after syscall instruction */
373	td->td_pcb->pcb_tpc = sa->trapframe->pc; /* Remember if restart */
374	if (DELAYBRANCH(sa->trapframe->cause))	 /* Check BD bit */
375		locr0->pc = MipsEmulateBranch(locr0, sa->trapframe->pc, 0, 0);
376	else
377		locr0->pc += sizeof(int);
378	sa->code = locr0->v0;
379
380	switch (sa->code) {
381	case SYS___syscall:
382	case SYS_syscall:
383		/*
384		 * This is an indirect syscall, in which the code is the first argument.
385		 */
386#if (!defined(__mips_n32) && !defined(__mips_n64)) || defined(COMPAT_FREEBSD32)
387		if (sa->code == SYS___syscall && SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
388			/*
389			 * Like syscall, but code is a quad, so as to maintain alignment
390			 * for the rest of the arguments.
391			 */
392			if (_QUAD_LOWWORD == 0)
393				sa->code = locr0->a0;
394			else
395				sa->code = locr0->a1;
396			sa->args[0] = locr0->a2;
397			sa->args[1] = locr0->a3;
398			nsaved = 2;
399			break;
400		}
401#endif
402		/*
403		 * This is either not a quad syscall, or is a quad syscall with a
404		 * new ABI in which quads fit in a single register.
405		 */
406		sa->code = locr0->a0;
407		sa->args[0] = locr0->a1;
408		sa->args[1] = locr0->a2;
409		sa->args[2] = locr0->a3;
410		nsaved = 3;
411#if defined(__mips_n32) || defined(__mips_n64)
412#ifdef COMPAT_FREEBSD32
413		if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
414#endif
415			/*
416			 * Non-o32 ABIs support more arguments in registers.
417			 */
418			sa->args[3] = locr0->a4;
419			sa->args[4] = locr0->a5;
420			sa->args[5] = locr0->a6;
421			sa->args[6] = locr0->a7;
422			nsaved += 4;
423#ifdef COMPAT_FREEBSD32
424		}
425#endif
426#endif
427		break;
428	default:
429		/*
430		 * A direct syscall, arguments are just parameters to the syscall.
431		 */
432		sa->args[0] = locr0->a0;
433		sa->args[1] = locr0->a1;
434		sa->args[2] = locr0->a2;
435		sa->args[3] = locr0->a3;
436		nsaved = 4;
437#if defined (__mips_n32) || defined(__mips_n64)
438#ifdef COMPAT_FREEBSD32
439		if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
440#endif
441			/*
442			 * Non-o32 ABIs support more arguments in registers.
443			 */
444			sa->args[4] = locr0->a4;
445			sa->args[5] = locr0->a5;
446			sa->args[6] = locr0->a6;
447			sa->args[7] = locr0->a7;
448			nsaved += 4;
449#ifdef COMPAT_FREEBSD32
450		}
451#endif
452#endif
453		break;
454	}
455
456#ifdef TRAP_DEBUG
457	if (trap_debug)
458		printf("SYSCALL #%d pid:%u\n", sa->code, td->td_proc->p_pid);
459#endif
460
461	se = td->td_proc->p_sysent;
462	/*
463	 * XXX
464	 * Shouldn't this go before switching on the code?
465	 */
466	if (se->sv_mask)
467		sa->code &= se->sv_mask;
468
469	if (sa->code >= se->sv_size)
470		sa->callp = &se->sv_table[0];
471	else
472		sa->callp = &se->sv_table[sa->code];
473
474	sa->narg = sa->callp->sy_narg;
475
476	if (sa->narg > nsaved) {
477#if defined(__mips_n32) || defined(__mips_n64)
478		/*
479		 * XXX
480		 * Is this right for new ABIs?  I think the 4 there
481		 * should be 8, size there are 8 registers to skip,
482		 * not 4, but I'm not certain.
483		 */
484#ifdef COMPAT_FREEBSD32
485		if (!SV_PROC_FLAG(td->td_proc, SV_ILP32))
486#endif
487			printf("SYSCALL #%u pid:%u, narg (%u) > nsaved (%u).\n",
488			    sa->code, td->td_proc->p_pid, sa->narg, nsaved);
489#endif
490#if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
491		if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
492			unsigned i;
493			int32_t arg;
494
495			error = 0; /* XXX GCC is awful.  */
496			for (i = nsaved; i < sa->narg; i++) {
497				error = copyin((caddr_t)(intptr_t)(locr0->sp +
498				    (4 + (i - nsaved)) * sizeof(int32_t)),
499				    (caddr_t)&arg, sizeof arg);
500				if (error != 0)
501					break;
502				sa->args[i] = arg;
503			}
504		} else
505#endif
506		error = copyin((caddr_t)(intptr_t)(locr0->sp +
507		    4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
508		   (u_int)(sa->narg - nsaved) * sizeof(register_t));
509		if (error != 0) {
510			locr0->v0 = error;
511			locr0->a3 = 1;
512		}
513	} else
514		error = 0;
515
516	if (error == 0) {
517		td->td_retval[0] = 0;
518		td->td_retval[1] = locr0->v1;
519	}
520
521	return (error);
522}
523
524#undef __FBSDID
525#define __FBSDID(x)
526#include "../../kern/subr_syscall.c"
527
528/*
529 * Handle an exception.
530 * Called from MipsKernGenException() or MipsUserGenException()
531 * when a processor trap occurs.
532 * In the case of a kernel trap, we return the pc where to resume if
533 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
534 */
535register_t
536trap(struct trapframe *trapframe)
537{
538	int type, usermode;
539	int i = 0;
540	unsigned ucode = 0;
541	struct thread *td = curthread;
542	struct proc *p = curproc;
543	vm_prot_t ftype;
544	pmap_t pmap;
545	int access_type;
546	ksiginfo_t ksi;
547	char *msg = NULL;
548	intptr_t addr = 0;
549	register_t pc;
550	int cop;
551	register_t *frame_regs;
552
553	trapdebug_enter(trapframe, 0);
554
555	type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
556	if (TRAPF_USERMODE(trapframe)) {
557		type |= T_USER;
558		usermode = 1;
559	} else {
560		usermode = 0;
561	}
562
563	/*
564	 * Enable hardware interrupts if they were on before the trap. If it
565	 * was off disable all so we don't accidently enable it when doing a
566	 * return to userland.
567	 */
568	if (trapframe->sr & MIPS_SR_INT_IE) {
569		set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
570		intr_enable();
571	} else {
572		intr_disable();
573	}
574
575#ifdef TRAP_DEBUG
576	if (trap_debug) {
577		static vm_offset_t last_badvaddr = 0;
578		static vm_offset_t this_badvaddr = 0;
579		static int count = 0;
580		u_int32_t pid;
581
582		printf("trap type %x (%s - ", type,
583		    trap_type[type & (~T_USER)]);
584
585		if (type & T_USER)
586			printf("user mode)\n");
587		else
588			printf("kernel mode)\n");
589
590#ifdef SMP
591		printf("cpuid = %d\n", PCPU_GET(cpuid));
592#endif
593		pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
594		printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
595		    (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
596		    (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
597		    (curproc ? curproc->p_pid : -1), pid);
598
599		switch (type & ~T_USER) {
600		case T_TLB_MOD:
601		case T_TLB_LD_MISS:
602		case T_TLB_ST_MISS:
603		case T_ADDR_ERR_LD:
604		case T_ADDR_ERR_ST:
605			this_badvaddr = trapframe->badvaddr;
606			break;
607		case T_SYSCALL:
608			this_badvaddr = trapframe->ra;
609			break;
610		default:
611			this_badvaddr = trapframe->pc;
612			break;
613		}
614		if ((last_badvaddr == this_badvaddr) &&
615		    ((type & ~T_USER) != T_SYSCALL)) {
616			if (++count == 3) {
617				trap_frame_dump(trapframe);
618				panic("too many faults at %p\n", (void *)last_badvaddr);
619			}
620		} else {
621			last_badvaddr = this_badvaddr;
622			count = 0;
623		}
624	}
625#endif
626
627#ifdef KDTRACE_HOOKS
628	/*
629	 * A trap can occur while DTrace executes a probe. Before
630	 * executing the probe, DTrace blocks re-scheduling and sets
631	 * a flag in it's per-cpu flags to indicate that it doesn't
632	 * want to fault. On returning from the probe, the no-fault
633	 * flag is cleared and finally re-scheduling is enabled.
634	 *
635	 * If the DTrace kernel module has registered a trap handler,
636	 * call it and if it returns non-zero, assume that it has
637	 * handled the trap and modified the trap frame so that this
638	 * function can return normally.
639	 */
640	/*
641	 * XXXDTRACE: add pid probe handler here (if ever)
642	 */
643	if (!usermode) {
644		if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe, type))
645			return (trapframe->pc);
646	}
647#endif
648
649	switch (type) {
650	case T_MCHECK:
651#ifdef DDB
652		kdb_trap(type, 0, trapframe);
653#endif
654		panic("MCHECK\n");
655		break;
656	case T_TLB_MOD:
657		/* check for kernel address */
658		if (KERNLAND(trapframe->badvaddr)) {
659			if (pmap_emulate_modified(kernel_pmap,
660			    trapframe->badvaddr) != 0) {
661				ftype = VM_PROT_WRITE;
662				goto kernel_fault;
663			}
664			return (trapframe->pc);
665		}
666		/* FALLTHROUGH */
667
668	case T_TLB_MOD + T_USER:
669		pmap = &p->p_vmspace->vm_pmap;
670		if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
671			ftype = VM_PROT_WRITE;
672			goto dofault;
673		}
674		if (!usermode)
675			return (trapframe->pc);
676		goto out;
677
678	case T_TLB_LD_MISS:
679	case T_TLB_ST_MISS:
680		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
681		/* check for kernel address */
682		if (KERNLAND(trapframe->badvaddr)) {
683			vm_offset_t va;
684			int rv;
685
686	kernel_fault:
687			va = trunc_page((vm_offset_t)trapframe->badvaddr);
688			rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
689			if (rv == KERN_SUCCESS)
690				return (trapframe->pc);
691			if (td->td_pcb->pcb_onfault != NULL) {
692				pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
693				td->td_pcb->pcb_onfault = NULL;
694				return (pc);
695			}
696			goto err;
697		}
698
699		/*
700		 * It is an error for the kernel to access user space except
701		 * through the copyin/copyout routines.
702		 */
703		if (td->td_pcb->pcb_onfault == NULL)
704			goto err;
705
706		/* check for fuswintr() or suswintr() getting a page fault */
707		/* XXX There must be a nicer way to do this.  */
708		if (td->td_pcb->pcb_onfault == fswintrberr) {
709			pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
710			td->td_pcb->pcb_onfault = NULL;
711			return (pc);
712		}
713
714		goto dofault;
715
716	case T_TLB_LD_MISS + T_USER:
717		ftype = VM_PROT_READ;
718		goto dofault;
719
720	case T_TLB_ST_MISS + T_USER:
721		ftype = VM_PROT_WRITE;
722dofault:
723		{
724			vm_offset_t va;
725			struct vmspace *vm;
726			vm_map_t map;
727			int rv = 0;
728
729			vm = p->p_vmspace;
730			map = &vm->vm_map;
731			va = trunc_page((vm_offset_t)trapframe->badvaddr);
732			if (KERNLAND(trapframe->badvaddr)) {
733				/*
734				 * Don't allow user-mode faults in kernel
735				 * address space.
736				 */
737				goto nogo;
738			}
739
740			/*
741			 * Keep swapout from messing with us during this
742			 * critical time.
743			 */
744			PROC_LOCK(p);
745			++p->p_lock;
746			PROC_UNLOCK(p);
747
748			rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
749
750			PROC_LOCK(p);
751			--p->p_lock;
752			PROC_UNLOCK(p);
753			/*
754			 * XXXDTRACE: add dtrace_doubletrap_func here?
755			 */
756#ifdef VMFAULT_TRACE
757			printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
758			    map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
759			    ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
760#endif
761
762			if (rv == KERN_SUCCESS) {
763				if (!usermode) {
764					return (trapframe->pc);
765				}
766				goto out;
767			}
768	nogo:
769			if (!usermode) {
770				if (td->td_pcb->pcb_onfault != NULL) {
771					pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
772					td->td_pcb->pcb_onfault = NULL;
773					return (pc);
774				}
775				goto err;
776			}
777			ucode = ftype;
778			i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
779			addr = trapframe->pc;
780
781			msg = "BAD_PAGE_FAULT";
782			log_bad_page_fault(msg, trapframe, type);
783
784			break;
785		}
786
787	case T_ADDR_ERR_LD + T_USER:	/* misaligned or kseg access */
788	case T_ADDR_ERR_ST + T_USER:	/* misaligned or kseg access */
789		if (trapframe->badvaddr < 0 ||
790		    trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
791			msg = "ADDRESS_SPACE_ERR";
792		} else if (allow_unaligned_acc) {
793			int mode;
794
795			if (type == (T_ADDR_ERR_LD + T_USER))
796				mode = VM_PROT_READ;
797			else
798				mode = VM_PROT_WRITE;
799
800			access_type = emulate_unaligned_access(trapframe, mode);
801			if (access_type != 0)
802				goto out;
803			msg = "ALIGNMENT_FIX_ERR";
804		} else {
805			msg = "ADDRESS_ERR";
806		}
807
808		/* FALL THROUGH */
809
810	case T_BUS_ERR_IFETCH + T_USER:	/* BERR asserted to cpu */
811	case T_BUS_ERR_LD_ST + T_USER:	/* BERR asserted to cpu */
812		ucode = 0;	/* XXX should be VM_PROT_something */
813		i = SIGBUS;
814		addr = trapframe->pc;
815		if (!msg)
816			msg = "BUS_ERR";
817		log_bad_page_fault(msg, trapframe, type);
818		break;
819
820	case T_SYSCALL + T_USER:
821		{
822			struct syscall_args sa;
823			int error;
824
825			sa.trapframe = trapframe;
826			error = syscallenter(td, &sa);
827
828#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
829			if (trp == trapdebug)
830				trapdebug[TRAPSIZE - 1].code = sa.code;
831			else
832				trp[-1].code = sa.code;
833#endif
834			trapdebug_enter(td->td_frame, -sa.code);
835
836			/*
837			 * The sync'ing of I & D caches for SYS_ptrace() is
838			 * done by procfs_domem() through procfs_rwmem()
839			 * instead of being done here under a special check
840			 * for SYS_ptrace().
841			 */
842			syscallret(td, error, &sa);
843			return (trapframe->pc);
844		}
845
846#ifdef DDB
847	case T_BREAK:
848		kdb_trap(type, 0, trapframe);
849		return (trapframe->pc);
850#endif
851
852	case T_BREAK + T_USER:
853		{
854			intptr_t va;
855			uint32_t instr;
856
857			/* compute address of break instruction */
858			va = trapframe->pc;
859			if (DELAYBRANCH(trapframe->cause))
860				va += sizeof(int);
861
862			/* read break instruction */
863			instr = fuword32((caddr_t)va);
864#if 0
865			printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
866			    p->p_comm, p->p_pid, instr, trapframe->pc,
867			    p->p_md.md_ss_addr, p->p_md.md_ss_instr);	/* XXX */
868#endif
869			if (td->td_md.md_ss_addr != va ||
870			    instr != MIPS_BREAK_SSTEP) {
871				i = SIGTRAP;
872				addr = trapframe->pc;
873				break;
874			}
875			/*
876			 * The restoration of the original instruction and
877			 * the clearing of the berakpoint will be done later
878			 * by the call to ptrace_clear_single_step() in
879			 * issignal() when SIGTRAP is processed.
880			 */
881			addr = trapframe->pc;
882			i = SIGTRAP;
883			break;
884		}
885
886	case T_IWATCH + T_USER:
887	case T_DWATCH + T_USER:
888		{
889			intptr_t va;
890
891			/* compute address of trapped instruction */
892			va = trapframe->pc;
893			if (DELAYBRANCH(trapframe->cause))
894				va += sizeof(int);
895			printf("watch exception @ %p\n", (void *)va);
896			i = SIGTRAP;
897			addr = va;
898			break;
899		}
900
901	case T_TRAP + T_USER:
902		{
903			intptr_t va;
904			uint32_t instr;
905			struct trapframe *locr0 = td->td_frame;
906
907			/* compute address of trap instruction */
908			va = trapframe->pc;
909			if (DELAYBRANCH(trapframe->cause))
910				va += sizeof(int);
911			/* read break instruction */
912			instr = fuword32((caddr_t)va);
913
914			if (DELAYBRANCH(trapframe->cause)) {	/* Check BD bit */
915				locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
916				    0);
917			} else {
918				locr0->pc += sizeof(int);
919			}
920			addr = va;
921			i = SIGEMT;	/* Stuff it with something for now */
922			break;
923		}
924
925	case T_RES_INST + T_USER:
926		{
927			InstFmt inst;
928			inst = *(InstFmt *)(intptr_t)trapframe->pc;
929			switch (inst.RType.op) {
930			case OP_SPECIAL3:
931				switch (inst.RType.func) {
932				case OP_RDHWR:
933					/* Register 29 used for TLS */
934					if (inst.RType.rd == 29) {
935						frame_regs = &(trapframe->zero);
936						frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
937#if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
938						if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
939							frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE32;
940						else
941#endif
942						frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE;
943						trapframe->pc += sizeof(int);
944						goto out;
945					}
946				break;
947				}
948			break;
949			}
950
951			log_illegal_instruction("RES_INST", trapframe);
952			i = SIGILL;
953			addr = trapframe->pc;
954		}
955		break;
956	case T_C2E:
957	case T_C2E + T_USER:
958		goto err;
959		break;
960	case T_COP_UNUSABLE:
961#ifdef	CPU_CNMIPS
962		cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
963		/* Handle only COP2 exception */
964		if (cop != 2)
965			goto err;
966
967		addr = trapframe->pc;
968		/* save userland cop2 context if it has been touched */
969		if ((td->td_md.md_flags & MDTD_COP2USED) &&
970		    (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
971			if (td->td_md.md_ucop2)
972				octeon_cop2_save(td->td_md.md_ucop2);
973			else
974				panic("COP2 was used in user mode but md_ucop2 is NULL");
975		}
976
977		if (td->td_md.md_cop2 == NULL) {
978			td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
979			if (td->td_md.md_cop2 == NULL)
980				panic("Failed to allocate COP2 context");
981			memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
982		}
983
984		octeon_cop2_restore(td->td_md.md_cop2);
985
986		/* Make userland re-request its context */
987		td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
988		td->td_md.md_flags |= MDTD_COP2USED;
989		td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
990		/* Enable COP2, it will be disabled in cpu_switch */
991		mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
992		return (trapframe->pc);
993#else
994		goto err;
995		break;
996#endif
997
998	case T_COP_UNUSABLE + T_USER:
999		cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
1000		if (cop == 1) {
1001#if !defined(CPU_HAVEFPU)
1002		/* FP (COP1) instruction */
1003			log_illegal_instruction("COP1_UNUSABLE", trapframe);
1004			i = SIGILL;
1005			break;
1006#else
1007			addr = trapframe->pc;
1008			MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
1009			PCPU_SET(fpcurthread, td);
1010			td->td_frame->sr |= MIPS_SR_COP_1_BIT;
1011			td->td_md.md_flags |= MDTD_FPUSED;
1012			goto out;
1013#endif
1014		}
1015#ifdef	CPU_CNMIPS
1016		else  if (cop == 2) {
1017			addr = trapframe->pc;
1018			if ((td->td_md.md_flags & MDTD_COP2USED) &&
1019			    (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
1020				if (td->td_md.md_cop2)
1021					octeon_cop2_save(td->td_md.md_cop2);
1022				else
1023					panic("COP2 was used in kernel mode but md_cop2 is NULL");
1024			}
1025
1026			if (td->td_md.md_ucop2 == NULL) {
1027				td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
1028				if (td->td_md.md_ucop2 == NULL)
1029					panic("Failed to allocate userland COP2 context");
1030				memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
1031			}
1032
1033			octeon_cop2_restore(td->td_md.md_ucop2);
1034
1035			td->td_frame->sr |= MIPS_SR_COP_2_BIT;
1036			td->td_md.md_flags |= MDTD_COP2USED;
1037			td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
1038			goto out;
1039		}
1040#endif
1041		else {
1042			log_illegal_instruction("COPn_UNUSABLE", trapframe);
1043			i = SIGILL;	/* only FPU instructions allowed */
1044			break;
1045		}
1046
1047	case T_FPE:
1048#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1049		trapDump("fpintr");
1050#else
1051		printf("FPU Trap: PC %#jx CR %x SR %x\n",
1052		    (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
1053		goto err;
1054#endif
1055
1056	case T_FPE + T_USER:
1057		if (!emulate_fp) {
1058			i = SIGILL;
1059			addr = trapframe->pc;
1060			break;
1061		}
1062		MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
1063		goto out;
1064
1065	case T_OVFLOW + T_USER:
1066		i = SIGFPE;
1067		addr = trapframe->pc;
1068		break;
1069
1070	case T_ADDR_ERR_LD:	/* misaligned access */
1071	case T_ADDR_ERR_ST:	/* misaligned access */
1072#ifdef TRAP_DEBUG
1073		if (trap_debug) {
1074			printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
1075			    (intmax_t)trapframe->badvaddr);
1076		}
1077#endif
1078		/* Only allow emulation on a user address */
1079		if (allow_unaligned_acc &&
1080		    ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
1081			int mode;
1082
1083			if (type == T_ADDR_ERR_LD)
1084				mode = VM_PROT_READ;
1085			else
1086				mode = VM_PROT_WRITE;
1087
1088			access_type = emulate_unaligned_access(trapframe, mode);
1089			if (access_type != 0)
1090				return (trapframe->pc);
1091		}
1092		/* FALLTHROUGH */
1093
1094	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
1095		if (td->td_pcb->pcb_onfault != NULL) {
1096			pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
1097			td->td_pcb->pcb_onfault = NULL;
1098			return (pc);
1099		}
1100
1101		/* FALLTHROUGH */
1102
1103	default:
1104err:
1105
1106#if !defined(SMP) && defined(DEBUG)
1107		stacktrace(!usermode ? trapframe : td->td_frame);
1108		trapDump("trap");
1109#endif
1110#ifdef SMP
1111		printf("cpu:%d-", PCPU_GET(cpuid));
1112#endif
1113		printf("Trap cause = %d (%s - ", type,
1114		    trap_type[type & (~T_USER)]);
1115
1116		if (type & T_USER)
1117			printf("user mode)\n");
1118		else
1119			printf("kernel mode)\n");
1120
1121#ifdef TRAP_DEBUG
1122		if (trap_debug)
1123			printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
1124			       (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
1125			       (intmax_t)trapframe->sr);
1126#endif
1127
1128#ifdef KDB
1129		if (debugger_on_panic || kdb_active) {
1130			kdb_trap(type, 0, trapframe);
1131		}
1132#endif
1133		panic("trap");
1134	}
1135	td->td_frame->pc = trapframe->pc;
1136	td->td_frame->cause = trapframe->cause;
1137	td->td_frame->badvaddr = trapframe->badvaddr;
1138	ksiginfo_init_trap(&ksi);
1139	ksi.ksi_signo = i;
1140	ksi.ksi_code = ucode;
1141	ksi.ksi_addr = (void *)addr;
1142	ksi.ksi_trapno = type;
1143	trapsignal(td, &ksi);
1144out:
1145
1146	/*
1147	 * Note: we should only get here if returning to user mode.
1148	 */
1149	userret(td, trapframe);
1150	return (trapframe->pc);
1151}
1152
1153#if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1154void
1155trapDump(char *msg)
1156{
1157	register_t s;
1158	int i;
1159
1160	s = intr_disable();
1161	printf("trapDump(%s)\n", msg);
1162	for (i = 0; i < TRAPSIZE; i++) {
1163		if (trp == trapdebug) {
1164			trp = &trapdebug[TRAPSIZE - 1];
1165		} else {
1166			trp--;
1167		}
1168
1169		if (trp->cause == 0)
1170			break;
1171
1172		printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
1173		    trap_type[(trp->cause & MIPS_CR_EXC_CODE) >>
1174			MIPS_CR_EXC_CODE_SHIFT],
1175		    (intmax_t)trp->vadr, (intmax_t)trp->pc,
1176		    (intmax_t)trp->cause, (intmax_t)trp->status);
1177
1178		printf("   RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
1179		    (intmax_t)trp->sp, (int)trp->code);
1180	}
1181	intr_restore(s);
1182}
1183#endif
1184
1185
1186/*
1187 * Return the resulting PC as if the branch was executed.
1188 */
1189uintptr_t
1190MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1191    uintptr_t instptr)
1192{
1193	InstFmt inst;
1194	register_t *regsPtr = (register_t *) framePtr;
1195	uintptr_t retAddr = 0;
1196	int condition;
1197
1198#define	GetBranchDest(InstPtr, inst) \
1199	(InstPtr + 4 + ((short)inst.IType.imm << 2))
1200
1201
1202	if (instptr) {
1203		if (instptr < MIPS_KSEG0_START)
1204			inst.word = fuword32((void *)instptr);
1205		else
1206			inst = *(InstFmt *) instptr;
1207	} else {
1208		if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1209			inst.word = fuword32((void *)instPC);
1210		else
1211			inst = *(InstFmt *) instPC;
1212	}
1213
1214	switch ((int)inst.JType.op) {
1215	case OP_SPECIAL:
1216		switch ((int)inst.RType.func) {
1217		case OP_JR:
1218		case OP_JALR:
1219			retAddr = regsPtr[inst.RType.rs];
1220			break;
1221
1222		default:
1223			retAddr = instPC + 4;
1224			break;
1225		}
1226		break;
1227
1228	case OP_BCOND:
1229		switch ((int)inst.IType.rt) {
1230		case OP_BLTZ:
1231		case OP_BLTZL:
1232		case OP_BLTZAL:
1233		case OP_BLTZALL:
1234			if ((int)(regsPtr[inst.RType.rs]) < 0)
1235				retAddr = GetBranchDest(instPC, inst);
1236			else
1237				retAddr = instPC + 8;
1238			break;
1239
1240		case OP_BGEZ:
1241		case OP_BGEZL:
1242		case OP_BGEZAL:
1243		case OP_BGEZALL:
1244			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1245				retAddr = GetBranchDest(instPC, inst);
1246			else
1247				retAddr = instPC + 8;
1248			break;
1249
1250		case OP_TGEI:
1251		case OP_TGEIU:
1252		case OP_TLTI:
1253		case OP_TLTIU:
1254		case OP_TEQI:
1255		case OP_TNEI:
1256			retAddr = instPC + 4;	/* Like syscall... */
1257			break;
1258
1259		default:
1260			panic("MipsEmulateBranch: Bad branch cond");
1261		}
1262		break;
1263
1264	case OP_J:
1265	case OP_JAL:
1266		retAddr = (inst.JType.target << 2) |
1267		    ((unsigned)(instPC + 4) & 0xF0000000);
1268		break;
1269
1270	case OP_BEQ:
1271	case OP_BEQL:
1272		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1273			retAddr = GetBranchDest(instPC, inst);
1274		else
1275			retAddr = instPC + 8;
1276		break;
1277
1278	case OP_BNE:
1279	case OP_BNEL:
1280		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1281			retAddr = GetBranchDest(instPC, inst);
1282		else
1283			retAddr = instPC + 8;
1284		break;
1285
1286	case OP_BLEZ:
1287	case OP_BLEZL:
1288		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1289			retAddr = GetBranchDest(instPC, inst);
1290		else
1291			retAddr = instPC + 8;
1292		break;
1293
1294	case OP_BGTZ:
1295	case OP_BGTZL:
1296		if ((int)(regsPtr[inst.RType.rs]) > 0)
1297			retAddr = GetBranchDest(instPC, inst);
1298		else
1299			retAddr = instPC + 8;
1300		break;
1301
1302	case OP_COP1:
1303		switch (inst.RType.rs) {
1304		case OP_BCx:
1305		case OP_BCy:
1306			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1307				condition = fpcCSR & MIPS_FPU_COND_BIT;
1308			else
1309				condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1310			if (condition)
1311				retAddr = GetBranchDest(instPC, inst);
1312			else
1313				retAddr = instPC + 8;
1314			break;
1315
1316		default:
1317			retAddr = instPC + 4;
1318		}
1319		break;
1320
1321	default:
1322		retAddr = instPC + 4;
1323	}
1324	return (retAddr);
1325}
1326
1327
1328#if defined(DDB) || defined(DEBUG)
1329/*
1330 * Print a stack backtrace.
1331 */
1332void
1333stacktrace(struct trapframe *regs)
1334{
1335	stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1336}
1337#endif
1338
1339static void
1340log_frame_dump(struct trapframe *frame)
1341{
1342	log(LOG_ERR, "Trapframe Register Dump:\n");
1343	log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1344	    (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1345
1346	log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1347	    (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1348
1349#if defined(__mips_n32) || defined(__mips_n64)
1350	log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
1351	    (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1352
1353	log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1354	    (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1355#else
1356	log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1357	    (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1358
1359	log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1360	    (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1361#endif
1362	log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1363	    (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1364
1365	log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1366	    (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1367
1368	log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1369	    (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1370
1371	log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1372	    (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1373
1374	log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1375	    (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1376
1377#ifdef IC_REG
1378	log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1379	    (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1380#else
1381	log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1382	    (intmax_t)frame->cause, (intmax_t)frame->pc);
1383#endif
1384}
1385
1386#ifdef TRAP_DEBUG
1387static void
1388trap_frame_dump(struct trapframe *frame)
1389{
1390	printf("Trapframe Register Dump:\n");
1391	printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1392	    (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1393
1394	printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1395	    (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1396#if defined(__mips_n32) || defined(__mips_n64)
1397	printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
1398	    (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1399
1400	printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1401	    (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1402#else
1403	printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1404	    (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1405
1406	printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1407	    (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1408#endif
1409	printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1410	    (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1411
1412	printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1413	    (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1414
1415	printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1416	    (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1417
1418	printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1419	    (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1420
1421	printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1422	    (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1423
1424#ifdef IC_REG
1425	printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1426	    (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1427#else
1428	printf("\tcause: %#jx\tpc: %#jx\n",
1429	    (intmax_t)frame->cause, (intmax_t)frame->pc);
1430#endif
1431}
1432
1433#endif
1434
1435
1436static void
1437get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1438{
1439	pt_entry_t *ptep;
1440	pd_entry_t *pdep;
1441	struct proc *p = curproc;
1442
1443	pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1444	if (*pdep)
1445		ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1446	else
1447		ptep = (pt_entry_t *)0;
1448
1449	*pdepp = pdep;
1450	*ptepp = ptep;
1451}
1452
1453static void
1454log_illegal_instruction(const char *msg, struct trapframe *frame)
1455{
1456	pt_entry_t *ptep;
1457	pd_entry_t *pdep;
1458	unsigned int *addr;
1459	struct thread *td;
1460	struct proc *p;
1461	register_t pc;
1462
1463	td = curthread;
1464	p = td->td_proc;
1465
1466#ifdef SMP
1467	printf("cpuid = %d\n", PCPU_GET(cpuid));
1468#endif
1469	pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1470	log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
1471	    msg, p->p_pid, (long)td->td_tid, p->p_comm,
1472	    p->p_ucred ? p->p_ucred->cr_uid : -1,
1473	    (intmax_t)pc,
1474	    (intmax_t)frame->ra);
1475
1476	/* log registers in trap frame */
1477	log_frame_dump(frame);
1478
1479	get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1480
1481	/*
1482	 * Dump a few words around faulting instruction, if the addres is
1483	 * valid.
1484	 */
1485	if (!(pc & 3) &&
1486	    useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1487		/* dump page table entry for faulting instruction */
1488		log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1489		    (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1490
1491		addr = (unsigned int *)(intptr_t)pc;
1492		log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1493		    addr);
1494		log(LOG_ERR, "%08x %08x %08x %08x\n",
1495		    addr[0], addr[1], addr[2], addr[3]);
1496	} else {
1497		log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1498		    (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1499	}
1500}
1501
1502static void
1503log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1504{
1505	pt_entry_t *ptep;
1506	pd_entry_t *pdep;
1507	unsigned int *addr;
1508	struct thread *td;
1509	struct proc *p;
1510	char *read_or_write;
1511	register_t pc;
1512
1513	trap_type &= ~T_USER;
1514
1515	td = curthread;
1516	p = td->td_proc;
1517
1518#ifdef SMP
1519	printf("cpuid = %d\n", PCPU_GET(cpuid));
1520#endif
1521	switch (trap_type) {
1522	case T_TLB_MOD:
1523	case T_TLB_ST_MISS:
1524	case T_ADDR_ERR_ST:
1525		read_or_write = "write";
1526		break;
1527	case T_TLB_LD_MISS:
1528	case T_ADDR_ERR_LD:
1529	case T_BUS_ERR_IFETCH:
1530		read_or_write = "read";
1531		break;
1532	default:
1533		read_or_write = "unknown";
1534	}
1535
1536	pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1537	log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
1538	    "(type %#x) at %#jx\n",
1539	    msg, p->p_pid, (long)td->td_tid, p->p_comm,
1540	    p->p_ucred ? p->p_ucred->cr_uid : -1,
1541	    (intmax_t)pc,
1542	    read_or_write,
1543	    trap_type,
1544	    (intmax_t)frame->badvaddr);
1545
1546	/* log registers in trap frame */
1547	log_frame_dump(frame);
1548
1549	get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1550
1551	/*
1552	 * Dump a few words around faulting instruction, if the addres is
1553	 * valid.
1554	 */
1555	if (!(pc & 3) && (pc != frame->badvaddr) &&
1556	    (trap_type != T_BUS_ERR_IFETCH) &&
1557	    useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1558		/* dump page table entry for faulting instruction */
1559		log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1560		    (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1561
1562		addr = (unsigned int *)(intptr_t)pc;
1563		log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1564		    addr);
1565		log(LOG_ERR, "%08x %08x %08x %08x\n",
1566		    addr[0], addr[1], addr[2], addr[3]);
1567	} else {
1568		log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1569		    (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1570	}
1571
1572	get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1573	log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1574	    (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1575}
1576
1577
1578/*
1579 * Unaligned load/store emulation
1580 */
1581static int
1582mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1583{
1584	register_t *reg = (register_t *) frame;
1585	u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1586	register_t value_msb, value;
1587	unsigned size;
1588
1589	/*
1590	 * ADDR_ERR faults have higher priority than TLB
1591	 * Miss faults.  Therefore, it is necessary to
1592	 * verify that the faulting address is a valid
1593	 * virtual address within the process' address space
1594	 * before trying to emulate the unaligned access.
1595	 */
1596	switch (MIPS_INST_OPCODE(inst)) {
1597	case OP_LHU: case OP_LH:
1598	case OP_SH:
1599		size = 2;
1600		break;
1601	case OP_LWU: case OP_LW:
1602	case OP_SW:
1603		size = 4;
1604		break;
1605	case OP_LD:
1606	case OP_SD:
1607		size = 8;
1608		break;
1609	default:
1610		printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1611		return (0);
1612	}
1613
1614	if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1615		return (0);
1616
1617	/*
1618	 * XXX
1619	 * Handle LL/SC LLD/SCD.
1620	 */
1621	switch (MIPS_INST_OPCODE(inst)) {
1622	case OP_LHU:
1623		KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1624		lbu_macro(value_msb, addr);
1625		addr += 1;
1626		lbu_macro(value, addr);
1627		value |= value_msb << 8;
1628		reg[MIPS_INST_RT(inst)] = value;
1629		return (MIPS_LHU_ACCESS);
1630
1631	case OP_LH:
1632		KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1633		lb_macro(value_msb, addr);
1634		addr += 1;
1635		lbu_macro(value, addr);
1636		value |= value_msb << 8;
1637		reg[MIPS_INST_RT(inst)] = value;
1638		return (MIPS_LH_ACCESS);
1639
1640	case OP_LWU:
1641		KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1642		lwl_macro(value, addr);
1643		addr += 3;
1644		lwr_macro(value, addr);
1645		value &= 0xffffffff;
1646		reg[MIPS_INST_RT(inst)] = value;
1647		return (MIPS_LWU_ACCESS);
1648
1649	case OP_LW:
1650		KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1651		lwl_macro(value, addr);
1652		addr += 3;
1653		lwr_macro(value, addr);
1654		reg[MIPS_INST_RT(inst)] = value;
1655		return (MIPS_LW_ACCESS);
1656
1657#if defined(__mips_n32) || defined(__mips_n64)
1658	case OP_LD:
1659		KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1660		ldl_macro(value, addr);
1661		addr += 7;
1662		ldr_macro(value, addr);
1663		reg[MIPS_INST_RT(inst)] = value;
1664		return (MIPS_LD_ACCESS);
1665#endif
1666
1667	case OP_SH:
1668		KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1669		value = reg[MIPS_INST_RT(inst)];
1670		value_msb = value >> 8;
1671		sb_macro(value_msb, addr);
1672		addr += 1;
1673		sb_macro(value, addr);
1674		return (MIPS_SH_ACCESS);
1675
1676	case OP_SW:
1677		KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1678		value = reg[MIPS_INST_RT(inst)];
1679		swl_macro(value, addr);
1680		addr += 3;
1681		swr_macro(value, addr);
1682		return (MIPS_SW_ACCESS);
1683
1684#if defined(__mips_n32) || defined(__mips_n64)
1685	case OP_SD:
1686		KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1687		value = reg[MIPS_INST_RT(inst)];
1688		sdl_macro(value, addr);
1689		addr += 7;
1690		sdr_macro(value, addr);
1691		return (MIPS_SD_ACCESS);
1692#endif
1693	}
1694	panic("%s: should not be reached.", __func__);
1695}
1696
1697
1698static int
1699emulate_unaligned_access(struct trapframe *frame, int mode)
1700{
1701	register_t pc;
1702	int access_type = 0;
1703
1704	pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1705
1706	/*
1707	 * Fall through if it's instruction fetch exception
1708	 */
1709	if (!((pc & 3) || (pc == frame->badvaddr))) {
1710
1711		/*
1712		 * Handle unaligned load and store
1713		 */
1714
1715		/*
1716		 * Return access type if the instruction was emulated.
1717		 * Otherwise restore pc and fall through.
1718		 */
1719		access_type = mips_unaligned_load_store(frame,
1720		    mode, frame->badvaddr, pc);
1721
1722		if (access_type) {
1723			if (DELAYBRANCH(frame->cause))
1724				frame->pc = MipsEmulateBranch(frame, frame->pc,
1725				    0, 0);
1726			else
1727				frame->pc += 4;
1728
1729			log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1730			    access_name[access_type - 1], (intmax_t)pc,
1731			    (intmax_t)frame->badvaddr);
1732		}
1733	}
1734	return access_type;
1735}
1736