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