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/8.1/sys/mips/mips/trap.c 200443 2009-12-12 20:06:25Z kib $");
43
44 #include "opt_ddb.h"
45 #include "opt_global.h"
46
47 #define NO_REG_DEFS 1 /* Prevent asm.h from including regdef.h */
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/sysent.h>
51 #include <sys/proc.h>
52 #include <sys/kernel.h>
53 #include <sys/signalvar.h>
54 #include <sys/syscall.h>
55 #include <sys/lock.h>
56 #include <vm/vm.h>
57 #include <vm/vm_extern.h>
58 #include <vm/vm_kern.h>
59 #include <vm/vm_page.h>
60 #include <vm/vm_map.h>
61 #include <vm/vm_param.h>
62 #include <sys/vmmeter.h>
63 #include <sys/ptrace.h>
64 #include <sys/user.h>
65 #include <sys/buf.h>
66 #include <sys/vnode.h>
67 #include <sys/pioctl.h>
68 #include <sys/sysctl.h>
69 #include <sys/syslog.h>
70 #include <sys/bus.h>
71 #ifdef KTRACE
72 #include <sys/ktrace.h>
73 #endif
74 #include <net/netisr.h>
75
76 #include <machine/trap.h>
77 #include <machine/psl.h>
78 #include <machine/cpu.h>
79 #include <machine/intr.h>
80 #include <machine/pte.h>
81 #include <machine/pmap.h>
82 #include <machine/mips_opcode.h>
83 #include <machine/frame.h>
84 #include <machine/regnum.h>
85 #include <machine/rm7000.h>
86 #include <machine/archtype.h>
87 #include <machine/asm.h>
88
89 #ifdef DDB
90 #include <machine/db_machdep.h>
91 #include <ddb/db_sym.h>
92 #include <ddb/ddb.h>
93 #include <sys/kdb.h>
94 #endif
95
96 #include <sys/cdefs.h>
97 #include <sys/syslog.h>
98
99
100 #ifdef TRAP_DEBUG
101 int trap_debug = 1;
102
103 #endif
104
105 extern unsigned onfault_table[];
106
107 extern void MipsKernGenException(void);
108 extern void MipsUserGenException(void);
109 extern void MipsKernIntr(void);
110 extern void MipsUserIntr(void);
111 extern void MipsTLBInvalidException(void);
112 extern void MipsKernTLBInvalidException(void);
113 extern void MipsUserTLBInvalidException(void);
114 extern void MipsTLBMissException(void);
115 static void log_bad_page_fault(char *, struct trapframe *, int);
116 static void log_frame_dump(struct trapframe *frame);
117 static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **);
118
119 #ifdef TRAP_DEBUG
120 static void trap_frame_dump(struct trapframe *frame);
121
122 #endif
123 extern char edata[];
124
125 void (*machExceptionTable[]) (void)= {
126 /*
127 * The kernel exception handlers.
128 */
129 MipsKernIntr, /* external interrupt */
130 MipsKernGenException, /* TLB modification */
131 MipsKernTLBInvalidException, /* TLB miss (load or instr. fetch) */
132 MipsKernTLBInvalidException, /* TLB miss (store) */
133 MipsKernGenException, /* address error (load or I-fetch) */
134 MipsKernGenException, /* address error (store) */
135 MipsKernGenException, /* bus error (I-fetch) */
136 MipsKernGenException, /* bus error (load or store) */
137 MipsKernGenException, /* system call */
138 MipsKernGenException, /* breakpoint */
139 MipsKernGenException, /* reserved instruction */
140 MipsKernGenException, /* coprocessor unusable */
141 MipsKernGenException, /* arithmetic overflow */
142 MipsKernGenException, /* trap exception */
143 MipsKernGenException, /* virtual coherence exception inst */
144 MipsKernGenException, /* floating point exception */
145 MipsKernGenException, /* reserved */
146 MipsKernGenException, /* reserved */
147 MipsKernGenException, /* reserved */
148 MipsKernGenException, /* reserved */
149 MipsKernGenException, /* reserved */
150 MipsKernGenException, /* reserved */
151 MipsKernGenException, /* reserved */
152 MipsKernGenException, /* watch exception */
153 MipsKernGenException, /* reserved */
154 MipsKernGenException, /* reserved */
155 MipsKernGenException, /* reserved */
156 MipsKernGenException, /* reserved */
157 MipsKernGenException, /* reserved */
158 MipsKernGenException, /* reserved */
159 MipsKernGenException, /* reserved */
160 MipsKernGenException, /* virtual coherence exception data */
161 /*
162 * The user exception handlers.
163 */
164 MipsUserIntr, /* 0 */
165 MipsUserGenException, /* 1 */
166 MipsUserTLBInvalidException, /* 2 */
167 MipsUserTLBInvalidException, /* 3 */
168 MipsUserGenException, /* 4 */
169 MipsUserGenException, /* 5 */
170 MipsUserGenException, /* 6 */
171 MipsUserGenException, /* 7 */
172 MipsUserGenException, /* 8 */
173 MipsUserGenException, /* 9 */
174 MipsUserGenException, /* 10 */
175 MipsUserGenException, /* 11 */
176 MipsUserGenException, /* 12 */
177 MipsUserGenException, /* 13 */
178 MipsUserGenException, /* 14 */
179 MipsUserGenException, /* 15 */
180 MipsUserGenException, /* 16 */
181 MipsUserGenException, /* 17 */
182 MipsUserGenException, /* 18 */
183 MipsUserGenException, /* 19 */
184 MipsUserGenException, /* 20 */
185 MipsUserGenException, /* 21 */
186 MipsUserGenException, /* 22 */
187 MipsUserGenException, /* 23 */
188 MipsUserGenException, /* 24 */
189 MipsUserGenException, /* 25 */
190 MipsUserGenException, /* 26 */
191 MipsUserGenException, /* 27 */
192 MipsUserGenException, /* 28 */
193 MipsUserGenException, /* 29 */
194 MipsUserGenException, /* 20 */
195 MipsUserGenException, /* 31 */
196 };
197
198 char *trap_type[] = {
199 "external interrupt",
200 "TLB modification",
201 "TLB miss (load or instr. fetch)",
202 "TLB miss (store)",
203 "address error (load or I-fetch)",
204 "address error (store)",
205 "bus error (I-fetch)",
206 "bus error (load or store)",
207 "system call",
208 "breakpoint",
209 "reserved instruction",
210 "coprocessor unusable",
211 "arithmetic overflow",
212 "trap",
213 "virtual coherency instruction",
214 "floating point",
215 "reserved 16",
216 "reserved 17",
217 "reserved 18",
218 "reserved 19",
219 "reserved 20",
220 "reserved 21",
221 "reserved 22",
222 "watch",
223 "reserved 24",
224 "reserved 25",
225 "reserved 26",
226 "reserved 27",
227 "reserved 28",
228 "reserved 29",
229 "reserved 30",
230 "virtual coherency data",
231 };
232
233 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
234 struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
235
236 #endif
237
238 #if defined(DDB) || defined(DEBUG)
239 void stacktrace(struct trapframe *);
240 void logstacktrace(struct trapframe *);
241 int kdbpeek(int *);
242
243 /* extern functions printed by name in stack backtraces */
244 extern void MipsTLBMiss(void);
245 extern void MipsUserSyscallException(void);
246 extern char _locore[];
247 extern char _locoreEnd[];
248
249 #endif /* DDB || DEBUG */
250
251 extern void MipsSwitchFPState(struct thread *, struct trapframe *);
252 extern void MipsFPTrap(u_int, u_int, u_int);
253
254 u_int trap(struct trapframe *);
255 u_int MipsEmulateBranch(struct trapframe *, int, int, u_int);
256
257 #define KERNLAND(x) ((int)(x) < 0)
258 #define DELAYBRANCH(x) ((int)(x) < 0)
259
260 /*
261 * kdbpeekD(addr) - skip one word starting at 'addr', then read the second word
262 */
263 #define kdbpeekD(addr) kdbpeek(((int *)(addr)) + 1)
264 int rrs_debug = 0;
265
266 /*
267 * MIPS load/store access type
268 */
269 enum {
270 MIPS_LHU_ACCESS = 1,
271 MIPS_LH_ACCESS,
272 MIPS_LWU_ACCESS,
273 MIPS_LW_ACCESS,
274 MIPS_LD_ACCESS,
275 MIPS_SH_ACCESS,
276 MIPS_SW_ACCESS,
277 MIPS_SD_ACCESS
278 };
279
280 char *access_name[] = {
281 "Load Halfword Unsigned",
282 "Load Halfword",
283 "Load Word Unsigned",
284 "Load Word",
285 "Load Doubleword",
286 "Store Halfword",
287 "Store Word",
288 "Store Doubleword"
289 };
290
291
292 static int allow_unaligned_acc = 1;
293
294 SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW,
295 &allow_unaligned_acc, 0, "Allow unaligned accesses");
296
297 static int emulate_unaligned_access(struct trapframe *frame);
298
299 extern char *syscallnames[];
300
301 /*
302 * Handle an exception.
303 * Called from MipsKernGenException() or MipsUserGenException()
304 * when a processor trap occurs.
305 * In the case of a kernel trap, we return the pc where to resume if
306 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
307 */
308 u_int
309 trap(trapframe)
310 struct trapframe *trapframe;
311 {
312 int type, usermode;
313 int i = 0;
314 unsigned ucode = 0;
315 struct thread *td = curthread;
316 struct proc *p = curproc;
317 vm_prot_t ftype;
318 pt_entry_t *pte;
319 unsigned int entry;
320 pmap_t pmap;
321 int quad_syscall = 0;
322 int access_type;
323 ksiginfo_t ksi;
324 char *msg = NULL;
325 register_t addr = 0;
326
327 trapdebug_enter(trapframe, 0);
328
329 type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
330 if (USERMODE(trapframe->sr)) {
331 type |= T_USER;
332 usermode = 1;
333 } else {
334 usermode = 0;
335 }
336
337 /*
338 * Enable hardware interrupts if they were on before the trap. If it
339 * was off disable all so we don't accidently enable it when doing a
340 * return to userland.
341 */
342 if (trapframe->sr & SR_INT_ENAB) {
343 set_intr_mask(~(trapframe->sr & ALL_INT_MASK));
344 enableintr();
345 } else {
346 disableintr();
347 }
348
349 #ifdef TRAP_DEBUG
350 if (trap_debug) {
351 static vm_offset_t last_badvaddr = 0;
352 static vm_offset_t this_badvaddr = 0;
353 static int count = 0;
354 u_int32_t pid;
355
356 printf("trap type %x (%s - ", type,
357 trap_type[type & (~T_USER)]);
358
359 if (type & T_USER)
360 printf("user mode)\n");
361 else
362 printf("kernel mode)\n");
363
364 #ifdef SMP
365 printf("cpuid = %d\n", PCPU_GET(cpuid));
366 #endif
367 MachTLBGetPID(pid);
368 printf("badaddr = %p, pc = %p, ra = %p, sp = %p, sr = 0x%x, pid = %d, ASID = 0x%x\n",
369 trapframe->badvaddr, trapframe->pc, trapframe->ra,
370 trapframe->sp, trapframe->sr,
371 (curproc ? curproc->p_pid : -1), pid);
372
373 switch (type & ~T_USER) {
374 case T_TLB_MOD:
375 case T_TLB_LD_MISS:
376 case T_TLB_ST_MISS:
377 case T_ADDR_ERR_LD:
378 case T_ADDR_ERR_ST:
379 this_badvaddr = trapframe->badvaddr;
380 break;
381 case T_SYSCALL:
382 this_badvaddr = trapframe->ra;
383 break;
384 default:
385 this_badvaddr = trapframe->pc;
386 break;
387 }
388 if ((last_badvaddr == this_badvaddr) &&
389 ((type & ~T_USER) != T_SYSCALL)) {
390 if (++count == 3) {
391 trap_frame_dump(trapframe);
392 panic("too many faults at %p\n", last_badvaddr);
393 }
394 } else {
395 last_badvaddr = this_badvaddr;
396 count = 0;
397 }
398 }
399 #endif
400 switch (type) {
401 case T_MCHECK:
402 #ifdef DDB
403 kdb_trap(type, 0, trapframe);
404 #endif
405 panic("MCHECK\n");
406 break;
407 case T_TLB_MOD:
408 /* check for kernel address */
409 if (KERNLAND(trapframe->badvaddr)) {
410 vm_offset_t pa;
411
412 PMAP_LOCK(kernel_pmap);
413 if (!(pte = pmap_segmap(kernel_pmap,
414 trapframe->badvaddr)))
415 panic("trap: ktlbmod: invalid segmap");
416 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
417 entry = *pte;
418 #ifdef SMP
419 /* It is possible that some other CPU changed m-bit */
420 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
421 trapframe->badvaddr &= ~PGOFSET;
422 pmap_update_page(kernel_pmap,
423 trapframe->badvaddr, entry);
424 PMAP_UNLOCK(kernel_pmap);
425 return (trapframe->pc);
426 }
427 #else
428 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
429 panic("trap: ktlbmod: invalid pte");
430 #endif
431 if (entry & mips_pg_ro_bit()) {
432 /* write to read only page in the kernel */
433 ftype = VM_PROT_WRITE;
434 PMAP_UNLOCK(kernel_pmap);
435 goto kernel_fault;
436 }
437 entry |= mips_pg_m_bit();
438 *pte = entry;
439 trapframe->badvaddr &= ~PGOFSET;
440 pmap_update_page(kernel_pmap, trapframe->badvaddr, entry);
441 pa = mips_tlbpfn_to_paddr(entry);
442 if (!page_is_managed(pa))
443 panic("trap: ktlbmod: unmanaged page");
444 pmap_set_modified(pa);
445 PMAP_UNLOCK(kernel_pmap);
446 return (trapframe->pc);
447 }
448 /* FALLTHROUGH */
449
450 case T_TLB_MOD + T_USER:
451 {
452 vm_offset_t pa;
453
454 pmap = &p->p_vmspace->vm_pmap;
455
456 PMAP_LOCK(pmap);
457 if (!(pte = pmap_segmap(pmap, trapframe->badvaddr)))
458 panic("trap: utlbmod: invalid segmap");
459 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1);
460 entry = *pte;
461 #ifdef SMP
462 /* It is possible that some other CPU changed m-bit */
463 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
464 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
465 pmap_update_page(pmap, trapframe->badvaddr, entry);
466 PMAP_UNLOCK(pmap);
467 goto out;
468 }
469 #else
470 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
471 panic("trap: utlbmod: invalid pte");
472 }
473 #endif
474
475 if (entry & mips_pg_ro_bit()) {
476 /* write to read only page */
477 ftype = VM_PROT_WRITE;
478 PMAP_UNLOCK(pmap);
479 goto dofault;
480 }
481 entry |= mips_pg_m_bit();
482 *pte = entry;
483 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET);
484 pmap_update_page(pmap, trapframe->badvaddr, entry);
485 trapframe->badvaddr |= (pmap->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT);
486 pa = mips_tlbpfn_to_paddr(entry);
487 if (!page_is_managed(pa))
488 panic("trap: utlbmod: unmanaged page");
489 pmap_set_modified(pa);
490
491 PMAP_UNLOCK(pmap);
492 if (!usermode) {
493 return (trapframe->pc);
494 }
495 goto out;
496 }
497
498 case T_TLB_LD_MISS:
499 case T_TLB_ST_MISS:
500 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
501 /* check for kernel address */
502 if (KERNLAND(trapframe->badvaddr)) {
503 vm_offset_t va;
504 int rv;
505
506 kernel_fault:
507 va = trunc_page((vm_offset_t)trapframe->badvaddr);
508 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
509 if (rv == KERN_SUCCESS)
510 return (trapframe->pc);
511 if ((i = td->td_pcb->pcb_onfault) != 0) {
512 td->td_pcb->pcb_onfault = 0;
513 return (onfault_table[i]);
514 }
515 goto err;
516 }
517 /*
518 * It is an error for the kernel to access user space except
519 * through the copyin/copyout routines.
520 */
521 if ((i = td->td_pcb->pcb_onfault) == 0)
522 goto err;
523 /* check for fuswintr() or suswintr() getting a page fault */
524 if (i == 4) {
525 return (onfault_table[i]);
526 }
527 goto dofault;
528
529 case T_TLB_LD_MISS + T_USER:
530 ftype = VM_PROT_READ;
531 goto dofault;
532
533 case T_TLB_ST_MISS + T_USER:
534 ftype = VM_PROT_WRITE;
535 dofault:
536 {
537 vm_offset_t va;
538 struct vmspace *vm;
539 vm_map_t map;
540 int rv = 0;
541 int flag;
542
543 vm = p->p_vmspace;
544 map = &vm->vm_map;
545 va = trunc_page((vm_offset_t)trapframe->badvaddr);
546 if ((vm_offset_t)trapframe->badvaddr < VM_MIN_KERNEL_ADDRESS) {
547 if (ftype & VM_PROT_WRITE)
548 flag = VM_FAULT_DIRTY;
549 else
550 flag = VM_FAULT_NORMAL;
551 } else {
552 /*
553 * Don't allow user-mode faults in kernel
554 * address space.
555 */
556 goto nogo;
557 }
558
559 /*
560 * Keep swapout from messing with us during this
561 * critical time.
562 */
563 PROC_LOCK(p);
564 ++p->p_lock;
565 PROC_UNLOCK(p);
566
567 rv = vm_fault(map, va, ftype, flag);
568
569 PROC_LOCK(p);
570 --p->p_lock;
571 PROC_UNLOCK(p);
572 #ifdef VMFAULT_TRACE
573 printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
574 map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, flag,
575 rv, trapframe->pc);
576 #endif
577
578 if (rv == KERN_SUCCESS) {
579 if (!usermode) {
580 return (trapframe->pc);
581 }
582 goto out;
583 }
584 nogo:
585 if (!usermode) {
586 if ((i = td->td_pcb->pcb_onfault) != 0) {
587 td->td_pcb->pcb_onfault = 0;
588 return (onfault_table[i]);
589 }
590 goto err;
591 }
592 ucode = ftype;
593 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
594 addr = trapframe->pc;
595
596 msg = "BAD_PAGE_FAULT";
597 log_bad_page_fault(msg, trapframe, type);
598
599 break;
600 }
601
602 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */
603 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */
604 if (allow_unaligned_acc) {
605 int mode;
606
607 if (type == (T_ADDR_ERR_LD + T_USER))
608 mode = VM_PROT_READ;
609 else
610 mode = VM_PROT_WRITE;
611
612 /*
613 * ADDR_ERR faults have higher priority than TLB
614 * Miss faults. Therefore, it is necessary to
615 * verify that the faulting address is a valid
616 * virtual address within the process' address space
617 * before trying to emulate the unaligned access.
618 */
619 if (useracc((caddr_t)
620 (((vm_offset_t)trapframe->badvaddr) &
621 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
622 access_type = emulate_unaligned_access(
623 trapframe);
624 if (access_type != 0)
625 goto out;
626 }
627 }
628 msg = "ADDRESS_ERR";
629
630 /* FALL THROUGH */
631
632 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
633 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */
634 ucode = 0; /* XXX should be VM_PROT_something */
635 i = SIGBUS;
636 addr = trapframe->pc;
637 if (!msg)
638 msg = "BUS_ERR";
639 log_bad_page_fault(msg, trapframe, type);
640 break;
641
642 case T_SYSCALL + T_USER:
643 {
644 struct trapframe *locr0 = td->td_frame;
645 struct sysent *callp;
646 unsigned int code;
647 int nargs, nsaved;
648 register_t args[8];
649
650 /*
651 * note: PCPU_LAZY_INC() can only be used if we can
652 * afford occassional inaccuracy in the count.
653 */
654 PCPU_LAZY_INC(cnt.v_syscall);
655 if (td->td_ucred != p->p_ucred)
656 cred_update_thread(td);
657 #ifdef KSE
658 if (p->p_flag & P_SA)
659 thread_user_enter(td);
660 #endif
661 /* compute next PC after syscall instruction */
662 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */
663 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
664 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
665 0);
666 } else {
667 locr0->pc += sizeof(int);
668 }
669 code = locr0->v0;
670
671 switch (code) {
672 case SYS_syscall:
673 /*
674 * Code is first argument, followed by
675 * actual args.
676 */
677 code = locr0->a0;
678 args[0] = locr0->a1;
679 args[1] = locr0->a2;
680 args[2] = locr0->a3;
681 nsaved = 3;
682 break;
683
684 case SYS___syscall:
685 /*
686 * Like syscall, but code is a quad, so as
687 * to maintain quad alignment for the rest
688 * of the arguments.
689 */
690 if (_QUAD_LOWWORD == 0) {
691 code = locr0->a0;
692 } else {
693 code = locr0->a1;
694 }
695 args[0] = locr0->a2;
696 args[1] = locr0->a3;
697 nsaved = 2;
698 quad_syscall = 1;
699 break;
700
701 default:
702 args[0] = locr0->a0;
703 args[1] = locr0->a1;
704 args[2] = locr0->a2;
705 args[3] = locr0->a3;
706 nsaved = 4;
707 }
708 #ifdef TRAP_DEBUG
709 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
710 #endif
711
712 if (p->p_sysent->sv_mask)
713 code &= p->p_sysent->sv_mask;
714
715 if (code >= p->p_sysent->sv_size)
716 callp = &p->p_sysent->sv_table[0];
717 else
718 callp = &p->p_sysent->sv_table[code];
719
720 nargs = callp->sy_narg;
721
722 if (nargs > nsaved) {
723 i = copyin((caddr_t)(locr0->sp +
724 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
725 (u_int)(nargs - nsaved) * sizeof(register_t));
726 if (i) {
727 locr0->v0 = i;
728 locr0->a3 = 1;
729 #ifdef KTRACE
730 if (KTRPOINT(td, KTR_SYSCALL))
731 ktrsyscall(code, nargs, args);
732 #endif
733 goto done;
734 }
735 }
736 #ifdef KTRACE
737 if (KTRPOINT(td, KTR_SYSCALL))
738 ktrsyscall(code, nargs, args);
739 #endif
740 td->td_retval[0] = 0;
741 td->td_retval[1] = locr0->v1;
742
743 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
744 if (trp == trapdebug)
745 trapdebug[TRAPSIZE - 1].code = code;
746 else
747 trp[-1].code = code;
748 #endif
749 STOPEVENT(p, S_SCE, nargs);
750
751 PTRACESTOP_SC(p, td, S_PT_SCE);
752 i = (*callp->sy_call) (td, args);
753 #if 0
754 /*
755 * Reinitialize proc pointer `p' as it may be
756 * different if this is a child returning from fork
757 * syscall.
758 */
759 td = curthread;
760 locr0 = td->td_frame;
761 #endif
762 trapdebug_enter(locr0, -code);
763 cpu_set_syscall_retval(td, i);
764
765 /*
766 * The sync'ing of I & D caches for SYS_ptrace() is
767 * done by procfs_domem() through procfs_rwmem()
768 * instead of being done here under a special check
769 * for SYS_ptrace().
770 */
771 done:
772 /*
773 * Check for misbehavior.
774 */
775 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
776 (code >= 0 && code < SYS_MAXSYSCALL) ?
777 syscallnames[code] : "???");
778 KASSERT(td->td_critnest == 0,
779 ("System call %s returning in a critical section",
780 (code >= 0 && code < SYS_MAXSYSCALL) ?
781 syscallnames[code] : "???"));
782 KASSERT(td->td_locks == 0,
783 ("System call %s returning with %d locks held",
784 (code >= 0 && code < SYS_MAXSYSCALL) ?
785 syscallnames[code] : "???",
786 td->td_locks));
787 userret(td, trapframe);
788 #ifdef KTRACE
789 if (KTRPOINT(p, KTR_SYSRET))
790 ktrsysret(code, i, td->td_retval[0]);
791 #endif
792 /*
793 * This works because errno is findable through the
794 * register set. If we ever support an emulation
795 * where this is not the case, this code will need
796 * to be revisited.
797 */
798 STOPEVENT(p, S_SCX, code);
799
800 PTRACESTOP_SC(p, td, S_PT_SCX);
801
802 mtx_assert(&Giant, MA_NOTOWNED);
803 return (trapframe->pc);
804 }
805
806 #ifdef DDB
807 case T_BREAK:
808 kdb_trap(type, 0, trapframe);
809 return (trapframe->pc);
810 #endif
811
812 case T_BREAK + T_USER:
813 {
814 unsigned int va, instr;
815
816 /* compute address of break instruction */
817 va = trapframe->pc;
818 if (DELAYBRANCH(trapframe->cause))
819 va += sizeof(int);
820
821 /* read break instruction */
822 instr = fuword((caddr_t)va);
823 #if 0
824 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
825 p->p_comm, p->p_pid, instr, trapframe->pc,
826 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
827 #endif
828 if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
829 i = SIGTRAP;
830 addr = trapframe->pc;
831 break;
832 }
833 /*
834 * The restoration of the original instruction and
835 * the clearing of the berakpoint will be done later
836 * by the call to ptrace_clear_single_step() in
837 * issignal() when SIGTRAP is processed.
838 */
839 addr = trapframe->pc;
840 i = SIGTRAP;
841 break;
842 }
843
844 case T_IWATCH + T_USER:
845 case T_DWATCH + T_USER:
846 {
847 unsigned int va;
848
849 /* compute address of trapped instruction */
850 va = trapframe->pc;
851 if (DELAYBRANCH(trapframe->cause))
852 va += sizeof(int);
853 printf("watch exception @ 0x%x\n", va);
854 i = SIGTRAP;
855 addr = va;
856 break;
857 }
858
859 case T_TRAP + T_USER:
860 {
861 unsigned int va, instr;
862 struct trapframe *locr0 = td->td_frame;
863
864 /* compute address of trap instruction */
865 va = trapframe->pc;
866 if (DELAYBRANCH(trapframe->cause))
867 va += sizeof(int);
868 /* read break instruction */
869 instr = fuword((caddr_t)va);
870
871 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
872 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
873 0);
874 } else {
875 locr0->pc += sizeof(int);
876 }
877 addr = va;
878 i = SIGEMT; /* Stuff it with something for now */
879 break;
880 }
881
882 case T_RES_INST + T_USER:
883 i = SIGILL;
884 addr = trapframe->pc;
885 break;
886 case T_C2E:
887 case T_C2E + T_USER:
888 goto err;
889 break;
890 case T_COP_UNUSABLE:
891 goto err;
892 break;
893 case T_COP_UNUSABLE + T_USER:
894 #if defined(SOFTFLOAT)
895 /* FP (COP1) instruction */
896 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
897 i = SIGILL;
898 break;
899 }
900 #endif
901 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
902 i = SIGILL; /* only FPU instructions allowed */
903 break;
904 }
905 addr = trapframe->pc;
906 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
907 PCPU_SET(fpcurthread, td);
908 td->td_frame->sr |= SR_COP_1_BIT;
909 td->td_md.md_flags |= MDTD_FPUSED;
910 goto out;
911
912 case T_FPE:
913 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
914 trapDump("fpintr");
915 #else
916 printf("FPU Trap: PC %x CR %x SR %x\n",
917 trapframe->pc, trapframe->cause, trapframe->sr);
918 goto err;
919 #endif
920
921 case T_FPE + T_USER:
922 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
923 goto out;
924
925 case T_OVFLOW + T_USER:
926 i = SIGFPE;
927 addr = trapframe->pc;
928 break;
929
930 case T_ADDR_ERR_LD: /* misaligned access */
931 case T_ADDR_ERR_ST: /* misaligned access */
932 #ifdef TRAP_DEBUG
933 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
934 trapframe->badvaddr);
935 #endif
936 /* Only allow emulation on a user address */
937 if (allow_unaligned_acc &&
938 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
939 int mode;
940
941 if (type == T_ADDR_ERR_LD)
942 mode = VM_PROT_READ;
943 else
944 mode = VM_PROT_WRITE;
945
946 /*
947 * ADDR_ERR faults have higher priority than TLB
948 * Miss faults. Therefore, it is necessary to
949 * verify that the faulting address is a valid
950 * virtual address within the process' address space
951 * before trying to emulate the unaligned access.
952 */
953 if (useracc((caddr_t)
954 (((vm_offset_t)trapframe->badvaddr) &
955 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
956 access_type = emulate_unaligned_access(
957 trapframe);
958 if (access_type != 0) {
959 return (trapframe->pc);
960 }
961 }
962 }
963 /* FALLTHROUGH */
964
965 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
966 if ((i = td->td_pcb->pcb_onfault) != 0) {
967 td->td_pcb->pcb_onfault = 0;
968 return (onfault_table[i]);
969 }
970 /* FALLTHROUGH */
971
972 default:
973 err:
974
975 #if !defined(SMP) && defined(DEBUG)
976 stacktrace(!usermode ? trapframe : td->td_frame);
977 trapDump("trap");
978 #endif
979 #ifdef SMP
980 printf("cpu:%d-", PCPU_GET(cpuid));
981 #endif
982 printf("Trap cause = %d (%s - ", type,
983 trap_type[type & (~T_USER)]);
984
985 if (type & T_USER)
986 printf("user mode)\n");
987 else
988 printf("kernel mode)\n");
989
990 #ifdef TRAP_DEBUG
991 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
992 trapframe->badvaddr, trapframe->pc, trapframe->ra,
993 trapframe->sr);
994 #endif
995
996 #ifdef KDB
997 if (debugger_on_panic || kdb_active) {
998 kdb_trap(type, 0, trapframe);
999 }
1000 #endif
1001 panic("trap");
1002 }
1003 td->td_frame->pc = trapframe->pc;
1004 td->td_frame->cause = trapframe->cause;
1005 td->td_frame->badvaddr = trapframe->badvaddr;
1006 ksiginfo_init_trap(&ksi);
1007 ksi.ksi_signo = i;
1008 ksi.ksi_code = ucode;
1009 ksi.ksi_addr = (void *)addr;
1010 ksi.ksi_trapno = type;
1011 trapsignal(td, &ksi);
1012 out:
1013
1014 /*
1015 * Note: we should only get here if returning to user mode.
1016 */
1017 userret(td, trapframe);
1018 mtx_assert(&Giant, MA_NOTOWNED);
1019 return (trapframe->pc);
1020 }
1021
1022 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1023 void
1024 trapDump(char *msg)
1025 {
1026 int i, s;
1027
1028 s = disableintr();
1029 printf("trapDump(%s)\n", msg);
1030 for (i = 0; i < TRAPSIZE; i++) {
1031 if (trp == trapdebug) {
1032 trp = &trapdebug[TRAPSIZE - 1];
1033 } else {
1034 trp--;
1035 }
1036
1037 if (trp->cause == 0)
1038 break;
1039
1040 printf("%s: ADR %x PC %x CR %x SR %x\n",
1041 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
1042 trp->vadr, trp->pc, trp->cause, trp->status);
1043
1044 printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
1045 }
1046 restoreintr(s);
1047 }
1048
1049 #endif
1050
1051
1052 /*
1053 * Return the resulting PC as if the branch was executed.
1054 */
1055 u_int
1056 MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR,
1057 u_int instptr)
1058 {
1059 InstFmt inst;
1060 register_t *regsPtr = (register_t *) framePtr;
1061 unsigned retAddr = 0;
1062 int condition;
1063
1064 #define GetBranchDest(InstPtr, inst) \
1065 ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
1066
1067
1068 if (instptr) {
1069 if (instptr < MIPS_KSEG0_START)
1070 inst.word = fuword((void *)instptr);
1071 else
1072 inst = *(InstFmt *) instptr;
1073 } else {
1074 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1075 inst.word = fuword((void *)instPC);
1076 else
1077 inst = *(InstFmt *) instPC;
1078 }
1079
1080 switch ((int)inst.JType.op) {
1081 case OP_SPECIAL:
1082 switch ((int)inst.RType.func) {
1083 case OP_JR:
1084 case OP_JALR:
1085 retAddr = regsPtr[inst.RType.rs];
1086 break;
1087
1088 default:
1089 retAddr = instPC + 4;
1090 break;
1091 }
1092 break;
1093
1094 case OP_BCOND:
1095 switch ((int)inst.IType.rt) {
1096 case OP_BLTZ:
1097 case OP_BLTZL:
1098 case OP_BLTZAL:
1099 case OP_BLTZALL:
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_BGEZ:
1107 case OP_BGEZL:
1108 case OP_BGEZAL:
1109 case OP_BGEZALL:
1110 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1111 retAddr = GetBranchDest(instPC, inst);
1112 else
1113 retAddr = instPC + 8;
1114 break;
1115
1116 case OP_TGEI:
1117 case OP_TGEIU:
1118 case OP_TLTI:
1119 case OP_TLTIU:
1120 case OP_TEQI:
1121 case OP_TNEI:
1122 retAddr = instPC + 4; /* Like syscall... */
1123 break;
1124
1125 default:
1126 panic("MipsEmulateBranch: Bad branch cond");
1127 }
1128 break;
1129
1130 case OP_J:
1131 case OP_JAL:
1132 retAddr = (inst.JType.target << 2) |
1133 ((unsigned)instPC & 0xF0000000);
1134 break;
1135
1136 case OP_BEQ:
1137 case OP_BEQL:
1138 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1139 retAddr = GetBranchDest(instPC, inst);
1140 else
1141 retAddr = instPC + 8;
1142 break;
1143
1144 case OP_BNE:
1145 case OP_BNEL:
1146 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1147 retAddr = GetBranchDest(instPC, inst);
1148 else
1149 retAddr = instPC + 8;
1150 break;
1151
1152 case OP_BLEZ:
1153 case OP_BLEZL:
1154 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1155 retAddr = GetBranchDest(instPC, inst);
1156 else
1157 retAddr = instPC + 8;
1158 break;
1159
1160 case OP_BGTZ:
1161 case OP_BGTZL:
1162 if ((int)(regsPtr[inst.RType.rs]) > 0)
1163 retAddr = GetBranchDest(instPC, inst);
1164 else
1165 retAddr = instPC + 8;
1166 break;
1167
1168 case OP_COP1:
1169 switch (inst.RType.rs) {
1170 case OP_BCx:
1171 case OP_BCy:
1172 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1173 condition = fpcCSR & FPC_COND_BIT;
1174 else
1175 condition = !(fpcCSR & FPC_COND_BIT);
1176 if (condition)
1177 retAddr = GetBranchDest(instPC, inst);
1178 else
1179 retAddr = instPC + 8;
1180 break;
1181
1182 default:
1183 retAddr = instPC + 4;
1184 }
1185 break;
1186
1187 default:
1188 retAddr = instPC + 4;
1189 }
1190 return (retAddr);
1191 }
1192
1193
1194 #if defined(DDB) || defined(DEBUG)
1195 #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
1196
1197 /* forward */
1198 char *fn_name(unsigned addr);
1199
1200 /*
1201 * Print a stack backtrace.
1202 */
1203 void
1204 stacktrace(struct trapframe *regs)
1205 {
1206 stacktrace_subr(regs, printf);
1207 }
1208
1209 void
1210 stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...))
1211 {
1212 InstFmt i;
1213 unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr;
1214 unsigned instr, mask;
1215 unsigned int frames = 0;
1216 int more, stksize;
1217
1218 /* get initial values from the exception frame */
1219 sp = regs->sp;
1220 pc = regs->pc;
1221 fp = regs->s8;
1222 ra = regs->ra; /* May be a 'leaf' function */
1223 a0 = regs->a0;
1224 a1 = regs->a1;
1225 a2 = regs->a2;
1226 a3 = regs->a3;
1227
1228 /* Jump here when done with a frame, to start a new one */
1229 loop:
1230
1231 /* Jump here after a nonstandard (interrupt handler) frame */
1232 stksize = 0;
1233 subr = 0;
1234 if (frames++ > 100) {
1235 (*printfn) ("\nstackframe count exceeded\n");
1236 /* return breaks stackframe-size heuristics with gcc -O2 */
1237 goto finish; /* XXX */
1238 }
1239 /* check for bad SP: could foul up next frame */
1240 if (sp & 3 || sp < 0x80000000) {
1241 (*printfn) ("SP 0x%x: not in kernel\n", sp);
1242 ra = 0;
1243 subr = 0;
1244 goto done;
1245 }
1246 #define Between(x, y, z) \
1247 ( ((x) <= (y)) && ((y) < (z)) )
1248 #define pcBetween(a,b) \
1249 Between((unsigned)a, pc, (unsigned)b)
1250
1251 /*
1252 * Check for current PC in exception handler code that don't have a
1253 * preceding "j ra" at the tail of the preceding function. Depends
1254 * on relative ordering of functions in exception.S, swtch.S.
1255 */
1256 if (pcBetween(MipsKernGenException, MipsUserGenException))
1257 subr = (unsigned)MipsKernGenException;
1258 else if (pcBetween(MipsUserGenException, MipsKernIntr))
1259 subr = (unsigned)MipsUserGenException;
1260 else if (pcBetween(MipsKernIntr, MipsUserIntr))
1261 subr = (unsigned)MipsKernIntr;
1262 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
1263 subr = (unsigned)MipsUserIntr;
1264 else if (pcBetween(MipsTLBInvalidException,
1265 MipsKernTLBInvalidException))
1266 subr = (unsigned)MipsTLBInvalidException;
1267 else if (pcBetween(MipsKernTLBInvalidException,
1268 MipsUserTLBInvalidException))
1269 subr = (unsigned)MipsKernTLBInvalidException;
1270 else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
1271 subr = (unsigned)MipsUserTLBInvalidException;
1272 else if (pcBetween(cpu_switch, MipsSwitchFPState))
1273 subr = (unsigned)cpu_switch;
1274 else if (pcBetween(_locore, _locoreEnd)) {
1275 subr = (unsigned)_locore;
1276 ra = 0;
1277 goto done;
1278 }
1279 /* check for bad PC */
1280 if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) {
1281 (*printfn) ("PC 0x%x: not in kernel\n", pc);
1282 ra = 0;
1283 goto done;
1284 }
1285 /*
1286 * Find the beginning of the current subroutine by scanning
1287 * backwards from the current PC for the end of the previous
1288 * subroutine.
1289 */
1290 if (!subr) {
1291 va = pc - sizeof(int);
1292 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
1293 va -= sizeof(int);
1294 va += 2 * sizeof(int); /* skip back over branch & delay slot */
1295 /* skip over nulls which might separate .o files */
1296 while ((instr = kdbpeek((int *)va)) == 0)
1297 va += sizeof(int);
1298 subr = va;
1299 }
1300 /* scan forwards to find stack size and any saved registers */
1301 stksize = 0;
1302 more = 3;
1303 mask = 0;
1304 for (va = subr; more; va += sizeof(int),
1305 more = (more == 3) ? 3 : more - 1) {
1306 /* stop if hit our current position */
1307 if (va >= pc)
1308 break;
1309 instr = kdbpeek((int *)va);
1310 i.word = instr;
1311 switch (i.JType.op) {
1312 case OP_SPECIAL:
1313 switch (i.RType.func) {
1314 case OP_JR:
1315 case OP_JALR:
1316 more = 2; /* stop after next instruction */
1317 break;
1318
1319 case OP_SYSCALL:
1320 case OP_BREAK:
1321 more = 1; /* stop now */
1322 };
1323 break;
1324
1325 case OP_BCOND:
1326 case OP_J:
1327 case OP_JAL:
1328 case OP_BEQ:
1329 case OP_BNE:
1330 case OP_BLEZ:
1331 case OP_BGTZ:
1332 more = 2; /* stop after next instruction */
1333 break;
1334
1335 case OP_COP0:
1336 case OP_COP1:
1337 case OP_COP2:
1338 case OP_COP3:
1339 switch (i.RType.rs) {
1340 case OP_BCx:
1341 case OP_BCy:
1342 more = 2; /* stop after next instruction */
1343 };
1344 break;
1345
1346 case OP_SW:
1347 /* look for saved registers on the stack */
1348 if (i.IType.rs != 29)
1349 break;
1350 /* only restore the first one */
1351 if (mask & (1 << i.IType.rt))
1352 break;
1353 mask |= (1 << i.IType.rt);
1354 switch (i.IType.rt) {
1355 case 4:/* a0 */
1356 a0 = kdbpeek((int *)(sp + (short)i.IType.imm));
1357 break;
1358
1359 case 5:/* a1 */
1360 a1 = kdbpeek((int *)(sp + (short)i.IType.imm));
1361 break;
1362
1363 case 6:/* a2 */
1364 a2 = kdbpeek((int *)(sp + (short)i.IType.imm));
1365 break;
1366
1367 case 7:/* a3 */
1368 a3 = kdbpeek((int *)(sp + (short)i.IType.imm));
1369 break;
1370
1371 case 30: /* fp */
1372 fp = kdbpeek((int *)(sp + (short)i.IType.imm));
1373 break;
1374
1375 case 31: /* ra */
1376 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
1377 }
1378 break;
1379
1380 case OP_SD:
1381 /* look for saved registers on the stack */
1382 if (i.IType.rs != 29)
1383 break;
1384 /* only restore the first one */
1385 if (mask & (1 << i.IType.rt))
1386 break;
1387 mask |= (1 << i.IType.rt);
1388 switch (i.IType.rt) {
1389 case 4:/* a0 */
1390 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1391 break;
1392
1393 case 5:/* a1 */
1394 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1395 break;
1396
1397 case 6:/* a2 */
1398 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1399 break;
1400
1401 case 7:/* a3 */
1402 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1403 break;
1404
1405 case 30: /* fp */
1406 fp = kdbpeekD((int *)(sp + (short)i.IType.imm));
1407 break;
1408
1409 case 31: /* ra */
1410 ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
1411 }
1412 break;
1413
1414 case OP_ADDI:
1415 case OP_ADDIU:
1416 /* look for stack pointer adjustment */
1417 if (i.IType.rs != 29 || i.IType.rt != 29)
1418 break;
1419 stksize = -((short)i.IType.imm);
1420 }
1421 }
1422
1423 done:
1424 (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
1425 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1426
1427 if (ra) {
1428 if (pc == ra && stksize == 0)
1429 (*printfn) ("stacktrace: loop!\n");
1430 else {
1431 pc = ra;
1432 sp += stksize;
1433 ra = 0;
1434 goto loop;
1435 }
1436 } else {
1437 finish:
1438 if (curproc)
1439 (*printfn) ("pid %d\n", curproc->p_pid);
1440 else
1441 (*printfn) ("curproc NULL\n");
1442 }
1443 }
1444
1445 /*
1446 * Functions ``special'' enough to print by name
1447 */
1448 #ifdef __STDC__
1449 #define Name(_fn) { (void*)_fn, # _fn }
1450 #else
1451 #define Name(_fn) { _fn, "_fn"}
1452 #endif
1453 static struct {
1454 void *addr;
1455 char *name;
1456 } names[] = {
1457
1458 Name(trap),
1459 Name(MipsKernGenException),
1460 Name(MipsUserGenException),
1461 Name(MipsKernIntr),
1462 Name(MipsUserIntr),
1463 Name(cpu_switch),
1464 {
1465 0, 0
1466 }
1467 };
1468
1469 /*
1470 * Map a function address to a string name, if known; or a hex string.
1471 */
1472 char *
1473 fn_name(unsigned addr)
1474 {
1475 static char buf[17];
1476 int i = 0;
1477
1478 #ifdef DDB
1479 db_expr_t diff;
1480 c_db_sym_t sym;
1481 char *symname;
1482
1483 diff = 0;
1484 symname = NULL;
1485 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
1486 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
1487 if (symname && diff == 0)
1488 return (symname);
1489 #endif
1490
1491 for (i = 0; names[i].name; i++)
1492 if (names[i].addr == (void *)addr)
1493 return (names[i].name);
1494 sprintf(buf, "%x", addr);
1495 return (buf);
1496 }
1497
1498 #endif /* DDB */
1499
1500 static void
1501 log_frame_dump(struct trapframe *frame)
1502 {
1503 log(LOG_ERR, "Trapframe Register Dump:\n");
1504 log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1505 0, frame->ast, frame->v0, frame->v1);
1506
1507 log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1508 frame->a0, frame->a1, frame->a2, frame->a3);
1509
1510 log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1511 frame->t0, frame->t1, frame->t2, frame->t3);
1512
1513 log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1514 frame->t4, frame->t5, frame->t6, frame->t7);
1515
1516 log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1517 frame->t8, frame->t9, frame->s0, frame->s1);
1518
1519 log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1520 frame->s2, frame->s3, frame->s4, frame->s5);
1521
1522 log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1523 frame->s6, frame->s7, frame->k0, frame->k1);
1524
1525 log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1526 frame->gp, frame->sp, frame->s8, frame->ra);
1527
1528 log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1529 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1530
1531 #ifdef IC_REG
1532 log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n",
1533 frame->cause, frame->pc, frame->ic);
1534 #else
1535 log(LOG_ERR, "\tcause: %08x\tpc: %08x\n",
1536 frame->cause, frame->pc);
1537 #endif
1538 }
1539
1540 #ifdef TRAP_DEBUG
1541 static void
1542 trap_frame_dump(struct trapframe *frame)
1543 {
1544 printf("Trapframe Register Dump:\n");
1545 printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1546 0, frame->ast, frame->v0, frame->v1);
1547
1548 printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1549 frame->a0, frame->a1, frame->a2, frame->a3);
1550
1551 printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1552 frame->t0, frame->t1, frame->t2, frame->t3);
1553
1554 printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1555 frame->t4, frame->t5, frame->t6, frame->t7);
1556
1557 printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1558 frame->t8, frame->t9, frame->s0, frame->s1);
1559
1560 printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1561 frame->s2, frame->s3, frame->s4, frame->s5);
1562
1563 printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1564 frame->s6, frame->s7, frame->k0, frame->k1);
1565
1566 printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1567 frame->gp, frame->sp, frame->s8, frame->ra);
1568
1569 printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1570 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1571
1572 #ifdef IC_REG
1573 printf("\tcause: %08x\tpc: %08x\tic: %08x\n",
1574 frame->cause, frame->pc, frame->ic);
1575 #else
1576 printf("\tcause: %08x\tpc: %08x\n",
1577 frame->cause, frame->pc);
1578 #endif
1579 }
1580
1581 #endif
1582
1583
1584 static void
1585 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1586 {
1587 pt_entry_t *ptep;
1588 pd_entry_t *pdep;
1589 struct proc *p = curproc;
1590
1591 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
1592 if (*pdep)
1593 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1594 else
1595 ptep = (pt_entry_t *)0;
1596
1597 *pdepp = pdep;
1598 *ptepp = ptep;
1599 }
1600
1601
1602 static void
1603 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1604 {
1605 pt_entry_t *ptep;
1606 pd_entry_t *pdep;
1607 unsigned int *addr;
1608 struct proc *p = curproc;
1609 char *read_or_write;
1610 register_t pc;
1611
1612 trap_type &= ~T_USER;
1613
1614 #ifdef SMP
1615 printf("cpuid = %d\n", PCPU_GET(cpuid));
1616 #endif
1617 switch (trap_type) {
1618 case T_TLB_ST_MISS:
1619 case T_ADDR_ERR_ST:
1620 read_or_write = "write";
1621 break;
1622 case T_TLB_LD_MISS:
1623 case T_ADDR_ERR_LD:
1624 case T_BUS_ERR_IFETCH:
1625 read_or_write = "read";
1626 break;
1627 default:
1628 read_or_write = "";
1629 }
1630
1631 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1632 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n",
1633 msg, p->p_pid, p->p_comm,
1634 p->p_ucred ? p->p_ucred->cr_uid : -1,
1635 pc,
1636 read_or_write,
1637 frame->badvaddr);
1638
1639 /* log registers in trap frame */
1640 log_frame_dump(frame);
1641
1642 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1643
1644 /*
1645 * Dump a few words around faulting instruction, if the addres is
1646 * valid.
1647 */
1648 if (!(pc & 3) && (pc != frame->badvaddr) &&
1649 (trap_type != T_BUS_ERR_IFETCH) &&
1650 useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1651 /* dump page table entry for faulting instruction */
1652 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n",
1653 pc, *pdep, ptep ? *ptep : 0);
1654
1655 addr = (unsigned int *)pc;
1656 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1657 addr);
1658 log(LOG_ERR, "%08x %08x %08x %08x\n",
1659 addr[0], addr[1], addr[2], addr[3]);
1660 } else {
1661 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n",
1662 pc, *pdep, ptep ? *ptep : 0);
1663 }
1664 /* panic("Bad trap");*/
1665 }
1666
1667
1668 /*
1669 * Unaligned load/store emulation
1670 */
1671 static int
1672 mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
1673 {
1674 register_t *reg = (register_t *) frame;
1675 u_int32_t inst = *((u_int32_t *) pc);
1676 u_int32_t value_msb, value;
1677 int access_type = 0;
1678
1679 switch (MIPS_INST_OPCODE(inst)) {
1680 case OP_LHU:
1681 lbu_macro(value_msb, addr);
1682 addr += 1;
1683 lbu_macro(value, addr);
1684 value |= value_msb << 8;
1685 reg[MIPS_INST_RT(inst)] = value;
1686 access_type = MIPS_LHU_ACCESS;
1687 break;
1688
1689 case OP_LH:
1690 lb_macro(value_msb, addr);
1691 addr += 1;
1692 lbu_macro(value, addr);
1693 value |= value_msb << 8;
1694 reg[MIPS_INST_RT(inst)] = value;
1695 access_type = MIPS_LH_ACCESS;
1696 break;
1697
1698 case OP_LWU:
1699 lwl_macro(value, addr);
1700 addr += 3;
1701 lwr_macro(value, addr);
1702 value &= 0xffffffff;
1703 reg[MIPS_INST_RT(inst)] = value;
1704 access_type = MIPS_LWU_ACCESS;
1705 break;
1706
1707 case OP_LW:
1708 lwl_macro(value, addr);
1709 addr += 3;
1710 lwr_macro(value, addr);
1711 reg[MIPS_INST_RT(inst)] = value;
1712 access_type = MIPS_LW_ACCESS;
1713 break;
1714
1715 case OP_SH:
1716 value = reg[MIPS_INST_RT(inst)];
1717 value_msb = value >> 8;
1718 sb_macro(value_msb, addr);
1719 addr += 1;
1720 sb_macro(value, addr);
1721 access_type = MIPS_SH_ACCESS;
1722 break;
1723
1724 case OP_SW:
1725 value = reg[MIPS_INST_RT(inst)];
1726 swl_macro(value, addr);
1727 addr += 3;
1728 swr_macro(value, addr);
1729 access_type = MIPS_SW_ACCESS;
1730 break;
1731
1732 default:
1733 break;
1734 }
1735
1736 return access_type;
1737 }
1738
1739
1740 static int
1741 emulate_unaligned_access(struct trapframe *frame)
1742 {
1743 register_t pc;
1744 int access_type = 0;
1745
1746 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1747
1748 /*
1749 * Fall through if it's instruction fetch exception
1750 */
1751 if (!((pc & 3) || (pc == frame->badvaddr))) {
1752
1753 /*
1754 * Handle unaligned load and store
1755 */
1756
1757 /*
1758 * Return access type if the instruction was emulated.
1759 * Otherwise restore pc and fall through.
1760 */
1761 access_type = mips_unaligned_load_store(frame,
1762 frame->badvaddr, pc);
1763
1764 if (access_type) {
1765 if (DELAYBRANCH(frame->cause))
1766 frame->pc = MipsEmulateBranch(frame, frame->pc,
1767 0, 0);
1768 else
1769 frame->pc += 4;
1770
1771 log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n",
1772 access_name[access_type - 1], pc, frame->badvaddr);
1773 }
1774 }
1775 return access_type;
1776 }
Cache object: ad1f27cff3a5f502cc0064860b23b7a0
|