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