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