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