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