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