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