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 * 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
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
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 #ifdef KDB
533 if (kdb_active) {
534 kdb_reenter();
535 return (0);
536 }
537 #endif
538 type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
539 if (TRAPF_USERMODE(trapframe)) {
540 type |= T_USER;
541 usermode = 1;
542 } else {
543 usermode = 0;
544 }
545
546 /*
547 * Enable hardware interrupts if they were on before the trap. If it
548 * was off disable all so we don't accidently enable it when doing a
549 * return to userland.
550 */
551 if (trapframe->sr & MIPS_SR_INT_IE) {
552 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
553 intr_enable();
554 } else {
555 intr_disable();
556 }
557
558 #ifdef TRAP_DEBUG
559 if (trap_debug) {
560 static vm_offset_t last_badvaddr = 0;
561 static vm_offset_t this_badvaddr = 0;
562 static int count = 0;
563 u_int32_t pid;
564
565 printf("trap type %x (%s - ", type,
566 trap_type[type & (~T_USER)]);
567
568 if (type & T_USER)
569 printf("user mode)\n");
570 else
571 printf("kernel mode)\n");
572
573 #ifdef SMP
574 printf("cpuid = %d\n", PCPU_GET(cpuid));
575 #endif
576 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
577 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
578 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
579 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
580 (curproc ? curproc->p_pid : -1), pid);
581
582 switch (type & ~T_USER) {
583 case T_TLB_MOD:
584 case T_TLB_LD_MISS:
585 case T_TLB_ST_MISS:
586 case T_ADDR_ERR_LD:
587 case T_ADDR_ERR_ST:
588 this_badvaddr = trapframe->badvaddr;
589 break;
590 case T_SYSCALL:
591 this_badvaddr = trapframe->ra;
592 break;
593 default:
594 this_badvaddr = trapframe->pc;
595 break;
596 }
597 if ((last_badvaddr == this_badvaddr) &&
598 ((type & ~T_USER) != T_SYSCALL)) {
599 if (++count == 3) {
600 trap_frame_dump(trapframe);
601 panic("too many faults at %p\n", (void *)last_badvaddr);
602 }
603 } else {
604 last_badvaddr = this_badvaddr;
605 count = 0;
606 }
607 }
608 #endif
609
610 #ifdef KDTRACE_HOOKS
611 /*
612 * A trap can occur while DTrace executes a probe. Before
613 * executing the probe, DTrace blocks re-scheduling and sets
614 * a flag in it's per-cpu flags to indicate that it doesn't
615 * want to fault. On returning from the probe, the no-fault
616 * flag is cleared and finally re-scheduling is enabled.
617 *
618 * If the DTrace kernel module has registered a trap handler,
619 * call it and if it returns non-zero, assume that it has
620 * handled the trap and modified the trap frame so that this
621 * function can return normally.
622 */
623 /*
624 * XXXDTRACE: add pid probe handler here (if ever)
625 */
626 if (!usermode) {
627 if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe, type))
628 return (trapframe->pc);
629 }
630 #endif
631
632 switch (type) {
633 case T_MCHECK:
634 #ifdef DDB
635 kdb_trap(type, 0, trapframe);
636 #endif
637 panic("MCHECK\n");
638 break;
639 case T_TLB_MOD:
640 /* check for kernel address */
641 if (KERNLAND(trapframe->badvaddr)) {
642 if (pmap_emulate_modified(kernel_pmap,
643 trapframe->badvaddr) != 0) {
644 ftype = VM_PROT_WRITE;
645 goto kernel_fault;
646 }
647 return (trapframe->pc);
648 }
649 /* FALLTHROUGH */
650
651 case T_TLB_MOD + T_USER:
652 pmap = &p->p_vmspace->vm_pmap;
653 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
654 ftype = VM_PROT_WRITE;
655 goto dofault;
656 }
657 if (!usermode)
658 return (trapframe->pc);
659 goto out;
660
661 case T_TLB_LD_MISS:
662 case T_TLB_ST_MISS:
663 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
664 /* check for kernel address */
665 if (KERNLAND(trapframe->badvaddr)) {
666 vm_offset_t va;
667 int rv;
668
669 kernel_fault:
670 va = trunc_page((vm_offset_t)trapframe->badvaddr);
671 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
672 if (rv == KERN_SUCCESS)
673 return (trapframe->pc);
674 if (td->td_pcb->pcb_onfault != NULL) {
675 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
676 td->td_pcb->pcb_onfault = NULL;
677 return (pc);
678 }
679 goto err;
680 }
681
682 /*
683 * It is an error for the kernel to access user space except
684 * through the copyin/copyout routines.
685 */
686 if (td->td_pcb->pcb_onfault == NULL)
687 goto err;
688
689 /* check for fuswintr() or suswintr() getting a page fault */
690 /* XXX There must be a nicer way to do this. */
691 if (td->td_pcb->pcb_onfault == fswintrberr) {
692 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
693 td->td_pcb->pcb_onfault = NULL;
694 return (pc);
695 }
696
697 goto dofault;
698
699 case T_TLB_LD_MISS + T_USER:
700 ftype = VM_PROT_READ;
701 goto dofault;
702
703 case T_TLB_ST_MISS + T_USER:
704 ftype = VM_PROT_WRITE;
705 dofault:
706 {
707 vm_offset_t va;
708 struct vmspace *vm;
709 vm_map_t map;
710 int rv = 0;
711
712 vm = p->p_vmspace;
713 map = &vm->vm_map;
714 va = trunc_page((vm_offset_t)trapframe->badvaddr);
715 if (KERNLAND(trapframe->badvaddr)) {
716 /*
717 * Don't allow user-mode faults in kernel
718 * address space.
719 */
720 goto nogo;
721 }
722
723 /*
724 * Keep swapout from messing with us during this
725 * critical time.
726 */
727 PROC_LOCK(p);
728 ++p->p_lock;
729 PROC_UNLOCK(p);
730
731 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
732
733 PROC_LOCK(p);
734 --p->p_lock;
735 PROC_UNLOCK(p);
736 /*
737 * XXXDTRACE: add dtrace_doubletrap_func here?
738 */
739 #ifdef VMFAULT_TRACE
740 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
741 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
742 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
743 #endif
744
745 if (rv == KERN_SUCCESS) {
746 if (!usermode) {
747 return (trapframe->pc);
748 }
749 goto out;
750 }
751 nogo:
752 if (!usermode) {
753 if (td->td_pcb->pcb_onfault != NULL) {
754 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
755 td->td_pcb->pcb_onfault = NULL;
756 return (pc);
757 }
758 goto err;
759 }
760 ucode = ftype;
761 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
762 addr = trapframe->pc;
763
764 msg = "BAD_PAGE_FAULT";
765 log_bad_page_fault(msg, trapframe, type);
766
767 break;
768 }
769
770 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
771 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
772 if (trapframe->badvaddr < 0 ||
773 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
774 msg = "ADDRESS_SPACE_ERR";
775 } else if (allow_unaligned_acc) {
776 int mode;
777
778 if (type == (T_ADDR_ERR_LD + T_USER))
779 mode = VM_PROT_READ;
780 else
781 mode = VM_PROT_WRITE;
782
783 access_type = emulate_unaligned_access(trapframe, mode);
784 if (access_type != 0)
785 goto out;
786 msg = "ALIGNMENT_FIX_ERR";
787 } else {
788 msg = "ADDRESS_ERR";
789 }
790
791 /* FALL THROUGH */
792
793 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
794 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
795 ucode = 0; /* XXX should be VM_PROT_something */
796 i = SIGBUS;
797 addr = trapframe->pc;
798 if (!msg)
799 msg = "BUS_ERR";
800 log_bad_page_fault(msg, trapframe, type);
801 break;
802
803 case T_SYSCALL + T_USER:
804 {
805 struct syscall_args sa;
806 int error;
807
808 sa.trapframe = trapframe;
809 error = syscallenter(td, &sa);
810
811 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
812 if (trp == trapdebug)
813 trapdebug[TRAPSIZE - 1].code = sa.code;
814 else
815 trp[-1].code = sa.code;
816 #endif
817 trapdebug_enter(td->td_frame, -sa.code);
818
819 /*
820 * The sync'ing of I & D caches for SYS_ptrace() is
821 * done by procfs_domem() through procfs_rwmem()
822 * instead of being done here under a special check
823 * for SYS_ptrace().
824 */
825 syscallret(td, error, &sa);
826 return (trapframe->pc);
827 }
828
829 #ifdef DDB
830 case T_BREAK:
831 kdb_trap(type, 0, trapframe);
832 return (trapframe->pc);
833 #endif
834
835 case T_BREAK + T_USER:
836 {
837 intptr_t va;
838 uint32_t instr;
839
840 /* compute address of break instruction */
841 va = trapframe->pc;
842 if (DELAYBRANCH(trapframe->cause))
843 va += sizeof(int);
844
845 /* read break instruction */
846 instr = fuword32((caddr_t)va);
847 #if 0
848 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
849 p->p_comm, p->p_pid, instr, trapframe->pc,
850 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
851 #endif
852 if (td->td_md.md_ss_addr != va ||
853 instr != MIPS_BREAK_SSTEP) {
854 i = SIGTRAP;
855 addr = trapframe->pc;
856 break;
857 }
858 /*
859 * The restoration of the original instruction and
860 * the clearing of the berakpoint will be done later
861 * by the call to ptrace_clear_single_step() in
862 * issignal() when SIGTRAP is processed.
863 */
864 addr = trapframe->pc;
865 i = SIGTRAP;
866 break;
867 }
868
869 case T_IWATCH + T_USER:
870 case T_DWATCH + T_USER:
871 {
872 intptr_t va;
873
874 /* compute address of trapped instruction */
875 va = trapframe->pc;
876 if (DELAYBRANCH(trapframe->cause))
877 va += sizeof(int);
878 printf("watch exception @ %p\n", (void *)va);
879 i = SIGTRAP;
880 addr = va;
881 break;
882 }
883
884 case T_TRAP + T_USER:
885 {
886 intptr_t va;
887 uint32_t instr;
888 struct trapframe *locr0 = td->td_frame;
889
890 /* compute address of trap instruction */
891 va = trapframe->pc;
892 if (DELAYBRANCH(trapframe->cause))
893 va += sizeof(int);
894 /* read break instruction */
895 instr = fuword32((caddr_t)va);
896
897 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
898 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
899 0);
900 } else {
901 locr0->pc += sizeof(int);
902 }
903 addr = va;
904 i = SIGEMT; /* Stuff it with something for now */
905 break;
906 }
907
908 case T_RES_INST + T_USER:
909 {
910 InstFmt inst;
911 inst = *(InstFmt *)(intptr_t)trapframe->pc;
912 switch (inst.RType.op) {
913 case OP_SPECIAL3:
914 switch (inst.RType.func) {
915 case OP_RDHWR:
916 /* Register 29 used for TLS */
917 if (inst.RType.rd == 29) {
918 frame_regs = &(trapframe->zero);
919 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
920 #if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
921 if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
922 frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE32;
923 else
924 #endif
925 frame_regs[inst.RType.rt] += TLS_TP_OFFSET + TLS_TCB_SIZE;
926 trapframe->pc += sizeof(int);
927 goto out;
928 }
929 break;
930 }
931 break;
932 }
933
934 log_illegal_instruction("RES_INST", trapframe);
935 i = SIGILL;
936 addr = trapframe->pc;
937 }
938 break;
939 case T_C2E:
940 case T_C2E + T_USER:
941 goto err;
942 break;
943 case T_COP_UNUSABLE:
944 #ifdef CPU_CNMIPS
945 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
946 /* Handle only COP2 exception */
947 if (cop != 2)
948 goto err;
949
950 addr = trapframe->pc;
951 /* save userland cop2 context if it has been touched */
952 if ((td->td_md.md_flags & MDTD_COP2USED) &&
953 (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
954 if (td->td_md.md_ucop2)
955 octeon_cop2_save(td->td_md.md_ucop2);
956 else
957 panic("COP2 was used in user mode but md_ucop2 is NULL");
958 }
959
960 if (td->td_md.md_cop2 == NULL) {
961 td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
962 if (td->td_md.md_cop2 == NULL)
963 panic("Failed to allocate COP2 context");
964 memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
965 }
966
967 octeon_cop2_restore(td->td_md.md_cop2);
968
969 /* Make userland re-request its context */
970 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
971 td->td_md.md_flags |= MDTD_COP2USED;
972 td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
973 /* Enable COP2, it will be disabled in cpu_switch */
974 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
975 return (trapframe->pc);
976 #else
977 goto err;
978 break;
979 #endif
980
981 case T_COP_UNUSABLE + T_USER:
982 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
983 if (cop == 1) {
984 #if !defined(CPU_HAVEFPU)
985 /* FP (COP1) instruction */
986 log_illegal_instruction("COP1_UNUSABLE", trapframe);
987 i = SIGILL;
988 break;
989 #else
990 addr = trapframe->pc;
991 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
992 PCPU_SET(fpcurthread, td);
993 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
994 td->td_md.md_flags |= MDTD_FPUSED;
995 goto out;
996 #endif
997 }
998 #ifdef CPU_CNMIPS
999 else if (cop == 2) {
1000 addr = trapframe->pc;
1001 if ((td->td_md.md_flags & MDTD_COP2USED) &&
1002 (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
1003 if (td->td_md.md_cop2)
1004 octeon_cop2_save(td->td_md.md_cop2);
1005 else
1006 panic("COP2 was used in kernel mode but md_cop2 is NULL");
1007 }
1008
1009 if (td->td_md.md_ucop2 == NULL) {
1010 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
1011 if (td->td_md.md_ucop2 == NULL)
1012 panic("Failed to allocate userland COP2 context");
1013 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
1014 }
1015
1016 octeon_cop2_restore(td->td_md.md_ucop2);
1017
1018 td->td_frame->sr |= MIPS_SR_COP_2_BIT;
1019 td->td_md.md_flags |= MDTD_COP2USED;
1020 td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
1021 goto out;
1022 }
1023 #endif
1024 else {
1025 log_illegal_instruction("COPn_UNUSABLE", trapframe);
1026 i = SIGILL; /* only FPU instructions allowed */
1027 break;
1028 }
1029
1030 case T_FPE:
1031 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1032 trapDump("fpintr");
1033 #else
1034 printf("FPU Trap: PC %#jx CR %x SR %x\n",
1035 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
1036 goto err;
1037 #endif
1038
1039 case T_FPE + T_USER:
1040 if (!emulate_fp) {
1041 i = SIGILL;
1042 addr = trapframe->pc;
1043 break;
1044 }
1045 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
1046 goto out;
1047
1048 case T_OVFLOW + T_USER:
1049 i = SIGFPE;
1050 addr = trapframe->pc;
1051 break;
1052
1053 case T_ADDR_ERR_LD: /* misaligned access */
1054 case T_ADDR_ERR_ST: /* misaligned access */
1055 #ifdef TRAP_DEBUG
1056 if (trap_debug) {
1057 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
1058 (intmax_t)trapframe->badvaddr);
1059 }
1060 #endif
1061 /* Only allow emulation on a user address */
1062 if (allow_unaligned_acc &&
1063 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
1064 int mode;
1065
1066 if (type == T_ADDR_ERR_LD)
1067 mode = VM_PROT_READ;
1068 else
1069 mode = VM_PROT_WRITE;
1070
1071 access_type = emulate_unaligned_access(trapframe, mode);
1072 if (access_type != 0)
1073 return (trapframe->pc);
1074 }
1075 /* FALLTHROUGH */
1076
1077 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
1078 if (td->td_pcb->pcb_onfault != NULL) {
1079 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
1080 td->td_pcb->pcb_onfault = NULL;
1081 return (pc);
1082 }
1083
1084 /* FALLTHROUGH */
1085
1086 default:
1087 err:
1088
1089 #if !defined(SMP) && defined(DEBUG)
1090 stacktrace(!usermode ? trapframe : td->td_frame);
1091 trapDump("trap");
1092 #endif
1093 #ifdef SMP
1094 printf("cpu:%d-", PCPU_GET(cpuid));
1095 #endif
1096 printf("Trap cause = %d (%s - ", type,
1097 trap_type[type & (~T_USER)]);
1098
1099 if (type & T_USER)
1100 printf("user mode)\n");
1101 else
1102 printf("kernel mode)\n");
1103
1104 #ifdef TRAP_DEBUG
1105 if (trap_debug)
1106 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
1107 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
1108 (intmax_t)trapframe->sr);
1109 #endif
1110
1111 #ifdef KDB
1112 if (debugger_on_panic) {
1113 kdb_why = KDB_WHY_TRAP;
1114 kdb_trap(type, 0, trapframe);
1115 kdb_why = KDB_WHY_UNSET;
1116 }
1117 #endif
1118 panic("trap");
1119 }
1120 td->td_frame->pc = trapframe->pc;
1121 td->td_frame->cause = trapframe->cause;
1122 td->td_frame->badvaddr = trapframe->badvaddr;
1123 ksiginfo_init_trap(&ksi);
1124 ksi.ksi_signo = i;
1125 ksi.ksi_code = ucode;
1126 ksi.ksi_addr = (void *)addr;
1127 ksi.ksi_trapno = type;
1128 trapsignal(td, &ksi);
1129 out:
1130
1131 /*
1132 * Note: we should only get here if returning to user mode.
1133 */
1134 userret(td, trapframe);
1135 return (trapframe->pc);
1136 }
1137
1138 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1139 void
1140 trapDump(char *msg)
1141 {
1142 register_t s;
1143 int i;
1144
1145 s = intr_disable();
1146 printf("trapDump(%s)\n", msg);
1147 for (i = 0; i < TRAPSIZE; i++) {
1148 if (trp == trapdebug) {
1149 trp = &trapdebug[TRAPSIZE - 1];
1150 } else {
1151 trp--;
1152 }
1153
1154 if (trp->cause == 0)
1155 break;
1156
1157 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
1158 trap_type[(trp->cause & MIPS_CR_EXC_CODE) >>
1159 MIPS_CR_EXC_CODE_SHIFT],
1160 (intmax_t)trp->vadr, (intmax_t)trp->pc,
1161 (intmax_t)trp->cause, (intmax_t)trp->status);
1162
1163 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
1164 (intmax_t)trp->sp, (int)trp->code);
1165 }
1166 intr_restore(s);
1167 }
1168 #endif
1169
1170
1171 /*
1172 * Return the resulting PC as if the branch was executed.
1173 */
1174 uintptr_t
1175 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1176 uintptr_t instptr)
1177 {
1178 InstFmt inst;
1179 register_t *regsPtr = (register_t *) framePtr;
1180 uintptr_t retAddr = 0;
1181 int condition;
1182
1183 #define GetBranchDest(InstPtr, inst) \
1184 (InstPtr + 4 + ((short)inst.IType.imm << 2))
1185
1186
1187 if (instptr) {
1188 if (instptr < MIPS_KSEG0_START)
1189 inst.word = fuword32((void *)instptr);
1190 else
1191 inst = *(InstFmt *) instptr;
1192 } else {
1193 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1194 inst.word = fuword32((void *)instPC);
1195 else
1196 inst = *(InstFmt *) instPC;
1197 }
1198
1199 switch ((int)inst.JType.op) {
1200 case OP_SPECIAL:
1201 switch ((int)inst.RType.func) {
1202 case OP_JR:
1203 case OP_JALR:
1204 retAddr = regsPtr[inst.RType.rs];
1205 break;
1206
1207 default:
1208 retAddr = instPC + 4;
1209 break;
1210 }
1211 break;
1212
1213 case OP_BCOND:
1214 switch ((int)inst.IType.rt) {
1215 case OP_BLTZ:
1216 case OP_BLTZL:
1217 case OP_BLTZAL:
1218 case OP_BLTZALL:
1219 if ((int)(regsPtr[inst.RType.rs]) < 0)
1220 retAddr = GetBranchDest(instPC, inst);
1221 else
1222 retAddr = instPC + 8;
1223 break;
1224
1225 case OP_BGEZ:
1226 case OP_BGEZL:
1227 case OP_BGEZAL:
1228 case OP_BGEZALL:
1229 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1230 retAddr = GetBranchDest(instPC, inst);
1231 else
1232 retAddr = instPC + 8;
1233 break;
1234
1235 case OP_TGEI:
1236 case OP_TGEIU:
1237 case OP_TLTI:
1238 case OP_TLTIU:
1239 case OP_TEQI:
1240 case OP_TNEI:
1241 retAddr = instPC + 4; /* Like syscall... */
1242 break;
1243
1244 default:
1245 panic("MipsEmulateBranch: Bad branch cond");
1246 }
1247 break;
1248
1249 case OP_J:
1250 case OP_JAL:
1251 retAddr = (inst.JType.target << 2) |
1252 ((unsigned)(instPC + 4) & 0xF0000000);
1253 break;
1254
1255 case OP_BEQ:
1256 case OP_BEQL:
1257 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1258 retAddr = GetBranchDest(instPC, inst);
1259 else
1260 retAddr = instPC + 8;
1261 break;
1262
1263 case OP_BNE:
1264 case OP_BNEL:
1265 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1266 retAddr = GetBranchDest(instPC, inst);
1267 else
1268 retAddr = instPC + 8;
1269 break;
1270
1271 case OP_BLEZ:
1272 case OP_BLEZL:
1273 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1274 retAddr = GetBranchDest(instPC, inst);
1275 else
1276 retAddr = instPC + 8;
1277 break;
1278
1279 case OP_BGTZ:
1280 case OP_BGTZL:
1281 if ((int)(regsPtr[inst.RType.rs]) > 0)
1282 retAddr = GetBranchDest(instPC, inst);
1283 else
1284 retAddr = instPC + 8;
1285 break;
1286
1287 case OP_COP1:
1288 switch (inst.RType.rs) {
1289 case OP_BCx:
1290 case OP_BCy:
1291 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1292 condition = fpcCSR & MIPS_FPU_COND_BIT;
1293 else
1294 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1295 if (condition)
1296 retAddr = GetBranchDest(instPC, inst);
1297 else
1298 retAddr = instPC + 8;
1299 break;
1300
1301 default:
1302 retAddr = instPC + 4;
1303 }
1304 break;
1305
1306 default:
1307 retAddr = instPC + 4;
1308 }
1309 return (retAddr);
1310 }
1311
1312
1313 #if defined(DDB) || defined(DEBUG)
1314 /*
1315 * Print a stack backtrace.
1316 */
1317 void
1318 stacktrace(struct trapframe *regs)
1319 {
1320 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1321 }
1322 #endif
1323
1324 static void
1325 log_frame_dump(struct trapframe *frame)
1326 {
1327 log(LOG_ERR, "Trapframe Register Dump:\n");
1328 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1329 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1330
1331 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1332 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1333
1334 #if defined(__mips_n32) || defined(__mips_n64)
1335 log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
1336 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1337
1338 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1339 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1340 #else
1341 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1342 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1343
1344 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1345 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1346 #endif
1347 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1348 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1349
1350 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1351 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1352
1353 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1354 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1355
1356 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1357 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1358
1359 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1360 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1361
1362 #ifdef IC_REG
1363 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1364 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1365 #else
1366 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1367 (intmax_t)frame->cause, (intmax_t)frame->pc);
1368 #endif
1369 }
1370
1371 #ifdef TRAP_DEBUG
1372 static void
1373 trap_frame_dump(struct trapframe *frame)
1374 {
1375 printf("Trapframe Register Dump:\n");
1376 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1377 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1378
1379 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1380 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1381 #if defined(__mips_n32) || defined(__mips_n64)
1382 printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
1383 (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1384
1385 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1386 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1387 #else
1388 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1389 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1390
1391 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1392 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1393 #endif
1394 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1395 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1396
1397 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1398 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1399
1400 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1401 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1402
1403 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1404 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1405
1406 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1407 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1408
1409 #ifdef IC_REG
1410 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1411 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1412 #else
1413 printf("\tcause: %#jx\tpc: %#jx\n",
1414 (intmax_t)frame->cause, (intmax_t)frame->pc);
1415 #endif
1416 }
1417
1418 #endif
1419
1420
1421 static void
1422 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1423 {
1424 pt_entry_t *ptep;
1425 pd_entry_t *pdep;
1426 struct proc *p = curproc;
1427
1428 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1429 if (*pdep)
1430 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1431 else
1432 ptep = (pt_entry_t *)0;
1433
1434 *pdepp = pdep;
1435 *ptepp = ptep;
1436 }
1437
1438 static void
1439 log_illegal_instruction(const char *msg, struct trapframe *frame)
1440 {
1441 pt_entry_t *ptep;
1442 pd_entry_t *pdep;
1443 unsigned int *addr;
1444 struct thread *td;
1445 struct proc *p;
1446 register_t pc;
1447
1448 td = curthread;
1449 p = td->td_proc;
1450
1451 #ifdef SMP
1452 printf("cpuid = %d\n", PCPU_GET(cpuid));
1453 #endif
1454 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1455 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
1456 msg, p->p_pid, (long)td->td_tid, p->p_comm,
1457 p->p_ucred ? p->p_ucred->cr_uid : -1,
1458 (intmax_t)pc,
1459 (intmax_t)frame->ra);
1460
1461 /* log registers in trap frame */
1462 log_frame_dump(frame);
1463
1464 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1465
1466 /*
1467 * Dump a few words around faulting instruction, if the addres is
1468 * valid.
1469 */
1470 if (!(pc & 3) &&
1471 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1472 /* dump page table entry for faulting instruction */
1473 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1474 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1475
1476 addr = (unsigned int *)(intptr_t)pc;
1477 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1478 addr);
1479 log(LOG_ERR, "%08x %08x %08x %08x\n",
1480 addr[0], addr[1], addr[2], addr[3]);
1481 } else {
1482 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1483 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1484 }
1485 }
1486
1487 static void
1488 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1489 {
1490 pt_entry_t *ptep;
1491 pd_entry_t *pdep;
1492 unsigned int *addr;
1493 struct thread *td;
1494 struct proc *p;
1495 char *read_or_write;
1496 register_t pc;
1497
1498 trap_type &= ~T_USER;
1499
1500 td = curthread;
1501 p = td->td_proc;
1502
1503 #ifdef SMP
1504 printf("cpuid = %d\n", PCPU_GET(cpuid));
1505 #endif
1506 switch (trap_type) {
1507 case T_TLB_MOD:
1508 case T_TLB_ST_MISS:
1509 case T_ADDR_ERR_ST:
1510 read_or_write = "write";
1511 break;
1512 case T_TLB_LD_MISS:
1513 case T_ADDR_ERR_LD:
1514 case T_BUS_ERR_IFETCH:
1515 read_or_write = "read";
1516 break;
1517 default:
1518 read_or_write = "unknown";
1519 }
1520
1521 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1522 log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
1523 "(type %#x) at %#jx\n",
1524 msg, p->p_pid, (long)td->td_tid, p->p_comm,
1525 p->p_ucred ? p->p_ucred->cr_uid : -1,
1526 (intmax_t)pc,
1527 read_or_write,
1528 trap_type,
1529 (intmax_t)frame->badvaddr);
1530
1531 /* log registers in trap frame */
1532 log_frame_dump(frame);
1533
1534 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1535
1536 /*
1537 * Dump a few words around faulting instruction, if the addres is
1538 * valid.
1539 */
1540 if (!(pc & 3) && (pc != frame->badvaddr) &&
1541 (trap_type != T_BUS_ERR_IFETCH) &&
1542 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1543 /* dump page table entry for faulting instruction */
1544 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1545 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1546
1547 addr = (unsigned int *)(intptr_t)pc;
1548 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1549 addr);
1550 log(LOG_ERR, "%08x %08x %08x %08x\n",
1551 addr[0], addr[1], addr[2], addr[3]);
1552 } else {
1553 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1554 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1555 }
1556
1557 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1558 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1559 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1560 }
1561
1562
1563 /*
1564 * Unaligned load/store emulation
1565 */
1566 static int
1567 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1568 {
1569 register_t *reg = (register_t *) frame;
1570 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1571 register_t value_msb, value;
1572 unsigned size;
1573
1574 /*
1575 * ADDR_ERR faults have higher priority than TLB
1576 * Miss faults. Therefore, it is necessary to
1577 * verify that the faulting address is a valid
1578 * virtual address within the process' address space
1579 * before trying to emulate the unaligned access.
1580 */
1581 switch (MIPS_INST_OPCODE(inst)) {
1582 case OP_LHU: case OP_LH:
1583 case OP_SH:
1584 size = 2;
1585 break;
1586 case OP_LWU: case OP_LW:
1587 case OP_SW:
1588 size = 4;
1589 break;
1590 case OP_LD:
1591 case OP_SD:
1592 size = 8;
1593 break;
1594 default:
1595 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1596 return (0);
1597 }
1598
1599 if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1600 return (0);
1601
1602 /*
1603 * XXX
1604 * Handle LL/SC LLD/SCD.
1605 */
1606 switch (MIPS_INST_OPCODE(inst)) {
1607 case OP_LHU:
1608 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1609 lbu_macro(value_msb, addr);
1610 addr += 1;
1611 lbu_macro(value, addr);
1612 value |= value_msb << 8;
1613 reg[MIPS_INST_RT(inst)] = value;
1614 return (MIPS_LHU_ACCESS);
1615
1616 case OP_LH:
1617 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1618 lb_macro(value_msb, addr);
1619 addr += 1;
1620 lbu_macro(value, addr);
1621 value |= value_msb << 8;
1622 reg[MIPS_INST_RT(inst)] = value;
1623 return (MIPS_LH_ACCESS);
1624
1625 case OP_LWU:
1626 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1627 lwl_macro(value, addr);
1628 addr += 3;
1629 lwr_macro(value, addr);
1630 value &= 0xffffffff;
1631 reg[MIPS_INST_RT(inst)] = value;
1632 return (MIPS_LWU_ACCESS);
1633
1634 case OP_LW:
1635 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1636 lwl_macro(value, addr);
1637 addr += 3;
1638 lwr_macro(value, addr);
1639 reg[MIPS_INST_RT(inst)] = value;
1640 return (MIPS_LW_ACCESS);
1641
1642 #if defined(__mips_n32) || defined(__mips_n64)
1643 case OP_LD:
1644 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1645 ldl_macro(value, addr);
1646 addr += 7;
1647 ldr_macro(value, addr);
1648 reg[MIPS_INST_RT(inst)] = value;
1649 return (MIPS_LD_ACCESS);
1650 #endif
1651
1652 case OP_SH:
1653 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1654 value = reg[MIPS_INST_RT(inst)];
1655 value_msb = value >> 8;
1656 sb_macro(value_msb, addr);
1657 addr += 1;
1658 sb_macro(value, addr);
1659 return (MIPS_SH_ACCESS);
1660
1661 case OP_SW:
1662 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1663 value = reg[MIPS_INST_RT(inst)];
1664 swl_macro(value, addr);
1665 addr += 3;
1666 swr_macro(value, addr);
1667 return (MIPS_SW_ACCESS);
1668
1669 #if defined(__mips_n32) || defined(__mips_n64)
1670 case OP_SD:
1671 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1672 value = reg[MIPS_INST_RT(inst)];
1673 sdl_macro(value, addr);
1674 addr += 7;
1675 sdr_macro(value, addr);
1676 return (MIPS_SD_ACCESS);
1677 #endif
1678 }
1679 panic("%s: should not be reached.", __func__);
1680 }
1681
1682
1683 static int
1684 emulate_unaligned_access(struct trapframe *frame, int mode)
1685 {
1686 register_t pc;
1687 int access_type = 0;
1688
1689 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1690
1691 /*
1692 * Fall through if it's instruction fetch exception
1693 */
1694 if (!((pc & 3) || (pc == frame->badvaddr))) {
1695
1696 /*
1697 * Handle unaligned load and store
1698 */
1699
1700 /*
1701 * Return access type if the instruction was emulated.
1702 * Otherwise restore pc and fall through.
1703 */
1704 access_type = mips_unaligned_load_store(frame,
1705 mode, frame->badvaddr, pc);
1706
1707 if (access_type) {
1708 if (DELAYBRANCH(frame->cause))
1709 frame->pc = MipsEmulateBranch(frame, frame->pc,
1710 0, 0);
1711 else
1712 frame->pc += 4;
1713
1714 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1715 access_name[access_type - 1], (intmax_t)pc,
1716 (intmax_t)frame->badvaddr);
1717 }
1718 }
1719 return access_type;
1720 }
Cache object: 56c9a0433cac7dcf28202f8d2ee023ac
|