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