FreeBSD/Linux Kernel Cross Reference
sys/mips/mips/trap.c
1 /* $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $ */
2 /* tracked to 1.23 */
3 /*-
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department and Ralph Campbell.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah Hdr: trap.c 1.32 91/04/06
37 *
38 * from: @(#)trap.c 8.5 (Berkeley) 1/11/94
39 * JNPR: trap.c,v 1.13.2.2 2007/08/29 10:03:49 girish
40 */
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD: releng/9.0/sys/mips/mips/trap.c 223562 2011-06-26 10:07:48Z kevlo $");
43
44 #include "opt_ddb.h"
45 #include "opt_global.h"
46 #include "opt_ktrace.h"
47
48 #define NO_REG_DEFS 1 /* Prevent asm.h from including regdef.h */
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/pte.h>
80 #include <machine/pmap.h>
81 #include <machine/md_var.h>
82 #include <machine/mips_opcode.h>
83 #include <machine/frame.h>
84 #include <machine/regnum.h>
85 #include <machine/asm.h>
86
87 #ifdef DDB
88 #include <machine/db_machdep.h>
89 #include <ddb/db_sym.h>
90 #include <ddb/ddb.h>
91 #include <sys/kdb.h>
92 #endif
93
94 #ifdef TRAP_DEBUG
95 int trap_debug = 0;
96 SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW,
97 &trap_debug, 0, "Debug information on all traps");
98 #endif
99
100 static void log_illegal_instruction(const char *, struct trapframe *);
101 static void log_bad_page_fault(char *, struct trapframe *, int);
102 static void log_frame_dump(struct trapframe *frame);
103 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
104
105 #ifdef TRAP_DEBUG
106 static void trap_frame_dump(struct trapframe *frame);
107 #endif
108
109 void (*machExceptionTable[]) (void)= {
110 /*
111 * The kernel exception handlers.
112 */
113 MipsKernIntr, /* external interrupt */
114 MipsKernGenException, /* TLB modification */
115 MipsTLBInvalidException,/* TLB miss (load or instr. fetch) */
116 MipsTLBInvalidException,/* TLB miss (store) */
117 MipsKernGenException, /* address error (load or I-fetch) */
118 MipsKernGenException, /* address error (store) */
119 MipsKernGenException, /* bus error (I-fetch) */
120 MipsKernGenException, /* bus error (load or store) */
121 MipsKernGenException, /* system call */
122 MipsKernGenException, /* breakpoint */
123 MipsKernGenException, /* reserved instruction */
124 MipsKernGenException, /* coprocessor unusable */
125 MipsKernGenException, /* arithmetic overflow */
126 MipsKernGenException, /* trap exception */
127 MipsKernGenException, /* virtual coherence exception inst */
128 MipsKernGenException, /* floating point exception */
129 MipsKernGenException, /* reserved */
130 MipsKernGenException, /* reserved */
131 MipsKernGenException, /* reserved */
132 MipsKernGenException, /* reserved */
133 MipsKernGenException, /* reserved */
134 MipsKernGenException, /* reserved */
135 MipsKernGenException, /* reserved */
136 MipsKernGenException, /* watch exception */
137 MipsKernGenException, /* reserved */
138 MipsKernGenException, /* reserved */
139 MipsKernGenException, /* reserved */
140 MipsKernGenException, /* reserved */
141 MipsKernGenException, /* reserved */
142 MipsKernGenException, /* reserved */
143 MipsKernGenException, /* reserved */
144 MipsKernGenException, /* virtual coherence exception data */
145 /*
146 * The user exception handlers.
147 */
148 MipsUserIntr, /* 0 */
149 MipsUserGenException, /* 1 */
150 MipsTLBInvalidException,/* 2 */
151 MipsTLBInvalidException,/* 3 */
152 MipsUserGenException, /* 4 */
153 MipsUserGenException, /* 5 */
154 MipsUserGenException, /* 6 */
155 MipsUserGenException, /* 7 */
156 MipsUserGenException, /* 8 */
157 MipsUserGenException, /* 9 */
158 MipsUserGenException, /* 10 */
159 MipsUserGenException, /* 11 */
160 MipsUserGenException, /* 12 */
161 MipsUserGenException, /* 13 */
162 MipsUserGenException, /* 14 */
163 MipsUserGenException, /* 15 */
164 MipsUserGenException, /* 16 */
165 MipsUserGenException, /* 17 */
166 MipsUserGenException, /* 18 */
167 MipsUserGenException, /* 19 */
168 MipsUserGenException, /* 20 */
169 MipsUserGenException, /* 21 */
170 MipsUserGenException, /* 22 */
171 MipsUserGenException, /* 23 */
172 MipsUserGenException, /* 24 */
173 MipsUserGenException, /* 25 */
174 MipsUserGenException, /* 26 */
175 MipsUserGenException, /* 27 */
176 MipsUserGenException, /* 28 */
177 MipsUserGenException, /* 29 */
178 MipsUserGenException, /* 20 */
179 MipsUserGenException, /* 31 */
180 };
181
182 char *trap_type[] = {
183 "external interrupt",
184 "TLB modification",
185 "TLB miss (load or instr. fetch)",
186 "TLB miss (store)",
187 "address error (load or I-fetch)",
188 "address error (store)",
189 "bus error (I-fetch)",
190 "bus error (load or store)",
191 "system call",
192 "breakpoint",
193 "reserved instruction",
194 "coprocessor unusable",
195 "arithmetic overflow",
196 "trap",
197 "virtual coherency instruction",
198 "floating point",
199 "reserved 16",
200 "reserved 17",
201 "reserved 18",
202 "reserved 19",
203 "reserved 20",
204 "reserved 21",
205 "reserved 22",
206 "watch",
207 "reserved 24",
208 "reserved 25",
209 "reserved 26",
210 "reserved 27",
211 "reserved 28",
212 "reserved 29",
213 "reserved 30",
214 "virtual coherency data",
215 };
216
217 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
218 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
219 #endif
220
221 #if defined(DDB) || defined(DEBUG)
222 void stacktrace(struct trapframe *);
223 void logstacktrace(struct trapframe *);
224 #endif
225
226 #define KERNLAND(x) ((vm_offset_t)(x) >= VM_MIN_KERNEL_ADDRESS && (vm_offset_t)(x) < VM_MAX_KERNEL_ADDRESS)
227 #define DELAYBRANCH(x) ((int)(x) < 0)
228
229 /*
230 * MIPS load/store access type
231 */
232 enum {
233 MIPS_LHU_ACCESS = 1,
234 MIPS_LH_ACCESS,
235 MIPS_LWU_ACCESS,
236 MIPS_LW_ACCESS,
237 MIPS_LD_ACCESS,
238 MIPS_SH_ACCESS,
239 MIPS_SW_ACCESS,
240 MIPS_SD_ACCESS
241 };
242
243 char *access_name[] = {
244 "Load Halfword Unsigned",
245 "Load Halfword",
246 "Load Word Unsigned",
247 "Load Word",
248 "Load Doubleword",
249 "Store Halfword",
250 "Store Word",
251 "Store Doubleword"
252 };
253
254
255 static int allow_unaligned_acc = 1;
256
257 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
258 &allow_unaligned_acc, 0, "Allow unaligned accesses");
259
260 static int emulate_unaligned_access(struct trapframe *frame, int mode);
261
262 extern void fswintrberr(void); /* XXX */
263
264 /*
265 * Handle an exception.
266 * Called from MipsKernGenException() or MipsUserGenException()
267 * when a processor trap occurs.
268 * In the case of a kernel trap, we return the pc where to resume if
269 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
270 */
271 register_t
272 trap(struct trapframe *trapframe)
273 {
274 int type, usermode;
275 int i = 0;
276 unsigned ucode = 0;
277 struct thread *td = curthread;
278 struct proc *p = curproc;
279 vm_prot_t ftype;
280 pmap_t pmap;
281 int access_type;
282 ksiginfo_t ksi;
283 char *msg = NULL;
284 intptr_t addr = 0;
285 register_t pc;
286
287 trapdebug_enter(trapframe, 0);
288
289 type = (trapframe->cause & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
290 if (TRAPF_USERMODE(trapframe)) {
291 type |= T_USER;
292 usermode = 1;
293 } else {
294 usermode = 0;
295 }
296
297 /*
298 * Enable hardware interrupts if they were on before the trap. If it
299 * was off disable all so we don't accidently enable it when doing a
300 * return to userland.
301 */
302 if (trapframe->sr & MIPS_SR_INT_IE) {
303 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
304 intr_enable();
305 } else {
306 intr_disable();
307 }
308
309 #ifdef TRAP_DEBUG
310 if (trap_debug) {
311 static vm_offset_t last_badvaddr = 0;
312 static vm_offset_t this_badvaddr = 0;
313 static int count = 0;
314 u_int32_t pid;
315
316 printf("trap type %x (%s - ", type,
317 trap_type[type & (~T_USER)]);
318
319 if (type & T_USER)
320 printf("user mode)\n");
321 else
322 printf("kernel mode)\n");
323
324 #ifdef SMP
325 printf("cpuid = %d\n", PCPU_GET(cpuid));
326 #endif
327 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
328 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
329 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
330 (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
331 (curproc ? curproc->p_pid : -1), pid);
332
333 switch (type & ~T_USER) {
334 case T_TLB_MOD:
335 case T_TLB_LD_MISS:
336 case T_TLB_ST_MISS:
337 case T_ADDR_ERR_LD:
338 case T_ADDR_ERR_ST:
339 this_badvaddr = trapframe->badvaddr;
340 break;
341 case T_SYSCALL:
342 this_badvaddr = trapframe->ra;
343 break;
344 default:
345 this_badvaddr = trapframe->pc;
346 break;
347 }
348 if ((last_badvaddr == this_badvaddr) &&
349 ((type & ~T_USER) != T_SYSCALL)) {
350 if (++count == 3) {
351 trap_frame_dump(trapframe);
352 panic("too many faults at %p\n", (void *)last_badvaddr);
353 }
354 } else {
355 last_badvaddr = this_badvaddr;
356 count = 0;
357 }
358 }
359 #endif
360 switch (type) {
361 case T_MCHECK:
362 #ifdef DDB
363 kdb_trap(type, 0, trapframe);
364 #endif
365 panic("MCHECK\n");
366 break;
367 case T_TLB_MOD:
368 /* check for kernel address */
369 if (KERNLAND(trapframe->badvaddr)) {
370 if (pmap_emulate_modified(kernel_pmap,
371 trapframe->badvaddr) != 0) {
372 ftype = VM_PROT_WRITE;
373 goto kernel_fault;
374 }
375 return (trapframe->pc);
376 }
377 /* FALLTHROUGH */
378
379 case T_TLB_MOD + T_USER:
380 pmap = &p->p_vmspace->vm_pmap;
381 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
382 ftype = VM_PROT_WRITE;
383 goto dofault;
384 }
385 if (!usermode)
386 return (trapframe->pc);
387 goto out;
388
389 case T_TLB_LD_MISS:
390 case T_TLB_ST_MISS:
391 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
392 /* check for kernel address */
393 if (KERNLAND(trapframe->badvaddr)) {
394 vm_offset_t va;
395 int rv;
396
397 kernel_fault:
398 va = trunc_page((vm_offset_t)trapframe->badvaddr);
399 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
400 if (rv == KERN_SUCCESS)
401 return (trapframe->pc);
402 if (td->td_pcb->pcb_onfault != NULL) {
403 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
404 td->td_pcb->pcb_onfault = NULL;
405 return (pc);
406 }
407 goto err;
408 }
409
410 /*
411 * It is an error for the kernel to access user space except
412 * through the copyin/copyout routines.
413 */
414 if (td->td_pcb->pcb_onfault == NULL)
415 goto err;
416
417 /* check for fuswintr() or suswintr() getting a page fault */
418 /* XXX There must be a nicer way to do this. */
419 if (td->td_pcb->pcb_onfault == fswintrberr) {
420 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
421 td->td_pcb->pcb_onfault = NULL;
422 return (pc);
423 }
424
425 goto dofault;
426
427 case T_TLB_LD_MISS + T_USER:
428 ftype = VM_PROT_READ;
429 goto dofault;
430
431 case T_TLB_ST_MISS + T_USER:
432 ftype = VM_PROT_WRITE;
433 dofault:
434 {
435 vm_offset_t va;
436 struct vmspace *vm;
437 vm_map_t map;
438 int rv = 0;
439
440 vm = p->p_vmspace;
441 map = &vm->vm_map;
442 va = trunc_page((vm_offset_t)trapframe->badvaddr);
443 if (KERNLAND(trapframe->badvaddr)) {
444 /*
445 * Don't allow user-mode faults in kernel
446 * address space.
447 */
448 goto nogo;
449 }
450
451 /*
452 * Keep swapout from messing with us during this
453 * critical time.
454 */
455 PROC_LOCK(p);
456 ++p->p_lock;
457 PROC_UNLOCK(p);
458
459 rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
460
461 PROC_LOCK(p);
462 --p->p_lock;
463 PROC_UNLOCK(p);
464 #ifdef VMFAULT_TRACE
465 printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
466 map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
467 ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
468 #endif
469
470 if (rv == KERN_SUCCESS) {
471 if (!usermode) {
472 return (trapframe->pc);
473 }
474 goto out;
475 }
476 nogo:
477 if (!usermode) {
478 if (td->td_pcb->pcb_onfault != NULL) {
479 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
480 td->td_pcb->pcb_onfault = NULL;
481 return (pc);
482 }
483 goto err;
484 }
485 ucode = ftype;
486 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
487 addr = trapframe->pc;
488
489 msg = "BAD_PAGE_FAULT";
490 log_bad_page_fault(msg, trapframe, type);
491
492 break;
493 }
494
495 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
496 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
497 if (trapframe->badvaddr < 0 ||
498 trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
499 msg = "ADDRESS_SPACE_ERR";
500 } else if (allow_unaligned_acc) {
501 int mode;
502
503 if (type == (T_ADDR_ERR_LD + T_USER))
504 mode = VM_PROT_READ;
505 else
506 mode = VM_PROT_WRITE;
507
508 access_type = emulate_unaligned_access(trapframe, mode);
509 if (access_type != 0)
510 goto out;
511 msg = "ALIGNMENT_FIX_ERR";
512 } else {
513 msg = "ADDRESS_ERR";
514 }
515
516 /* FALL THROUGH */
517
518 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
519 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
520 ucode = 0; /* XXX should be VM_PROT_something */
521 i = SIGBUS;
522 addr = trapframe->pc;
523 if (!msg)
524 msg = "BUS_ERR";
525 log_bad_page_fault(msg, trapframe, type);
526 break;
527
528 case T_SYSCALL + T_USER:
529 {
530 struct trapframe *locr0 = td->td_frame;
531 struct sysent *callp;
532 unsigned int code;
533 int nargs, nsaved;
534 register_t args[8];
535
536 bzero(args, sizeof args);
537
538 /*
539 * note: PCPU_LAZY_INC() can only be used if we can
540 * afford occassional inaccuracy in the count.
541 */
542 PCPU_LAZY_INC(cnt.v_syscall);
543 if (td->td_ucred != p->p_ucred)
544 cred_update_thread(td);
545 #ifdef KSE
546 if (p->p_flag & P_SA)
547 thread_user_enter(td);
548 #endif
549 /* compute next PC after syscall instruction */
550 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
551 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
552 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
553 0);
554 } else {
555 locr0->pc += sizeof(int);
556 }
557 code = locr0->v0;
558
559 switch (code) {
560 #if defined(__mips_n32) || defined(__mips_n64)
561 case SYS___syscall:
562 /*
563 * Quads fit in a single register in
564 * new ABIs.
565 *
566 * XXX o64?
567 */
568 #endif
569 case SYS_syscall:
570 /*
571 * Code is first argument, followed by
572 * actual args.
573 */
574 code = locr0->a0;
575 args[0] = locr0->a1;
576 args[1] = locr0->a2;
577 args[2] = locr0->a3;
578 nsaved = 3;
579 #if defined(__mips_n32) || defined(__mips_n64)
580 args[3] = locr0->t4;
581 args[4] = locr0->t5;
582 args[5] = locr0->t6;
583 args[6] = locr0->t7;
584 nsaved += 4;
585 #endif
586 break;
587
588 #if defined(__mips_o32)
589 case SYS___syscall:
590 /*
591 * Like syscall, but code is a quad, so as
592 * to maintain quad alignment for the rest
593 * of the arguments.
594 */
595 if (_QUAD_LOWWORD == 0) {
596 code = locr0->a0;
597 } else {
598 code = locr0->a1;
599 }
600 args[0] = locr0->a2;
601 args[1] = locr0->a3;
602 nsaved = 2;
603 break;
604 #endif
605
606 default:
607 args[0] = locr0->a0;
608 args[1] = locr0->a1;
609 args[2] = locr0->a2;
610 args[3] = locr0->a3;
611 nsaved = 4;
612 #if defined (__mips_n32) || defined(__mips_n64)
613 args[4] = locr0->t4;
614 args[5] = locr0->t5;
615 args[6] = locr0->t6;
616 args[7] = locr0->t7;
617 nsaved += 4;
618 #endif
619 }
620 #ifdef TRAP_DEBUG
621 if (trap_debug) {
622 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
623 }
624 #endif
625
626 if (p->p_sysent->sv_mask)
627 code &= p->p_sysent->sv_mask;
628
629 if (code >= p->p_sysent->sv_size)
630 callp = &p->p_sysent->sv_table[0];
631 else
632 callp = &p->p_sysent->sv_table[code];
633
634 nargs = callp->sy_narg;
635
636 if (nargs > nsaved) {
637 #if defined(__mips_n32) || defined(__mips_n64)
638 /*
639 * XXX
640 * Is this right for new ABIs? I think the 4 there
641 * should be 8, size there are 8 registers to skip,
642 * not 4, but I'm not certain.
643 */
644 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid);
645 #endif
646 i = copyin((caddr_t)(intptr_t)(locr0->sp +
647 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
648 (u_int)(nargs - nsaved) * sizeof(register_t));
649 if (i) {
650 locr0->v0 = i;
651 locr0->a3 = 1;
652 #ifdef KTRACE
653 if (KTRPOINT(td, KTR_SYSCALL))
654 ktrsyscall(code, nargs, args);
655 #endif
656 goto done;
657 }
658 }
659 #ifdef TRAP_DEBUG
660 if (trap_debug) {
661 for (i = 0; i < nargs; i++) {
662 printf("args[%d] = %#jx\n", i, (intmax_t)args[i]);
663 }
664 }
665 #endif
666 #ifdef SYSCALL_TRACING
667 printf("%s(", syscallnames[code]);
668 for (i = 0; i < nargs; i++) {
669 printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]);
670 }
671 printf(")\n");
672 #endif
673 #ifdef KTRACE
674 if (KTRPOINT(td, KTR_SYSCALL))
675 ktrsyscall(code, nargs, args);
676 #endif
677 td->td_retval[0] = 0;
678 td->td_retval[1] = locr0->v1;
679
680 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
681 if (trp == trapdebug)
682 trapdebug[TRAPSIZE - 1].code = code;
683 else
684 trp[-1].code = code;
685 #endif
686 STOPEVENT(p, S_SCE, nargs);
687
688 PTRACESTOP_SC(p, td, S_PT_SCE);
689 i = (*callp->sy_call) (td, args);
690 #if 0
691 /*
692 * Reinitialize proc pointer `p' as it may be
693 * different if this is a child returning from fork
694 * syscall.
695 */
696 td = curthread;
697 locr0 = td->td_frame;
698 #endif
699 trapdebug_enter(locr0, -code);
700 cpu_set_syscall_retval(td, i);
701
702 /*
703 * The sync'ing of I & D caches for SYS_ptrace() is
704 * done by procfs_domem() through procfs_rwmem()
705 * instead of being done here under a special check
706 * for SYS_ptrace().
707 */
708 done:
709 /*
710 * Check for misbehavior.
711 */
712 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
713 (code >= 0 && code < SYS_MAXSYSCALL) ?
714 syscallnames[code] : "???");
715 KASSERT(td->td_critnest == 0,
716 ("System call %s returning in a critical section",
717 (code >= 0 && code < SYS_MAXSYSCALL) ?
718 syscallnames[code] : "???"));
719 KASSERT(td->td_locks == 0,
720 ("System call %s returning with %d locks held",
721 (code >= 0 && code < SYS_MAXSYSCALL) ?
722 syscallnames[code] : "???",
723 td->td_locks));
724 userret(td, trapframe);
725 #ifdef KTRACE
726 if (KTRPOINT(td, KTR_SYSRET))
727 ktrsysret(code, i, td->td_retval[0]);
728 #endif
729 /*
730 * This works because errno is findable through the
731 * register set. If we ever support an emulation
732 * where this is not the case, this code will need
733 * to be revisited.
734 */
735 STOPEVENT(p, S_SCX, code);
736
737 PTRACESTOP_SC(p, td, S_PT_SCX);
738
739 mtx_assert(&Giant, MA_NOTOWNED);
740 return (trapframe->pc);
741 }
742
743 #ifdef DDB
744 case T_BREAK:
745 kdb_trap(type, 0, trapframe);
746 return (trapframe->pc);
747 #endif
748
749 case T_BREAK + T_USER:
750 {
751 intptr_t va;
752 uint32_t instr;
753
754 /* compute address of break instruction */
755 va = trapframe->pc;
756 if (DELAYBRANCH(trapframe->cause))
757 va += sizeof(int);
758
759 /* read break instruction */
760 instr = fuword32((caddr_t)va);
761 #if 0
762 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
763 p->p_comm, p->p_pid, instr, trapframe->pc,
764 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
765 #endif
766 if (td->td_md.md_ss_addr != va ||
767 instr != MIPS_BREAK_SSTEP) {
768 i = SIGTRAP;
769 addr = trapframe->pc;
770 break;
771 }
772 /*
773 * The restoration of the original instruction and
774 * the clearing of the berakpoint will be done later
775 * by the call to ptrace_clear_single_step() in
776 * issignal() when SIGTRAP is processed.
777 */
778 addr = trapframe->pc;
779 i = SIGTRAP;
780 break;
781 }
782
783 case T_IWATCH + T_USER:
784 case T_DWATCH + T_USER:
785 {
786 intptr_t va;
787
788 /* compute address of trapped instruction */
789 va = trapframe->pc;
790 if (DELAYBRANCH(trapframe->cause))
791 va += sizeof(int);
792 printf("watch exception @ %p\n", (void *)va);
793 i = SIGTRAP;
794 addr = va;
795 break;
796 }
797
798 case T_TRAP + T_USER:
799 {
800 intptr_t va;
801 uint32_t instr;
802 struct trapframe *locr0 = td->td_frame;
803
804 /* compute address of trap instruction */
805 va = trapframe->pc;
806 if (DELAYBRANCH(trapframe->cause))
807 va += sizeof(int);
808 /* read break instruction */
809 instr = fuword32((caddr_t)va);
810
811 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
812 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
813 0);
814 } else {
815 locr0->pc += sizeof(int);
816 }
817 addr = va;
818 i = SIGEMT; /* Stuff it with something for now */
819 break;
820 }
821
822 case T_RES_INST + T_USER:
823 log_illegal_instruction("RES_INST", trapframe);
824 i = SIGILL;
825 addr = trapframe->pc;
826 break;
827 case T_C2E:
828 case T_C2E + T_USER:
829 goto err;
830 break;
831 case T_COP_UNUSABLE:
832 goto err;
833 break;
834 case T_COP_UNUSABLE + T_USER:
835 #if !defined(CPU_HAVEFPU)
836 /* FP (COP1) instruction */
837 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) {
838 log_illegal_instruction("COP1_UNUSABLE", trapframe);
839 i = SIGILL;
840 break;
841 }
842 #endif
843 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) {
844 log_illegal_instruction("COPn_UNUSABLE", trapframe);
845 i = SIGILL; /* only FPU instructions allowed */
846 break;
847 }
848 addr = trapframe->pc;
849 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
850 PCPU_SET(fpcurthread, td);
851 td->td_frame->sr |= MIPS_SR_COP_1_BIT;
852 td->td_md.md_flags |= MDTD_FPUSED;
853 goto out;
854
855 case T_FPE:
856 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
857 trapDump("fpintr");
858 #else
859 printf("FPU Trap: PC %#jx CR %x SR %x\n",
860 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
861 goto err;
862 #endif
863
864 case T_FPE + T_USER:
865 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
866 goto out;
867
868 case T_OVFLOW + T_USER:
869 i = SIGFPE;
870 addr = trapframe->pc;
871 break;
872
873 case T_ADDR_ERR_LD: /* misaligned access */
874 case T_ADDR_ERR_ST: /* misaligned access */
875 #ifdef TRAP_DEBUG
876 if (trap_debug) {
877 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
878 (intmax_t)trapframe->badvaddr);
879 }
880 #endif
881 /* Only allow emulation on a user address */
882 if (allow_unaligned_acc &&
883 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
884 int mode;
885
886 if (type == T_ADDR_ERR_LD)
887 mode = VM_PROT_READ;
888 else
889 mode = VM_PROT_WRITE;
890
891 access_type = emulate_unaligned_access(trapframe, mode);
892 if (access_type != 0)
893 return (trapframe->pc);
894 }
895 /* FALLTHROUGH */
896
897 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
898 if (td->td_pcb->pcb_onfault != NULL) {
899 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
900 td->td_pcb->pcb_onfault = NULL;
901 return (pc);
902 }
903
904 /* FALLTHROUGH */
905
906 default:
907 err:
908
909 #if !defined(SMP) && defined(DEBUG)
910 stacktrace(!usermode ? trapframe : td->td_frame);
911 trapDump("trap");
912 #endif
913 #ifdef SMP
914 printf("cpu:%d-", PCPU_GET(cpuid));
915 #endif
916 printf("Trap cause = %d (%s - ", type,
917 trap_type[type & (~T_USER)]);
918
919 if (type & T_USER)
920 printf("user mode)\n");
921 else
922 printf("kernel mode)\n");
923
924 #ifdef TRAP_DEBUG
925 if (trap_debug)
926 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
927 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
928 (intmax_t)trapframe->sr);
929 #endif
930
931 #ifdef KDB
932 if (debugger_on_panic || kdb_active) {
933 kdb_trap(type, 0, trapframe);
934 }
935 #endif
936 panic("trap");
937 }
938 td->td_frame->pc = trapframe->pc;
939 td->td_frame->cause = trapframe->cause;
940 td->td_frame->badvaddr = trapframe->badvaddr;
941 ksiginfo_init_trap(&ksi);
942 ksi.ksi_signo = i;
943 ksi.ksi_code = ucode;
944 ksi.ksi_addr = (void *)addr;
945 ksi.ksi_trapno = type;
946 trapsignal(td, &ksi);
947 out:
948
949 /*
950 * Note: we should only get here if returning to user mode.
951 */
952 userret(td, trapframe);
953 mtx_assert(&Giant, MA_NOTOWNED);
954 return (trapframe->pc);
955 }
956
957 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
958 void
959 trapDump(char *msg)
960 {
961 register_t s;
962 int i;
963
964 s = intr_disable();
965 printf("trapDump(%s)\n", msg);
966 for (i = 0; i < TRAPSIZE; i++) {
967 if (trp == trapdebug) {
968 trp = &trapdebug[TRAPSIZE - 1];
969 } else {
970 trp--;
971 }
972
973 if (trp->cause == 0)
974 break;
975
976 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
977 trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >>
978 MIPS_CR_EXC_CODE_SHIFT],
979 (intmax_t)trp->vadr, (intmax_t)trp->pc,
980 (intmax_t)trp->cause, (intmax_t)trp->status);
981
982 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
983 (intmax_t)trp->sp, (int)trp->code);
984 }
985 intr_restore(s);
986 }
987 #endif
988
989
990 /*
991 * Return the resulting PC as if the branch was executed.
992 */
993 uintptr_t
994 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
995 uintptr_t instptr)
996 {
997 InstFmt inst;
998 register_t *regsPtr = (register_t *) framePtr;
999 uintptr_t retAddr = 0;
1000 int condition;
1001
1002 #define GetBranchDest(InstPtr, inst) \
1003 (InstPtr + 4 + ((short)inst.IType.imm << 2))
1004
1005
1006 if (instptr) {
1007 if (instptr < MIPS_KSEG0_START)
1008 inst.word = fuword32((void *)instptr);
1009 else
1010 inst = *(InstFmt *) instptr;
1011 } else {
1012 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1013 inst.word = fuword32((void *)instPC);
1014 else
1015 inst = *(InstFmt *) instPC;
1016 }
1017
1018 switch ((int)inst.JType.op) {
1019 case OP_SPECIAL:
1020 switch ((int)inst.RType.func) {
1021 case OP_JR:
1022 case OP_JALR:
1023 retAddr = regsPtr[inst.RType.rs];
1024 break;
1025
1026 default:
1027 retAddr = instPC + 4;
1028 break;
1029 }
1030 break;
1031
1032 case OP_BCOND:
1033 switch ((int)inst.IType.rt) {
1034 case OP_BLTZ:
1035 case OP_BLTZL:
1036 case OP_BLTZAL:
1037 case OP_BLTZALL:
1038 if ((int)(regsPtr[inst.RType.rs]) < 0)
1039 retAddr = GetBranchDest(instPC, inst);
1040 else
1041 retAddr = instPC + 8;
1042 break;
1043
1044 case OP_BGEZ:
1045 case OP_BGEZL:
1046 case OP_BGEZAL:
1047 case OP_BGEZALL:
1048 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1049 retAddr = GetBranchDest(instPC, inst);
1050 else
1051 retAddr = instPC + 8;
1052 break;
1053
1054 case OP_TGEI:
1055 case OP_TGEIU:
1056 case OP_TLTI:
1057 case OP_TLTIU:
1058 case OP_TEQI:
1059 case OP_TNEI:
1060 retAddr = instPC + 4; /* Like syscall... */
1061 break;
1062
1063 default:
1064 panic("MipsEmulateBranch: Bad branch cond");
1065 }
1066 break;
1067
1068 case OP_J:
1069 case OP_JAL:
1070 retAddr = (inst.JType.target << 2) |
1071 ((unsigned)(instPC + 4) & 0xF0000000);
1072 break;
1073
1074 case OP_BEQ:
1075 case OP_BEQL:
1076 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1077 retAddr = GetBranchDest(instPC, inst);
1078 else
1079 retAddr = instPC + 8;
1080 break;
1081
1082 case OP_BNE:
1083 case OP_BNEL:
1084 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1085 retAddr = GetBranchDest(instPC, inst);
1086 else
1087 retAddr = instPC + 8;
1088 break;
1089
1090 case OP_BLEZ:
1091 case OP_BLEZL:
1092 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1093 retAddr = GetBranchDest(instPC, inst);
1094 else
1095 retAddr = instPC + 8;
1096 break;
1097
1098 case OP_BGTZ:
1099 case OP_BGTZL:
1100 if ((int)(regsPtr[inst.RType.rs]) > 0)
1101 retAddr = GetBranchDest(instPC, inst);
1102 else
1103 retAddr = instPC + 8;
1104 break;
1105
1106 case OP_COP1:
1107 switch (inst.RType.rs) {
1108 case OP_BCx:
1109 case OP_BCy:
1110 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1111 condition = fpcCSR & MIPS_FPU_COND_BIT;
1112 else
1113 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1114 if (condition)
1115 retAddr = GetBranchDest(instPC, inst);
1116 else
1117 retAddr = instPC + 8;
1118 break;
1119
1120 default:
1121 retAddr = instPC + 4;
1122 }
1123 break;
1124
1125 default:
1126 retAddr = instPC + 4;
1127 }
1128 return (retAddr);
1129 }
1130
1131
1132 #if defined(DDB) || defined(DEBUG)
1133 /*
1134 * Print a stack backtrace.
1135 */
1136 void
1137 stacktrace(struct trapframe *regs)
1138 {
1139 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf);
1140 }
1141 #endif
1142
1143 static void
1144 log_frame_dump(struct trapframe *frame)
1145 {
1146 log(LOG_ERR, "Trapframe Register Dump:\n");
1147 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1148 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1149
1150 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1151 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1152
1153 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1154 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1155
1156 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1157 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1158
1159 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1160 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1161
1162 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1163 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1164
1165 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1166 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1167
1168 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1169 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1170
1171 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1172 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1173
1174 #ifdef IC_REG
1175 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1176 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1177 #else
1178 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1179 (intmax_t)frame->cause, (intmax_t)frame->pc);
1180 #endif
1181 }
1182
1183 #ifdef TRAP_DEBUG
1184 static void
1185 trap_frame_dump(struct trapframe *frame)
1186 {
1187 printf("Trapframe Register Dump:\n");
1188 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1189 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1190
1191 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1192 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1193
1194 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1195 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1196
1197 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1198 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1199
1200 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1201 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1202
1203 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1204 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1205
1206 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1207 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1208
1209 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1210 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1211
1212 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1213 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1214
1215 #ifdef IC_REG
1216 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n",
1217 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic);
1218 #else
1219 printf("\tcause: %#jx\tpc: %#jx\n",
1220 (intmax_t)frame->cause, (intmax_t)frame->pc);
1221 #endif
1222 }
1223
1224 #endif
1225
1226
1227 static void
1228 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1229 {
1230 pt_entry_t *ptep;
1231 pd_entry_t *pdep;
1232 struct proc *p = curproc;
1233
1234 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1235 if (*pdep)
1236 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1237 else
1238 ptep = (pt_entry_t *)0;
1239
1240 *pdepp = pdep;
1241 *ptepp = ptep;
1242 }
1243
1244 static void
1245 log_illegal_instruction(const char *msg, struct trapframe *frame)
1246 {
1247 pt_entry_t *ptep;
1248 pd_entry_t *pdep;
1249 unsigned int *addr;
1250 struct proc *p = curproc;
1251 register_t pc;
1252
1253 #ifdef SMP
1254 printf("cpuid = %d\n", PCPU_GET(cpuid));
1255 #endif
1256 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1257 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n",
1258 msg, p->p_pid, p->p_comm,
1259 p->p_ucred ? p->p_ucred->cr_uid : -1,
1260 (intmax_t)pc,
1261 (intmax_t)frame->ra);
1262
1263 /* log registers in trap frame */
1264 log_frame_dump(frame);
1265
1266 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1267
1268 /*
1269 * Dump a few words around faulting instruction, if the addres is
1270 * valid.
1271 */
1272 if (!(pc & 3) &&
1273 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1274 /* dump page table entry for faulting instruction */
1275 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1276 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1277
1278 addr = (unsigned int *)(intptr_t)pc;
1279 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1280 addr);
1281 log(LOG_ERR, "%08x %08x %08x %08x\n",
1282 addr[0], addr[1], addr[2], addr[3]);
1283 } else {
1284 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1285 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1286 }
1287 }
1288
1289 static void
1290 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1291 {
1292 pt_entry_t *ptep;
1293 pd_entry_t *pdep;
1294 unsigned int *addr;
1295 struct proc *p = curproc;
1296 char *read_or_write;
1297 register_t pc;
1298
1299 trap_type &= ~T_USER;
1300
1301 #ifdef SMP
1302 printf("cpuid = %d\n", PCPU_GET(cpuid));
1303 #endif
1304 switch (trap_type) {
1305 case T_TLB_ST_MISS:
1306 case T_ADDR_ERR_ST:
1307 read_or_write = "write";
1308 break;
1309 case T_TLB_LD_MISS:
1310 case T_ADDR_ERR_LD:
1311 case T_BUS_ERR_IFETCH:
1312 read_or_write = "read";
1313 break;
1314 default:
1315 read_or_write = "";
1316 }
1317
1318 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1319 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n",
1320 msg, p->p_pid, p->p_comm,
1321 p->p_ucred ? p->p_ucred->cr_uid : -1,
1322 (intmax_t)pc,
1323 read_or_write,
1324 (intmax_t)frame->badvaddr);
1325
1326 /* log registers in trap frame */
1327 log_frame_dump(frame);
1328
1329 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1330
1331 /*
1332 * Dump a few words around faulting instruction, if the addres is
1333 * valid.
1334 */
1335 if (!(pc & 3) && (pc != frame->badvaddr) &&
1336 (trap_type != T_BUS_ERR_IFETCH) &&
1337 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1338 /* dump page table entry for faulting instruction */
1339 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1340 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1341
1342 addr = (unsigned int *)(intptr_t)pc;
1343 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1344 addr);
1345 log(LOG_ERR, "%08x %08x %08x %08x\n",
1346 addr[0], addr[1], addr[2], addr[3]);
1347 } else {
1348 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1349 (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1350 }
1351
1352 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1353 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1354 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1355 }
1356
1357
1358 /*
1359 * Unaligned load/store emulation
1360 */
1361 static int
1362 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1363 {
1364 register_t *reg = (register_t *) frame;
1365 u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1366 register_t value_msb, value;
1367 unsigned size;
1368
1369 /*
1370 * ADDR_ERR faults have higher priority than TLB
1371 * Miss faults. Therefore, it is necessary to
1372 * verify that the faulting address is a valid
1373 * virtual address within the process' address space
1374 * before trying to emulate the unaligned access.
1375 */
1376 switch (MIPS_INST_OPCODE(inst)) {
1377 case OP_LHU: case OP_LH:
1378 case OP_SH:
1379 size = 2;
1380 break;
1381 case OP_LWU: case OP_LW:
1382 case OP_SW:
1383 size = 4;
1384 break;
1385 case OP_LD:
1386 case OP_SD:
1387 size = 8;
1388 break;
1389 default:
1390 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1391 return (0);
1392 }
1393
1394 if (!useracc((void *)((vm_offset_t)addr & ~(size - 1)), size * 2, mode))
1395 return (0);
1396
1397 /*
1398 * XXX
1399 * Handle LL/SC LLD/SCD.
1400 */
1401 switch (MIPS_INST_OPCODE(inst)) {
1402 case OP_LHU:
1403 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1404 lbu_macro(value_msb, addr);
1405 addr += 1;
1406 lbu_macro(value, addr);
1407 value |= value_msb << 8;
1408 reg[MIPS_INST_RT(inst)] = value;
1409 return (MIPS_LHU_ACCESS);
1410
1411 case OP_LH:
1412 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1413 lb_macro(value_msb, addr);
1414 addr += 1;
1415 lbu_macro(value, addr);
1416 value |= value_msb << 8;
1417 reg[MIPS_INST_RT(inst)] = value;
1418 return (MIPS_LH_ACCESS);
1419
1420 case OP_LWU:
1421 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1422 lwl_macro(value, addr);
1423 addr += 3;
1424 lwr_macro(value, addr);
1425 value &= 0xffffffff;
1426 reg[MIPS_INST_RT(inst)] = value;
1427 return (MIPS_LWU_ACCESS);
1428
1429 case OP_LW:
1430 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1431 lwl_macro(value, addr);
1432 addr += 3;
1433 lwr_macro(value, addr);
1434 reg[MIPS_INST_RT(inst)] = value;
1435 return (MIPS_LW_ACCESS);
1436
1437 #if defined(__mips_n32) || defined(__mips_n64)
1438 case OP_LD:
1439 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1440 ldl_macro(value, addr);
1441 addr += 7;
1442 ldr_macro(value, addr);
1443 reg[MIPS_INST_RT(inst)] = value;
1444 return (MIPS_LD_ACCESS);
1445 #endif
1446
1447 case OP_SH:
1448 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1449 value = reg[MIPS_INST_RT(inst)];
1450 value_msb = value >> 8;
1451 sb_macro(value_msb, addr);
1452 addr += 1;
1453 sb_macro(value, addr);
1454 return (MIPS_SH_ACCESS);
1455
1456 case OP_SW:
1457 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1458 value = reg[MIPS_INST_RT(inst)];
1459 swl_macro(value, addr);
1460 addr += 3;
1461 swr_macro(value, addr);
1462 return (MIPS_SW_ACCESS);
1463
1464 #if defined(__mips_n32) || defined(__mips_n64)
1465 case OP_SD:
1466 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1467 value = reg[MIPS_INST_RT(inst)];
1468 sdl_macro(value, addr);
1469 addr += 7;
1470 sdr_macro(value, addr);
1471 return (MIPS_SD_ACCESS);
1472 #endif
1473 }
1474 panic("%s: should not be reached.", __func__);
1475 }
1476
1477
1478 static int
1479 emulate_unaligned_access(struct trapframe *frame, int mode)
1480 {
1481 register_t pc;
1482 int access_type = 0;
1483
1484 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1485
1486 /*
1487 * Fall through if it's instruction fetch exception
1488 */
1489 if (!((pc & 3) || (pc == frame->badvaddr))) {
1490
1491 /*
1492 * Handle unaligned load and store
1493 */
1494
1495 /*
1496 * Return access type if the instruction was emulated.
1497 * Otherwise restore pc and fall through.
1498 */
1499 access_type = mips_unaligned_load_store(frame,
1500 mode, frame->badvaddr, pc);
1501
1502 if (access_type) {
1503 if (DELAYBRANCH(frame->cause))
1504 frame->pc = MipsEmulateBranch(frame, frame->pc,
1505 0, 0);
1506 else
1507 frame->pc += 4;
1508
1509 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n",
1510 access_name[access_type - 1], (intmax_t)pc,
1511 (intmax_t)frame->badvaddr);
1512 }
1513 }
1514 return access_type;
1515 }
Cache object: 8154afdb0642d28e61541c50e4347250
|