]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/mips/mips/trap.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / mips / mips / trap.c
1 /*      $OpenBSD: trap.c,v 1.19 1998/09/30 12:40:41 pefo Exp $  */
2 /* tracked to 1.23 */
3 /*-
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1992, 1993
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department and Ralph Campbell.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * from: Utah Hdr: trap.c 1.32 91/04/06
37  *
38  *      from: @(#)trap.c        8.5 (Berkeley) 1/11/94
39  *      JNPR: trap.c,v 1.13.2.2 2007/08/29 10:03:49 girish
40  */
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include "opt_ddb.h"
45 #include "opt_global.h"
46
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 }