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.0/sys/mips/mips/trap.c 183428 2008-09-28 03:50:34Z imp $");
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 unsigned int tpc;
648 int nargs, nsaved;
649 register_t args[8];
650
651 /*
652 * note: PCPU_LAZY_INC() can only be used if we can
653 * afford occassional inaccuracy in the count.
654 */
655 PCPU_LAZY_INC(cnt.v_syscall);
656 if (td->td_ucred != p->p_ucred)
657 cred_update_thread(td);
658 #ifdef KSE
659 if (p->p_flag & P_SA)
660 thread_user_enter(td);
661 #endif
662 /* compute next PC after syscall instruction */
663 tpc = trapframe->pc; /* Remember if restart */
664 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
665 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
666 0);
667 } else {
668 locr0->pc += sizeof(int);
669 }
670 code = locr0->v0;
671
672 switch (code) {
673 case SYS_syscall:
674 /*
675 * Code is first argument, followed by
676 * actual args.
677 */
678 code = locr0->a0;
679 args[0] = locr0->a1;
680 args[1] = locr0->a2;
681 args[2] = locr0->a3;
682 nsaved = 3;
683 break;
684
685 case SYS___syscall:
686 /*
687 * Like syscall, but code is a quad, so as
688 * to maintain quad alignment for the rest
689 * of the arguments.
690 */
691 if (_QUAD_LOWWORD == 0) {
692 code = locr0->a0;
693 } else {
694 code = locr0->a1;
695 }
696 args[0] = locr0->a2;
697 args[1] = locr0->a3;
698 nsaved = 2;
699 quad_syscall = 1;
700 break;
701
702 default:
703 args[0] = locr0->a0;
704 args[1] = locr0->a1;
705 args[2] = locr0->a2;
706 args[3] = locr0->a3;
707 nsaved = 4;
708 }
709 #ifdef TRAP_DEBUG
710 printf("SYSCALL #%d pid:%u\n", code, p->p_pid);
711 #endif
712
713 if (p->p_sysent->sv_mask)
714 code &= p->p_sysent->sv_mask;
715
716 if (code >= p->p_sysent->sv_size)
717 callp = &p->p_sysent->sv_table[0];
718 else
719 callp = &p->p_sysent->sv_table[code];
720
721 nargs = callp->sy_narg;
722
723 if (nargs > nsaved) {
724 i = copyin((caddr_t)(locr0->sp +
725 4 * sizeof(register_t)), (caddr_t)&args[nsaved],
726 (u_int)(nargs - nsaved) * sizeof(register_t));
727 if (i) {
728 locr0->v0 = i;
729 locr0->a3 = 1;
730 #ifdef KTRACE
731 if (KTRPOINT(td, KTR_SYSCALL))
732 ktrsyscall(code, nargs, args);
733 #endif
734 goto done;
735 }
736 }
737 #ifdef KTRACE
738 if (KTRPOINT(td, KTR_SYSCALL))
739 ktrsyscall(code, nargs, args);
740 #endif
741 td->td_retval[0] = 0;
742 td->td_retval[1] = locr0->v1;
743
744 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
745 if (trp == trapdebug)
746 trapdebug[TRAPSIZE - 1].code = code;
747 else
748 trp[-1].code = code;
749 #endif
750 STOPEVENT(p, S_SCE, nargs);
751
752 PTRACESTOP_SC(p, td, S_PT_SCE);
753 i = (*callp->sy_call) (td, args);
754 #if 0
755 /*
756 * Reinitialize proc pointer `p' as it may be
757 * different if this is a child returning from fork
758 * syscall.
759 */
760 td = curthread;
761 locr0 = td->td_frame;
762 #endif
763 trapdebug_enter(locr0, -code);
764 switch (i) {
765 case 0:
766 if (quad_syscall && code != SYS_lseek) {
767 /*
768 * System call invoked through the
769 * SYS___syscall interface but the
770 * return value is really just 32
771 * bits.
772 */
773 locr0->v0 = td->td_retval[0];
774 if (_QUAD_LOWWORD)
775 locr0->v1 = td->td_retval[0];
776 locr0->a3 = 0;
777 } else {
778 locr0->v0 = td->td_retval[0];
779 locr0->v1 = td->td_retval[1];
780 locr0->a3 = 0;
781 }
782 break;
783
784 case ERESTART:
785 locr0->pc = tpc;
786 break;
787
788 case EJUSTRETURN:
789 break; /* nothing to do */
790
791 default:
792 if (quad_syscall && code != SYS_lseek) {
793 locr0->v0 = i;
794 if (_QUAD_LOWWORD)
795 locr0->v1 = i;
796 locr0->a3 = 1;
797 } else {
798 locr0->v0 = i;
799 locr0->a3 = 1;
800 }
801 }
802
803 /*
804 * The sync'ing of I & D caches for SYS_ptrace() is
805 * done by procfs_domem() through procfs_rwmem()
806 * instead of being done here under a special check
807 * for SYS_ptrace().
808 */
809 done:
810 /*
811 * Check for misbehavior.
812 */
813 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
814 (code >= 0 && code < SYS_MAXSYSCALL) ?
815 syscallnames[code] : "???");
816 KASSERT(td->td_critnest == 0,
817 ("System call %s returning in a critical section",
818 (code >= 0 && code < SYS_MAXSYSCALL) ?
819 syscallnames[code] : "???"));
820 KASSERT(td->td_locks == 0,
821 ("System call %s returning with %d locks held",
822 (code >= 0 && code < SYS_MAXSYSCALL) ?
823 syscallnames[code] : "???",
824 td->td_locks));
825 userret(td, trapframe);
826 #ifdef KTRACE
827 if (KTRPOINT(p, KTR_SYSRET))
828 ktrsysret(code, i, td->td_retval[0]);
829 #endif
830 /*
831 * This works because errno is findable through the
832 * register set. If we ever support an emulation
833 * where this is not the case, this code will need
834 * to be revisited.
835 */
836 STOPEVENT(p, S_SCX, code);
837
838 PTRACESTOP_SC(p, td, S_PT_SCX);
839
840 mtx_assert(&Giant, MA_NOTOWNED);
841 return (trapframe->pc);
842 }
843
844 #ifdef DDB
845 case T_BREAK:
846 kdb_trap(type, 0, trapframe);
847 return (trapframe->pc);
848 #endif
849
850 case T_BREAK + T_USER:
851 {
852 unsigned int va, instr;
853
854 /* compute address of break instruction */
855 va = trapframe->pc;
856 if (DELAYBRANCH(trapframe->cause))
857 va += sizeof(int);
858
859 /* read break instruction */
860 instr = fuword((caddr_t)va);
861 #if 0
862 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
863 p->p_comm, p->p_pid, instr, trapframe->pc,
864 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
865 #endif
866 if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) {
867 i = SIGTRAP;
868 addr = trapframe->pc;
869 break;
870 }
871 /*
872 * The restoration of the original instruction and
873 * the clearing of the berakpoint will be done later
874 * by the call to ptrace_clear_single_step() in
875 * issignal() when SIGTRAP is processed.
876 */
877 addr = trapframe->pc;
878 i = SIGTRAP;
879 break;
880 }
881
882 case T_IWATCH + T_USER:
883 case T_DWATCH + T_USER:
884 {
885 unsigned int va;
886
887 /* compute address of trapped instruction */
888 va = trapframe->pc;
889 if (DELAYBRANCH(trapframe->cause))
890 va += sizeof(int);
891 printf("watch exception @ 0x%x\n", va);
892 i = SIGTRAP;
893 addr = va;
894 break;
895 }
896
897 case T_TRAP + T_USER:
898 {
899 unsigned int va, instr;
900 struct trapframe *locr0 = td->td_frame;
901
902 /* compute address of trap instruction */
903 va = trapframe->pc;
904 if (DELAYBRANCH(trapframe->cause))
905 va += sizeof(int);
906 /* read break instruction */
907 instr = fuword((caddr_t)va);
908
909 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */
910 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
911 0);
912 } else {
913 locr0->pc += sizeof(int);
914 }
915 addr = va;
916 i = SIGEMT; /* Stuff it with something for now */
917 break;
918 }
919
920 case T_RES_INST + T_USER:
921 i = SIGILL;
922 addr = trapframe->pc;
923 break;
924 case T_C2E:
925 case T_C2E + T_USER:
926 goto err;
927 break;
928 case T_COP_UNUSABLE:
929 goto err;
930 break;
931 case T_COP_UNUSABLE + T_USER:
932 #if defined(SOFTFLOAT)
933 /* FP (COP1) instruction */
934 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) {
935 i = SIGILL;
936 break;
937 }
938 #endif
939 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
940 i = SIGILL; /* only FPU instructions allowed */
941 break;
942 }
943 addr = trapframe->pc;
944 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
945 PCPU_SET(fpcurthread, td);
946 td->td_frame->sr |= SR_COP_1_BIT;
947 td->td_md.md_flags |= MDTD_FPUSED;
948 goto out;
949
950 case T_FPE:
951 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
952 trapDump("fpintr");
953 #else
954 printf("FPU Trap: PC %x CR %x SR %x\n",
955 trapframe->pc, trapframe->cause, trapframe->sr);
956 goto err;
957 #endif
958
959 case T_FPE + T_USER:
960 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
961 goto out;
962
963 case T_OVFLOW + T_USER:
964 i = SIGFPE;
965 addr = trapframe->pc;
966 break;
967
968 case T_ADDR_ERR_LD: /* misaligned access */
969 case T_ADDR_ERR_ST: /* misaligned access */
970 #ifdef TRAP_DEBUG
971 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type,
972 trapframe->badvaddr);
973 #endif
974 /* Only allow emulation on a user address */
975 if (allow_unaligned_acc &&
976 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
977 int mode;
978
979 if (type == T_ADDR_ERR_LD)
980 mode = VM_PROT_READ;
981 else
982 mode = VM_PROT_WRITE;
983
984 /*
985 * ADDR_ERR faults have higher priority than TLB
986 * Miss faults. Therefore, it is necessary to
987 * verify that the faulting address is a valid
988 * virtual address within the process' address space
989 * before trying to emulate the unaligned access.
990 */
991 if (useracc((caddr_t)
992 (((vm_offset_t)trapframe->badvaddr) &
993 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) {
994 access_type = emulate_unaligned_access(
995 trapframe);
996 if (access_type != 0) {
997 return (trapframe->pc);
998 }
999 }
1000 }
1001 /* FALLTHROUGH */
1002
1003 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
1004 if ((i = td->td_pcb->pcb_onfault) != 0) {
1005 td->td_pcb->pcb_onfault = 0;
1006 return (onfault_table[i]);
1007 }
1008 /* FALLTHROUGH */
1009
1010 default:
1011 err:
1012
1013 #if !defined(SMP) && defined(DEBUG)
1014 stacktrace(!usermode ? trapframe : td->td_frame);
1015 trapDump("trap");
1016 #endif
1017 #ifdef SMP
1018 printf("cpu:%d-", PCPU_GET(cpuid));
1019 #endif
1020 printf("Trap cause = %d (%s - ", type,
1021 trap_type[type & (~T_USER)]);
1022
1023 if (type & T_USER)
1024 printf("user mode)\n");
1025 else
1026 printf("kernel mode)\n");
1027
1028 #ifdef TRAP_DEBUG
1029 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n",
1030 trapframe->badvaddr, trapframe->pc, trapframe->ra,
1031 trapframe->sr);
1032 #endif
1033
1034 #ifdef KDB
1035 if (debugger_on_panic || kdb_active) {
1036 kdb_trap(type, 0, trapframe);
1037 }
1038 #endif
1039 panic("trap");
1040 }
1041 td->td_frame->pc = trapframe->pc;
1042 td->td_frame->cause = trapframe->cause;
1043 td->td_frame->badvaddr = trapframe->badvaddr;
1044 ksiginfo_init_trap(&ksi);
1045 ksi.ksi_signo = i;
1046 ksi.ksi_code = ucode;
1047 ksi.ksi_addr = (void *)addr;
1048 ksi.ksi_trapno = type;
1049 trapsignal(td, &ksi);
1050 out:
1051
1052 /*
1053 * Note: we should only get here if returning to user mode.
1054 */
1055 userret(td, trapframe);
1056 mtx_assert(&Giant, MA_NOTOWNED);
1057 return (trapframe->pc);
1058 }
1059
1060 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1061 void
1062 trapDump(char *msg)
1063 {
1064 int i, s;
1065
1066 s = disableintr();
1067 printf("trapDump(%s)\n", msg);
1068 for (i = 0; i < TRAPSIZE; i++) {
1069 if (trp == trapdebug) {
1070 trp = &trapdebug[TRAPSIZE - 1];
1071 } else {
1072 trp--;
1073 }
1074
1075 if (trp->cause == 0)
1076 break;
1077
1078 printf("%s: ADR %x PC %x CR %x SR %x\n",
1079 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
1080 trp->vadr, trp->pc, trp->cause, trp->status);
1081
1082 printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
1083 }
1084 restoreintr(s);
1085 }
1086
1087 #endif
1088
1089
1090 /*
1091 * Return the resulting PC as if the branch was executed.
1092 */
1093 u_int
1094 MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR,
1095 u_int instptr)
1096 {
1097 InstFmt inst;
1098 register_t *regsPtr = (register_t *) framePtr;
1099 unsigned retAddr = 0;
1100 int condition;
1101
1102 #define GetBranchDest(InstPtr, inst) \
1103 ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
1104
1105
1106 if (instptr) {
1107 if (instptr < MIPS_KSEG0_START)
1108 inst.word = fuword((void *)instptr);
1109 else
1110 inst = *(InstFmt *) instptr;
1111 } else {
1112 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1113 inst.word = fuword((void *)instPC);
1114 else
1115 inst = *(InstFmt *) instPC;
1116 }
1117
1118 switch ((int)inst.JType.op) {
1119 case OP_SPECIAL:
1120 switch ((int)inst.RType.func) {
1121 case OP_JR:
1122 case OP_JALR:
1123 retAddr = regsPtr[inst.RType.rs];
1124 break;
1125
1126 default:
1127 retAddr = instPC + 4;
1128 break;
1129 }
1130 break;
1131
1132 case OP_BCOND:
1133 switch ((int)inst.IType.rt) {
1134 case OP_BLTZ:
1135 case OP_BLTZL:
1136 case OP_BLTZAL:
1137 case OP_BLTZALL:
1138 if ((int)(regsPtr[inst.RType.rs]) < 0)
1139 retAddr = GetBranchDest(instPC, inst);
1140 else
1141 retAddr = instPC + 8;
1142 break;
1143
1144 case OP_BGEZ:
1145 case OP_BGEZL:
1146 case OP_BGEZAL:
1147 case OP_BGEZALL:
1148 if ((int)(regsPtr[inst.RType.rs]) >= 0)
1149 retAddr = GetBranchDest(instPC, inst);
1150 else
1151 retAddr = instPC + 8;
1152 break;
1153
1154 case OP_TGEI:
1155 case OP_TGEIU:
1156 case OP_TLTI:
1157 case OP_TLTIU:
1158 case OP_TEQI:
1159 case OP_TNEI:
1160 retAddr = instPC + 4; /* Like syscall... */
1161 break;
1162
1163 default:
1164 panic("MipsEmulateBranch: Bad branch cond");
1165 }
1166 break;
1167
1168 case OP_J:
1169 case OP_JAL:
1170 retAddr = (inst.JType.target << 2) |
1171 ((unsigned)instPC & 0xF0000000);
1172 break;
1173
1174 case OP_BEQ:
1175 case OP_BEQL:
1176 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1177 retAddr = GetBranchDest(instPC, inst);
1178 else
1179 retAddr = instPC + 8;
1180 break;
1181
1182 case OP_BNE:
1183 case OP_BNEL:
1184 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1185 retAddr = GetBranchDest(instPC, inst);
1186 else
1187 retAddr = instPC + 8;
1188 break;
1189
1190 case OP_BLEZ:
1191 case OP_BLEZL:
1192 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1193 retAddr = GetBranchDest(instPC, inst);
1194 else
1195 retAddr = instPC + 8;
1196 break;
1197
1198 case OP_BGTZ:
1199 case OP_BGTZL:
1200 if ((int)(regsPtr[inst.RType.rs]) > 0)
1201 retAddr = GetBranchDest(instPC, inst);
1202 else
1203 retAddr = instPC + 8;
1204 break;
1205
1206 case OP_COP1:
1207 switch (inst.RType.rs) {
1208 case OP_BCx:
1209 case OP_BCy:
1210 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1211 condition = fpcCSR & FPC_COND_BIT;
1212 else
1213 condition = !(fpcCSR & FPC_COND_BIT);
1214 if (condition)
1215 retAddr = GetBranchDest(instPC, inst);
1216 else
1217 retAddr = instPC + 8;
1218 break;
1219
1220 default:
1221 retAddr = instPC + 4;
1222 }
1223 break;
1224
1225 default:
1226 retAddr = instPC + 4;
1227 }
1228 return (retAddr);
1229 }
1230
1231
1232 #if defined(DDB) || defined(DEBUG)
1233 #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
1234
1235 /* forward */
1236 char *fn_name(unsigned addr);
1237
1238 /*
1239 * Print a stack backtrace.
1240 */
1241 void
1242 stacktrace(struct trapframe *regs)
1243 {
1244 stacktrace_subr(regs, printf);
1245 }
1246
1247 void
1248 stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...))
1249 {
1250 InstFmt i;
1251 unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr;
1252 unsigned instr, mask;
1253 unsigned int frames = 0;
1254 int more, stksize;
1255
1256 /* get initial values from the exception frame */
1257 sp = regs->sp;
1258 pc = regs->pc;
1259 fp = regs->s8;
1260 ra = regs->ra; /* May be a 'leaf' function */
1261 a0 = regs->a0;
1262 a1 = regs->a1;
1263 a2 = regs->a2;
1264 a3 = regs->a3;
1265
1266 /* Jump here when done with a frame, to start a new one */
1267 loop:
1268
1269 /* Jump here after a nonstandard (interrupt handler) frame */
1270 stksize = 0;
1271 subr = 0;
1272 if (frames++ > 100) {
1273 (*printfn) ("\nstackframe count exceeded\n");
1274 /* return breaks stackframe-size heuristics with gcc -O2 */
1275 goto finish; /* XXX */
1276 }
1277 /* check for bad SP: could foul up next frame */
1278 if (sp & 3 || sp < 0x80000000) {
1279 (*printfn) ("SP 0x%x: not in kernel\n", sp);
1280 ra = 0;
1281 subr = 0;
1282 goto done;
1283 }
1284 #define Between(x, y, z) \
1285 ( ((x) <= (y)) && ((y) < (z)) )
1286 #define pcBetween(a,b) \
1287 Between((unsigned)a, pc, (unsigned)b)
1288
1289 /*
1290 * Check for current PC in exception handler code that don't have a
1291 * preceding "j ra" at the tail of the preceding function. Depends
1292 * on relative ordering of functions in exception.S, swtch.S.
1293 */
1294 if (pcBetween(MipsKernGenException, MipsUserGenException))
1295 subr = (unsigned)MipsKernGenException;
1296 else if (pcBetween(MipsUserGenException, MipsKernIntr))
1297 subr = (unsigned)MipsUserGenException;
1298 else if (pcBetween(MipsKernIntr, MipsUserIntr))
1299 subr = (unsigned)MipsKernIntr;
1300 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
1301 subr = (unsigned)MipsUserIntr;
1302 else if (pcBetween(MipsTLBInvalidException,
1303 MipsKernTLBInvalidException))
1304 subr = (unsigned)MipsTLBInvalidException;
1305 else if (pcBetween(MipsKernTLBInvalidException,
1306 MipsUserTLBInvalidException))
1307 subr = (unsigned)MipsKernTLBInvalidException;
1308 else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException))
1309 subr = (unsigned)MipsUserTLBInvalidException;
1310 else if (pcBetween(cpu_switch, MipsSwitchFPState))
1311 subr = (unsigned)cpu_switch;
1312 else if (pcBetween(_locore, _locoreEnd)) {
1313 subr = (unsigned)_locore;
1314 ra = 0;
1315 goto done;
1316 }
1317 /* check for bad PC */
1318 if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) {
1319 (*printfn) ("PC 0x%x: not in kernel\n", pc);
1320 ra = 0;
1321 goto done;
1322 }
1323 /*
1324 * Find the beginning of the current subroutine by scanning
1325 * backwards from the current PC for the end of the previous
1326 * subroutine.
1327 */
1328 if (!subr) {
1329 va = pc - sizeof(int);
1330 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA)
1331 va -= sizeof(int);
1332 va += 2 * sizeof(int); /* skip back over branch & delay slot */
1333 /* skip over nulls which might separate .o files */
1334 while ((instr = kdbpeek((int *)va)) == 0)
1335 va += sizeof(int);
1336 subr = va;
1337 }
1338 /* scan forwards to find stack size and any saved registers */
1339 stksize = 0;
1340 more = 3;
1341 mask = 0;
1342 for (va = subr; more; va += sizeof(int),
1343 more = (more == 3) ? 3 : more - 1) {
1344 /* stop if hit our current position */
1345 if (va >= pc)
1346 break;
1347 instr = kdbpeek((int *)va);
1348 i.word = instr;
1349 switch (i.JType.op) {
1350 case OP_SPECIAL:
1351 switch (i.RType.func) {
1352 case OP_JR:
1353 case OP_JALR:
1354 more = 2; /* stop after next instruction */
1355 break;
1356
1357 case OP_SYSCALL:
1358 case OP_BREAK:
1359 more = 1; /* stop now */
1360 };
1361 break;
1362
1363 case OP_BCOND:
1364 case OP_J:
1365 case OP_JAL:
1366 case OP_BEQ:
1367 case OP_BNE:
1368 case OP_BLEZ:
1369 case OP_BGTZ:
1370 more = 2; /* stop after next instruction */
1371 break;
1372
1373 case OP_COP0:
1374 case OP_COP1:
1375 case OP_COP2:
1376 case OP_COP3:
1377 switch (i.RType.rs) {
1378 case OP_BCx:
1379 case OP_BCy:
1380 more = 2; /* stop after next instruction */
1381 };
1382 break;
1383
1384 case OP_SW:
1385 /* look for saved registers on the stack */
1386 if (i.IType.rs != 29)
1387 break;
1388 /* only restore the first one */
1389 if (mask & (1 << i.IType.rt))
1390 break;
1391 mask |= (1 << i.IType.rt);
1392 switch (i.IType.rt) {
1393 case 4:/* a0 */
1394 a0 = kdbpeek((int *)(sp + (short)i.IType.imm));
1395 break;
1396
1397 case 5:/* a1 */
1398 a1 = kdbpeek((int *)(sp + (short)i.IType.imm));
1399 break;
1400
1401 case 6:/* a2 */
1402 a2 = kdbpeek((int *)(sp + (short)i.IType.imm));
1403 break;
1404
1405 case 7:/* a3 */
1406 a3 = kdbpeek((int *)(sp + (short)i.IType.imm));
1407 break;
1408
1409 case 30: /* fp */
1410 fp = kdbpeek((int *)(sp + (short)i.IType.imm));
1411 break;
1412
1413 case 31: /* ra */
1414 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
1415 }
1416 break;
1417
1418 case OP_SD:
1419 /* look for saved registers on the stack */
1420 if (i.IType.rs != 29)
1421 break;
1422 /* only restore the first one */
1423 if (mask & (1 << i.IType.rt))
1424 break;
1425 mask |= (1 << i.IType.rt);
1426 switch (i.IType.rt) {
1427 case 4:/* a0 */
1428 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1429 break;
1430
1431 case 5:/* a1 */
1432 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1433 break;
1434
1435 case 6:/* a2 */
1436 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1437 break;
1438
1439 case 7:/* a3 */
1440 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm));
1441 break;
1442
1443 case 30: /* fp */
1444 fp = kdbpeekD((int *)(sp + (short)i.IType.imm));
1445 break;
1446
1447 case 31: /* ra */
1448 ra = kdbpeekD((int *)(sp + (short)i.IType.imm));
1449 }
1450 break;
1451
1452 case OP_ADDI:
1453 case OP_ADDIU:
1454 /* look for stack pointer adjustment */
1455 if (i.IType.rs != 29 || i.IType.rt != 29)
1456 break;
1457 stksize = -((short)i.IType.imm);
1458 }
1459 }
1460
1461 done:
1462 (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
1463 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1464
1465 if (ra) {
1466 if (pc == ra && stksize == 0)
1467 (*printfn) ("stacktrace: loop!\n");
1468 else {
1469 pc = ra;
1470 sp += stksize;
1471 ra = 0;
1472 goto loop;
1473 }
1474 } else {
1475 finish:
1476 if (curproc)
1477 (*printfn) ("pid %d\n", curproc->p_pid);
1478 else
1479 (*printfn) ("curproc NULL\n");
1480 }
1481 }
1482
1483 /*
1484 * Functions ``special'' enough to print by name
1485 */
1486 #ifdef __STDC__
1487 #define Name(_fn) { (void*)_fn, # _fn }
1488 #else
1489 #define Name(_fn) { _fn, "_fn"}
1490 #endif
1491 static struct {
1492 void *addr;
1493 char *name;
1494 } names[] = {
1495
1496 Name(trap),
1497 Name(MipsKernGenException),
1498 Name(MipsUserGenException),
1499 Name(MipsKernIntr),
1500 Name(MipsUserIntr),
1501 Name(cpu_switch),
1502 {
1503 0, 0
1504 }
1505 };
1506
1507 /*
1508 * Map a function address to a string name, if known; or a hex string.
1509 */
1510 char *
1511 fn_name(unsigned addr)
1512 {
1513 static char buf[17];
1514 int i = 0;
1515
1516 #ifdef DDB
1517 db_expr_t diff;
1518 c_db_sym_t sym;
1519 char *symname;
1520
1521 diff = 0;
1522 symname = NULL;
1523 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
1524 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
1525 if (symname && diff == 0)
1526 return (symname);
1527 #endif
1528
1529 for (i = 0; names[i].name; i++)
1530 if (names[i].addr == (void *)addr)
1531 return (names[i].name);
1532 sprintf(buf, "%x", addr);
1533 return (buf);
1534 }
1535
1536 #endif /* DDB */
1537
1538 static void
1539 log_frame_dump(struct trapframe *frame)
1540 {
1541 log(LOG_ERR, "Trapframe Register Dump:\n");
1542 log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1543 0, frame->ast, frame->v0, frame->v1);
1544
1545 log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1546 frame->a0, frame->a1, frame->a2, frame->a3);
1547
1548 log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1549 frame->t0, frame->t1, frame->t2, frame->t3);
1550
1551 log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1552 frame->t4, frame->t5, frame->t6, frame->t7);
1553
1554 log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1555 frame->t8, frame->t9, frame->s0, frame->s1);
1556
1557 log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1558 frame->s2, frame->s3, frame->s4, frame->s5);
1559
1560 log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1561 frame->s6, frame->s7, frame->k0, frame->k1);
1562
1563 log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1564 frame->gp, frame->sp, frame->s8, frame->ra);
1565
1566 log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1567 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1568
1569 #ifdef IC_REG
1570 log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n",
1571 frame->cause, frame->pc, frame->ic);
1572 #else
1573 log(LOG_ERR, "\tcause: %08x\tpc: %08x\n",
1574 frame->cause, frame->pc);
1575 #endif
1576 }
1577
1578 #ifdef TRAP_DEBUG
1579 static void
1580 trap_frame_dump(struct trapframe *frame)
1581 {
1582 printf("Trapframe Register Dump:\n");
1583 printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n",
1584 0, frame->ast, frame->v0, frame->v1);
1585
1586 printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n",
1587 frame->a0, frame->a1, frame->a2, frame->a3);
1588
1589 printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n",
1590 frame->t0, frame->t1, frame->t2, frame->t3);
1591
1592 printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n",
1593 frame->t4, frame->t5, frame->t6, frame->t7);
1594
1595 printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n",
1596 frame->t8, frame->t9, frame->s0, frame->s1);
1597
1598 printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n",
1599 frame->s2, frame->s3, frame->s4, frame->s5);
1600
1601 printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n",
1602 frame->s6, frame->s7, frame->k0, frame->k1);
1603
1604 printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n",
1605 frame->gp, frame->sp, frame->s8, frame->ra);
1606
1607 printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n",
1608 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr);
1609
1610 #ifdef IC_REG
1611 printf("\tcause: %08x\tpc: %08x\tic: %08x\n",
1612 frame->cause, frame->pc, frame->ic);
1613 #else
1614 printf("\tcause: %08x\tpc: %08x\n",
1615 frame->cause, frame->pc);
1616 #endif
1617 }
1618
1619 #endif
1620
1621
1622 static void
1623 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1624 {
1625 pt_entry_t *ptep;
1626 pd_entry_t *pdep;
1627 struct proc *p = curproc;
1628
1629 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT]));
1630 if (*pdep)
1631 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1632 else
1633 ptep = (pt_entry_t *)0;
1634
1635 *pdepp = pdep;
1636 *ptepp = ptep;
1637 }
1638
1639
1640 static void
1641 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1642 {
1643 pt_entry_t *ptep;
1644 pd_entry_t *pdep;
1645 unsigned int *addr;
1646 struct proc *p = curproc;
1647 char *read_or_write;
1648 register_t pc;
1649
1650 trap_type &= ~T_USER;
1651
1652 #ifdef SMP
1653 printf("cpuid = %d\n", PCPU_GET(cpuid));
1654 #endif
1655 switch (trap_type) {
1656 case T_TLB_ST_MISS:
1657 case T_ADDR_ERR_ST:
1658 read_or_write = "write";
1659 break;
1660 case T_TLB_LD_MISS:
1661 case T_ADDR_ERR_LD:
1662 case T_BUS_ERR_IFETCH:
1663 read_or_write = "read";
1664 break;
1665 default:
1666 read_or_write = "";
1667 }
1668
1669 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1670 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n",
1671 msg, p->p_pid, p->p_comm,
1672 p->p_ucred ? p->p_ucred->cr_uid : -1,
1673 pc,
1674 read_or_write,
1675 frame->badvaddr);
1676
1677 /* log registers in trap frame */
1678 log_frame_dump(frame);
1679
1680 get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1681
1682 /*
1683 * Dump a few words around faulting instruction, if the addres is
1684 * valid.
1685 */
1686 if (!(pc & 3) && (pc != frame->badvaddr) &&
1687 (trap_type != T_BUS_ERR_IFETCH) &&
1688 useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1689 /* dump page table entry for faulting instruction */
1690 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n",
1691 pc, *pdep, ptep ? *ptep : 0);
1692
1693 addr = (unsigned int *)pc;
1694 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1695 addr);
1696 log(LOG_ERR, "%08x %08x %08x %08x\n",
1697 addr[0], addr[1], addr[2], addr[3]);
1698 } else {
1699 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n",
1700 pc, *pdep, ptep ? *ptep : 0);
1701 }
1702 /* panic("Bad trap");*/
1703 }
1704
1705
1706 /*
1707 * Unaligned load/store emulation
1708 */
1709 static int
1710 mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc)
1711 {
1712 register_t *reg = (register_t *) frame;
1713 u_int32_t inst = *((u_int32_t *) pc);
1714 u_int32_t value_msb, value;
1715 int access_type = 0;
1716
1717 switch (MIPS_INST_OPCODE(inst)) {
1718 case OP_LHU:
1719 lbu_macro(value_msb, addr);
1720 addr += 1;
1721 lbu_macro(value, addr);
1722 value |= value_msb << 8;
1723 reg[MIPS_INST_RT(inst)] = value;
1724 access_type = MIPS_LHU_ACCESS;
1725 break;
1726
1727 case OP_LH:
1728 lb_macro(value_msb, addr);
1729 addr += 1;
1730 lbu_macro(value, addr);
1731 value |= value_msb << 8;
1732 reg[MIPS_INST_RT(inst)] = value;
1733 access_type = MIPS_LH_ACCESS;
1734 break;
1735
1736 case OP_LWU:
1737 lwl_macro(value, addr);
1738 addr += 3;
1739 lwr_macro(value, addr);
1740 value &= 0xffffffff;
1741 reg[MIPS_INST_RT(inst)] = value;
1742 access_type = MIPS_LWU_ACCESS;
1743 break;
1744
1745 case OP_LW:
1746 lwl_macro(value, addr);
1747 addr += 3;
1748 lwr_macro(value, addr);
1749 reg[MIPS_INST_RT(inst)] = value;
1750 access_type = MIPS_LW_ACCESS;
1751 break;
1752
1753 case OP_SH:
1754 value = reg[MIPS_INST_RT(inst)];
1755 value_msb = value >> 8;
1756 sb_macro(value_msb, addr);
1757 addr += 1;
1758 sb_macro(value, addr);
1759 access_type = MIPS_SH_ACCESS;
1760 break;
1761
1762 case OP_SW:
1763 value = reg[MIPS_INST_RT(inst)];
1764 swl_macro(value, addr);
1765 addr += 3;
1766 swr_macro(value, addr);
1767 access_type = MIPS_SW_ACCESS;
1768 break;
1769
1770 default:
1771 break;
1772 }
1773
1774 return access_type;
1775 }
1776
1777
1778 static int
1779 emulate_unaligned_access(struct trapframe *frame)
1780 {
1781 register_t pc;
1782 int access_type = 0;
1783
1784 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1785
1786 /*
1787 * Fall through if it's instruction fetch exception
1788 */
1789 if (!((pc & 3) || (pc == frame->badvaddr))) {
1790
1791 /*
1792 * Handle unaligned load and store
1793 */
1794
1795 /*
1796 * Return access type if the instruction was emulated.
1797 * Otherwise restore pc and fall through.
1798 */
1799 access_type = mips_unaligned_load_store(frame,
1800 frame->badvaddr, pc);
1801
1802 if (access_type) {
1803 if (DELAYBRANCH(frame->cause))
1804 frame->pc = MipsEmulateBranch(frame, frame->pc,
1805 0, 0);
1806 else
1807 frame->pc += 4;
1808
1809 log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n",
1810 access_name[access_type - 1], pc, frame->badvaddr);
1811 }
1812 }
1813 return access_type;
1814 }
Cache object: 595b321752aac209aaa3c5ef4316051f
|