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