]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/trap.c
Merge clang trunk r321017 to contrib/llvm/tools/clang.
[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_compat.h"
47 #include "opt_ddb.h"
48 #include "opt_ktrace.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/sysent.h>
53 #include <sys/proc.h>
54 #include <sys/kernel.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)  ((int)(x) < 0)
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         if (se->sv_mask)
447                 sa->code &= se->sv_mask;
448
449         if (sa->code >= se->sv_size)
450                 sa->callp = &se->sv_table[0];
451         else
452                 sa->callp = &se->sv_table[sa->code];
453
454         sa->narg = sa->callp->sy_narg;
455
456         if (sa->narg > nsaved) {
457 #if defined(__mips_n32) || defined(__mips_n64)
458                 /*
459                  * XXX
460                  * Is this right for new ABIs?  I think the 4 there
461                  * should be 8, size there are 8 registers to skip,
462                  * not 4, but I'm not certain.
463                  */
464 #ifdef COMPAT_FREEBSD32
465                 if (!SV_PROC_FLAG(td->td_proc, SV_ILP32))
466 #endif
467                         printf("SYSCALL #%u pid:%u, narg (%u) > nsaved (%u).\n",
468                             sa->code, td->td_proc->p_pid, sa->narg, nsaved);
469 #endif
470 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
471                 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
472                         unsigned i;
473                         int32_t arg;
474
475                         error = 0; /* XXX GCC is awful.  */
476                         for (i = nsaved; i < sa->narg; i++) {
477                                 error = copyin((caddr_t)(intptr_t)(locr0->sp +
478                                     (4 + (i - nsaved)) * sizeof(int32_t)),
479                                     (caddr_t)&arg, sizeof arg);
480                                 if (error != 0)
481                                         break;
482                                 sa->args[i] = arg;
483                         }
484                 } else
485 #endif
486                 error = copyin((caddr_t)(intptr_t)(locr0->sp +
487                     4 * sizeof(register_t)), (caddr_t)&sa->args[nsaved],
488                    (u_int)(sa->narg - nsaved) * sizeof(register_t));
489                 if (error != 0) {
490                         locr0->v0 = error;
491                         locr0->a3 = 1;
492                 }
493         } else
494                 error = 0;
495
496         if (error == 0) {
497                 td->td_retval[0] = 0;
498                 td->td_retval[1] = locr0->v1;
499         }
500
501         return (error);
502 }
503
504 #undef __FBSDID
505 #define __FBSDID(x)
506 #include "../../kern/subr_syscall.c"
507
508 /*
509  * Handle an exception.
510  * Called from MipsKernGenException() or MipsUserGenException()
511  * when a processor trap occurs.
512  * In the case of a kernel trap, we return the pc where to resume if
513  * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc.
514  */
515 register_t
516 trap(struct trapframe *trapframe)
517 {
518         int type, usermode;
519         int i = 0;
520         unsigned ucode = 0;
521         struct thread *td = curthread;
522         struct proc *p = curproc;
523         vm_prot_t ftype;
524         pmap_t pmap;
525         int access_type;
526         ksiginfo_t ksi;
527         char *msg = NULL;
528         intptr_t addr = 0;
529         register_t pc;
530         int cop;
531         register_t *frame_regs;
532
533         trapdebug_enter(trapframe, 0);
534         
535         type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
536         if (TRAPF_USERMODE(trapframe)) {
537                 type |= T_USER;
538                 usermode = 1;
539         } else {
540                 usermode = 0;
541         }
542
543         /*
544          * Enable hardware interrupts if they were on before the trap. If it
545          * was off disable all so we don't accidently enable it when doing a
546          * return to userland.
547          */
548         if (trapframe->sr & MIPS_SR_INT_IE) {
549                 set_intr_mask(trapframe->sr & MIPS_SR_INT_MASK);
550                 intr_enable();
551         } else {
552                 intr_disable();
553         }
554
555 #ifdef TRAP_DEBUG
556         if (trap_debug) {
557                 static vm_offset_t last_badvaddr = 0;
558                 static vm_offset_t this_badvaddr = 0;
559                 static int count = 0;
560                 u_int32_t pid;
561
562                 printf("trap type %x (%s - ", type,
563                     trap_type[type & (~T_USER)]);
564
565                 if (type & T_USER)
566                         printf("user mode)\n");
567                 else
568                         printf("kernel mode)\n");
569
570 #ifdef SMP
571                 printf("cpuid = %d\n", PCPU_GET(cpuid));
572 #endif
573                 pid = mips_rd_entryhi() & TLBHI_ASID_MASK;
574                 printf("badaddr = %#jx, pc = %#jx, ra = %#jx, sp = %#jx, sr = %jx, pid = %d, ASID = %u\n",
575                     (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
576                     (intmax_t)trapframe->sp, (intmax_t)trapframe->sr,
577                     (curproc ? curproc->p_pid : -1), pid);
578
579                 switch (type & ~T_USER) {
580                 case T_TLB_MOD:
581                 case T_TLB_LD_MISS:
582                 case T_TLB_ST_MISS:
583                 case T_ADDR_ERR_LD:
584                 case T_ADDR_ERR_ST:
585                         this_badvaddr = trapframe->badvaddr;
586                         break;
587                 case T_SYSCALL:
588                         this_badvaddr = trapframe->ra;
589                         break;
590                 default:
591                         this_badvaddr = trapframe->pc;
592                         break;
593                 }
594                 if ((last_badvaddr == this_badvaddr) &&
595                     ((type & ~T_USER) != T_SYSCALL) &&
596                     ((type & ~T_USER) != T_COP_UNUSABLE)) {
597                         if (++count == 3) {
598                                 trap_frame_dump(trapframe);
599                                 panic("too many faults at %p\n", (void *)last_badvaddr);
600                         }
601                 } else {
602                         last_badvaddr = this_badvaddr;
603                         count = 0;
604                 }
605         }
606 #endif
607
608 #ifdef KDTRACE_HOOKS
609         /*
610          * A trap can occur while DTrace executes a probe. Before
611          * executing the probe, DTrace blocks re-scheduling and sets
612          * a flag in its per-cpu flags to indicate that it doesn't
613          * want to fault. On returning from the probe, the no-fault
614          * flag is cleared and finally re-scheduling is enabled.
615          *
616          * If the DTrace kernel module has registered a trap handler,
617          * call it and if it returns non-zero, assume that it has
618          * handled the trap and modified the trap frame so that this
619          * function can return normally.
620          */
621         /*
622          * XXXDTRACE: add pid probe handler here (if ever)
623          */
624         if (!usermode) {
625                 if (dtrace_trap_func != NULL &&
626                     (*dtrace_trap_func)(trapframe, type) != 0)
627                         return (trapframe->pc);
628         }
629 #endif
630
631         switch (type) {
632         case T_MCHECK:
633 #ifdef DDB
634                 kdb_trap(type, 0, trapframe);
635 #endif
636                 panic("MCHECK\n");
637                 break;
638         case T_TLB_MOD:
639                 /* check for kernel address */
640                 if (KERNLAND(trapframe->badvaddr)) {
641                         if (pmap_emulate_modified(kernel_pmap, 
642                             trapframe->badvaddr) != 0) {
643                                 ftype = VM_PROT_WRITE;
644                                 goto kernel_fault;
645                         }
646                         return (trapframe->pc);
647                 }
648                 /* FALLTHROUGH */
649
650         case T_TLB_MOD + T_USER:
651                 pmap = &p->p_vmspace->vm_pmap;
652                 if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) {
653                         ftype = VM_PROT_WRITE;
654                         goto dofault;
655                 }
656                 if (!usermode)
657                         return (trapframe->pc);
658                 goto out;
659
660         case T_TLB_LD_MISS:
661         case T_TLB_ST_MISS:
662                 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
663                 /* check for kernel address */
664                 if (KERNLAND(trapframe->badvaddr)) {
665                         vm_offset_t va;
666                         int rv;
667
668         kernel_fault:
669                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
670                         rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL);
671                         if (rv == KERN_SUCCESS)
672                                 return (trapframe->pc);
673                         if (td->td_pcb->pcb_onfault != NULL) {
674                                 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
675                                 td->td_pcb->pcb_onfault = NULL;
676                                 return (pc);
677                         }
678                         goto err;
679                 }
680
681                 /*
682                  * It is an error for the kernel to access user space except
683                  * through the copyin/copyout routines.
684                  */
685                 if (td->td_pcb->pcb_onfault == NULL)
686                         goto err;
687
688                 /* check for fuswintr() or suswintr() getting a page fault */
689                 /* XXX There must be a nicer way to do this.  */
690                 if (td->td_pcb->pcb_onfault == fswintrberr) {
691                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
692                         td->td_pcb->pcb_onfault = NULL;
693                         return (pc);
694                 }
695
696                 goto dofault;
697
698         case T_TLB_LD_MISS + T_USER:
699                 ftype = VM_PROT_READ;
700                 goto dofault;
701
702         case T_TLB_ST_MISS + T_USER:
703                 ftype = VM_PROT_WRITE;
704 dofault:
705                 {
706                         vm_offset_t va;
707                         struct vmspace *vm;
708                         vm_map_t map;
709                         int rv = 0;
710
711                         vm = p->p_vmspace;
712                         map = &vm->vm_map;
713                         va = trunc_page((vm_offset_t)trapframe->badvaddr);
714                         if (KERNLAND(trapframe->badvaddr)) {
715                                 /*
716                                  * Don't allow user-mode faults in kernel
717                                  * address space.
718                                  */
719                                 goto nogo;
720                         }
721
722                         rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
723                         /*
724                          * XXXDTRACE: add dtrace_doubletrap_func here?
725                          */
726 #ifdef VMFAULT_TRACE
727                         printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
728                             map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
729                             ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
730 #endif
731
732                         if (rv == KERN_SUCCESS) {
733                                 if (!usermode) {
734                                         return (trapframe->pc);
735                                 }
736                                 goto out;
737                         }
738         nogo:
739                         if (!usermode) {
740                                 if (td->td_pcb->pcb_onfault != NULL) {
741                                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
742                                         td->td_pcb->pcb_onfault = NULL;
743                                         return (pc);
744                                 }
745                                 goto err;
746                         }
747                         i = SIGSEGV;
748                         if (rv == KERN_PROTECTION_FAILURE)
749                                 ucode = SEGV_ACCERR;
750                         else
751                                 ucode = SEGV_MAPERR;
752                         addr = trapframe->pc;
753
754                         msg = "BAD_PAGE_FAULT";
755                         log_bad_page_fault(msg, trapframe, type);
756
757                         break;
758                 }
759
760         case T_ADDR_ERR_LD + T_USER:    /* misaligned or kseg access */
761         case T_ADDR_ERR_ST + T_USER:    /* misaligned or kseg access */
762                 if (trapframe->badvaddr < 0 ||
763                     trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
764                         msg = "ADDRESS_SPACE_ERR";
765                 } else if (allow_unaligned_acc) {
766                         int mode;
767
768                         if (type == (T_ADDR_ERR_LD + T_USER))
769                                 mode = VM_PROT_READ;
770                         else
771                                 mode = VM_PROT_WRITE;
772
773                         access_type = emulate_unaligned_access(trapframe, mode);
774                         if (access_type != 0)
775                                 goto out;
776                         msg = "ALIGNMENT_FIX_ERR";
777                 } else {
778                         msg = "ADDRESS_ERR";
779                 }
780
781                 /* FALL THROUGH */
782
783         case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
784         case T_BUS_ERR_LD_ST + T_USER:  /* BERR asserted to cpu */
785                 ucode = 0;      /* XXX should be VM_PROT_something */
786                 i = SIGBUS;
787                 addr = trapframe->pc;
788                 if (!msg)
789                         msg = "BUS_ERR";
790                 log_bad_page_fault(msg, trapframe, type);
791                 break;
792
793         case T_SYSCALL + T_USER:
794                 {
795                         int error;
796
797                         td->td_sa.trapframe = trapframe;
798                         error = syscallenter(td);
799
800 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
801                         if (trp == trapdebug)
802                                 trapdebug[TRAPSIZE - 1].code = td->td_sa.code;
803                         else
804                                 trp[-1].code = td->td_sa.code;
805 #endif
806                         trapdebug_enter(td->td_frame, -td->td_sa.code);
807
808                         /*
809                          * The sync'ing of I & D caches for SYS_ptrace() is
810                          * done by procfs_domem() through procfs_rwmem()
811                          * instead of being done here under a special check
812                          * for SYS_ptrace().
813                          */
814                         syscallret(td, error);
815                         return (trapframe->pc);
816                 }
817
818 #if defined(KDTRACE_HOOKS) || defined(DDB)
819         case T_BREAK:
820 #ifdef KDTRACE_HOOKS
821                 if (!usermode && dtrace_invop_jump_addr != 0) {
822                         dtrace_invop_jump_addr(trapframe);
823                         return (trapframe->pc);
824                 }
825 #endif
826 #ifdef DDB
827                 kdb_trap(type, 0, trapframe);
828                 return (trapframe->pc);
829 #endif
830 #endif
831
832         case T_BREAK + T_USER:
833                 {
834                         intptr_t va;
835                         uint32_t instr;
836
837                         /* compute address of break instruction */
838                         va = trapframe->pc;
839                         if (DELAYBRANCH(trapframe->cause))
840                                 va += sizeof(int);
841
842                         /* read break instruction */
843                         instr = fuword32((caddr_t)va);
844 #if 0
845                         printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
846                             p->p_comm, p->p_pid, instr, trapframe->pc,
847                             p->p_md.md_ss_addr, p->p_md.md_ss_instr);   /* XXX */
848 #endif
849                         if (td->td_md.md_ss_addr != va ||
850                             instr != MIPS_BREAK_SSTEP) {
851                                 i = SIGTRAP;
852                                 addr = trapframe->pc;
853                                 break;
854                         }
855                         /*
856                          * The restoration of the original instruction and
857                          * the clearing of the breakpoint will be done later
858                          * by the call to ptrace_clear_single_step() in
859                          * issignal() when SIGTRAP is processed.
860                          */
861                         addr = trapframe->pc;
862                         i = SIGTRAP;
863                         break;
864                 }
865
866         case T_IWATCH + T_USER:
867         case T_DWATCH + T_USER:
868                 {
869                         intptr_t va;
870
871                         /* compute address of trapped instruction */
872                         va = trapframe->pc;
873                         if (DELAYBRANCH(trapframe->cause))
874                                 va += sizeof(int);
875                         printf("watch exception @ %p\n", (void *)va);
876                         i = SIGTRAP;
877                         addr = va;
878                         break;
879                 }
880
881         case T_TRAP + T_USER:
882                 {
883                         intptr_t va;
884                         uint32_t instr;
885                         struct trapframe *locr0 = td->td_frame;
886
887                         /* compute address of trap instruction */
888                         va = trapframe->pc;
889                         if (DELAYBRANCH(trapframe->cause))
890                                 va += sizeof(int);
891                         /* read break instruction */
892                         instr = fuword32((caddr_t)va);
893
894                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
895                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
896                                     0);
897                         } else {
898                                 locr0->pc += sizeof(int);
899                         }
900                         addr = va;
901                         i = SIGEMT;     /* Stuff it with something for now */
902                         break;
903                 }
904
905         case T_RES_INST + T_USER:
906                 {
907                         InstFmt inst;
908                         inst = *(InstFmt *)(intptr_t)trapframe->pc;
909                         switch (inst.RType.op) {
910                         case OP_SPECIAL3:
911                                 switch (inst.RType.func) {
912                                 case OP_RDHWR:
913                                         /* Register 29 used for TLS */
914                                         if (inst.RType.rd == 29) {
915                                                 frame_regs = &(trapframe->zero);
916                                                 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
917                                                 frame_regs[inst.RType.rt] += td->td_md.md_tls_tcb_offset;
918                                                 trapframe->pc += sizeof(int);
919                                                 goto out;
920                                         }
921                                 break;
922                                 }
923                         break;
924                         }
925
926                         log_illegal_instruction("RES_INST", trapframe);
927                         i = SIGILL;
928                         addr = trapframe->pc;
929                 }
930                 break;
931         case T_C2E:
932         case T_C2E + T_USER:
933                 goto err;
934                 break;
935         case T_COP_UNUSABLE:
936 #ifdef  CPU_CNMIPS
937                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
938                 /* Handle only COP2 exception */
939                 if (cop != 2)
940                         goto err;
941
942                 addr = trapframe->pc;
943                 /* save userland cop2 context if it has been touched */
944                 if ((td->td_md.md_flags & MDTD_COP2USED) &&
945                     (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
946                         if (td->td_md.md_ucop2)
947                                 octeon_cop2_save(td->td_md.md_ucop2);
948                         else
949                                 panic("COP2 was used in user mode but md_ucop2 is NULL");
950                 }
951
952                 if (td->td_md.md_cop2 == NULL) {
953                         td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
954                         if (td->td_md.md_cop2 == NULL)
955                                 panic("Failed to allocate COP2 context");
956                         memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
957                 }
958
959                 octeon_cop2_restore(td->td_md.md_cop2);
960                 
961                 /* Make userland re-request its context */
962                 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
963                 td->td_md.md_flags |= MDTD_COP2USED;
964                 td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
965                 /* Enable COP2, it will be disabled in cpu_switch */
966                 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
967                 return (trapframe->pc);
968 #else
969                 goto err;
970                 break;
971 #endif
972
973         case T_COP_UNUSABLE + T_USER:
974                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
975                 if (cop == 1) {
976                         /* FP (COP1) instruction */
977                         if (cpuinfo.fpu_id == 0) {
978                                 log_illegal_instruction("COP1_UNUSABLE",
979                                     trapframe);
980                                 i = SIGILL;
981                                 break;
982                         }
983                         addr = trapframe->pc;
984                         MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
985                         PCPU_SET(fpcurthread, td);
986 #if defined(__mips_n64)
987                         td->td_frame->sr |= MIPS_SR_COP_1_BIT | MIPS_SR_FR;
988 #else
989                         td->td_frame->sr |= MIPS_SR_COP_1_BIT;
990 #endif
991                         td->td_md.md_flags |= MDTD_FPUSED;
992                         goto out;
993                 }
994 #ifdef  CPU_CNMIPS
995                 else  if (cop == 2) {
996                         addr = trapframe->pc;
997                         if ((td->td_md.md_flags & MDTD_COP2USED) &&
998                             (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
999                                 if (td->td_md.md_cop2)
1000                                         octeon_cop2_save(td->td_md.md_cop2);
1001                                 else
1002                                         panic("COP2 was used in kernel mode but md_cop2 is NULL");
1003                         }
1004
1005                         if (td->td_md.md_ucop2 == NULL) {
1006                                 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
1007                                 if (td->td_md.md_ucop2 == NULL)
1008                                         panic("Failed to allocate userland COP2 context");
1009                                 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
1010                         }
1011
1012                         octeon_cop2_restore(td->td_md.md_ucop2);
1013
1014                         td->td_frame->sr |= MIPS_SR_COP_2_BIT;
1015                         td->td_md.md_flags |= MDTD_COP2USED;
1016                         td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
1017                         goto out;
1018                 }
1019 #endif
1020                 else {
1021                         log_illegal_instruction("COPn_UNUSABLE", trapframe);
1022                         i = SIGILL;     /* only FPU instructions allowed */
1023                         break;
1024                 }
1025
1026         case T_FPE:
1027 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1028                 trapDump("fpintr");
1029 #else
1030                 printf("FPU Trap: PC %#jx CR %x SR %x\n",
1031                     (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
1032                 goto err;
1033 #endif
1034
1035         case T_FPE + T_USER:
1036                 if (!emulate_fp) {
1037                         i = SIGFPE;
1038                         addr = trapframe->pc;
1039                         break;
1040                 }
1041                 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
1042                 goto out;
1043
1044         case T_OVFLOW + T_USER:
1045                 i = SIGFPE;
1046                 addr = trapframe->pc;
1047                 break;
1048
1049         case T_ADDR_ERR_LD:     /* misaligned access */
1050         case T_ADDR_ERR_ST:     /* misaligned access */
1051 #ifdef TRAP_DEBUG
1052                 if (trap_debug) {
1053                         printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
1054                             (intmax_t)trapframe->badvaddr);
1055                 }
1056 #endif
1057                 /* Only allow emulation on a user address */
1058                 if (allow_unaligned_acc &&
1059                     ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
1060                         int mode;
1061
1062                         if (type == T_ADDR_ERR_LD)
1063                                 mode = VM_PROT_READ;
1064                         else
1065                                 mode = VM_PROT_WRITE;
1066
1067                         access_type = emulate_unaligned_access(trapframe, mode);
1068                         if (access_type != 0)
1069                                 return (trapframe->pc);
1070                 }
1071                 /* FALLTHROUGH */
1072
1073         case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
1074                 if (td->td_pcb->pcb_onfault != NULL) {
1075                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
1076                         td->td_pcb->pcb_onfault = NULL;
1077                         return (pc);
1078                 }
1079
1080                 /* FALLTHROUGH */
1081
1082         default:
1083 err:
1084
1085 #if !defined(SMP) && defined(DEBUG)
1086                 trapDump("trap");
1087 #endif
1088 #ifdef SMP
1089                 printf("cpu:%d-", PCPU_GET(cpuid));
1090 #endif
1091                 printf("Trap cause = %d (%s - ", type,
1092                     trap_type[type & (~T_USER)]);
1093
1094                 if (type & T_USER)
1095                         printf("user mode)\n");
1096                 else
1097                         printf("kernel mode)\n");
1098
1099 #ifdef TRAP_DEBUG
1100                 if (trap_debug)
1101                         printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
1102                                (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
1103                                (intmax_t)trapframe->sr);
1104 #endif
1105
1106 #ifdef KDB
1107                 if (debugger_on_panic || kdb_active) {
1108                         kdb_trap(type, 0, trapframe);
1109                 }
1110 #endif
1111                 panic("trap");
1112         }
1113         td->td_frame->pc = trapframe->pc;
1114         td->td_frame->cause = trapframe->cause;
1115         td->td_frame->badvaddr = trapframe->badvaddr;
1116         ksiginfo_init_trap(&ksi);
1117         ksi.ksi_signo = i;
1118         ksi.ksi_code = ucode;
1119         ksi.ksi_addr = (void *)addr;
1120         ksi.ksi_trapno = type;
1121         trapsignal(td, &ksi);
1122 out:
1123
1124         /*
1125          * Note: we should only get here if returning to user mode.
1126          */
1127         userret(td, trapframe);
1128         return (trapframe->pc);
1129 }
1130
1131 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1132 void
1133 trapDump(char *msg)
1134 {
1135         register_t s;
1136         int i;
1137
1138         s = intr_disable();
1139         printf("trapDump(%s)\n", msg);
1140         for (i = 0; i < TRAPSIZE; i++) {
1141                 if (trp == trapdebug) {
1142                         trp = &trapdebug[TRAPSIZE - 1];
1143                 } else {
1144                         trp--;
1145                 }
1146
1147                 if (trp->cause == 0)
1148                         break;
1149
1150                 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
1151                     trap_type[(trp->cause & MIPS_CR_EXC_CODE) >> 
1152                         MIPS_CR_EXC_CODE_SHIFT],
1153                     (intmax_t)trp->vadr, (intmax_t)trp->pc,
1154                     (intmax_t)trp->cause, (intmax_t)trp->status);
1155
1156                 printf("   RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
1157                     (intmax_t)trp->sp, (int)trp->code);
1158         }
1159         intr_restore(s);
1160 }
1161 #endif
1162
1163
1164 /*
1165  * Return the resulting PC as if the branch was executed.
1166  */
1167 uintptr_t
1168 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1169     uintptr_t instptr)
1170 {
1171         InstFmt inst;
1172         register_t *regsPtr = (register_t *) framePtr;
1173         uintptr_t retAddr = 0;
1174         int condition;
1175
1176 #define GetBranchDest(InstPtr, inst) \
1177         (InstPtr + 4 + ((short)inst.IType.imm << 2))
1178
1179
1180         if (instptr) {
1181                 if (instptr < MIPS_KSEG0_START)
1182                         inst.word = fuword32((void *)instptr);
1183                 else
1184                         inst = *(InstFmt *) instptr;
1185         } else {
1186                 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1187                         inst.word = fuword32((void *)instPC);
1188                 else
1189                         inst = *(InstFmt *) instPC;
1190         }
1191
1192         switch ((int)inst.JType.op) {
1193         case OP_SPECIAL:
1194                 switch ((int)inst.RType.func) {
1195                 case OP_JR:
1196                 case OP_JALR:
1197                         retAddr = regsPtr[inst.RType.rs];
1198                         break;
1199
1200                 default:
1201                         retAddr = instPC + 4;
1202                         break;
1203                 }
1204                 break;
1205
1206         case OP_BCOND:
1207                 switch ((int)inst.IType.rt) {
1208                 case OP_BLTZ:
1209                 case OP_BLTZL:
1210                 case OP_BLTZAL:
1211                 case OP_BLTZALL:
1212                         if ((int)(regsPtr[inst.RType.rs]) < 0)
1213                                 retAddr = GetBranchDest(instPC, inst);
1214                         else
1215                                 retAddr = instPC + 8;
1216                         break;
1217
1218                 case OP_BGEZ:
1219                 case OP_BGEZL:
1220                 case OP_BGEZAL:
1221                 case OP_BGEZALL:
1222                         if ((int)(regsPtr[inst.RType.rs]) >= 0)
1223                                 retAddr = GetBranchDest(instPC, inst);
1224                         else
1225                                 retAddr = instPC + 8;
1226                         break;
1227
1228                 case OP_TGEI:
1229                 case OP_TGEIU:
1230                 case OP_TLTI:
1231                 case OP_TLTIU:
1232                 case OP_TEQI:
1233                 case OP_TNEI:
1234                         retAddr = instPC + 4;   /* Like syscall... */
1235                         break;
1236
1237                 default:
1238                         panic("MipsEmulateBranch: Bad branch cond");
1239                 }
1240                 break;
1241
1242         case OP_J:
1243         case OP_JAL:
1244                 retAddr = (inst.JType.target << 2) |
1245                     ((unsigned)(instPC + 4) & 0xF0000000);
1246                 break;
1247
1248         case OP_BEQ:
1249         case OP_BEQL:
1250                 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1251                         retAddr = GetBranchDest(instPC, inst);
1252                 else
1253                         retAddr = instPC + 8;
1254                 break;
1255
1256         case OP_BNE:
1257         case OP_BNEL:
1258                 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1259                         retAddr = GetBranchDest(instPC, inst);
1260                 else
1261                         retAddr = instPC + 8;
1262                 break;
1263
1264         case OP_BLEZ:
1265         case OP_BLEZL:
1266                 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1267                         retAddr = GetBranchDest(instPC, inst);
1268                 else
1269                         retAddr = instPC + 8;
1270                 break;
1271
1272         case OP_BGTZ:
1273         case OP_BGTZL:
1274                 if ((int)(regsPtr[inst.RType.rs]) > 0)
1275                         retAddr = GetBranchDest(instPC, inst);
1276                 else
1277                         retAddr = instPC + 8;
1278                 break;
1279
1280         case OP_COP1:
1281                 switch (inst.RType.rs) {
1282                 case OP_BCx:
1283                 case OP_BCy:
1284                         if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1285                                 condition = fpcCSR & MIPS_FPU_COND_BIT;
1286                         else
1287                                 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1288                         if (condition)
1289                                 retAddr = GetBranchDest(instPC, inst);
1290                         else
1291                                 retAddr = instPC + 8;
1292                         break;
1293
1294                 default:
1295                         retAddr = instPC + 4;
1296                 }
1297                 break;
1298
1299         default:
1300                 retAddr = instPC + 4;
1301         }
1302         return (retAddr);
1303 }
1304
1305 static void
1306 log_frame_dump(struct trapframe *frame)
1307 {
1308         log(LOG_ERR, "Trapframe Register Dump:\n");
1309         log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1310             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1311
1312         log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1313             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1314
1315 #if defined(__mips_n32) || defined(__mips_n64)
1316         log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
1317             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1318
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 #else
1322         log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1323             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1324
1325         log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1326             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1327 #endif
1328         log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1329             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1330
1331         log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1332             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1333
1334         log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1335             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1336
1337         log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1338             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1339
1340         log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1341             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1342
1343         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1344             (intmax_t)frame->cause, (intmax_t)frame->pc);
1345 }
1346
1347 #ifdef TRAP_DEBUG
1348 static void
1349 trap_frame_dump(struct trapframe *frame)
1350 {
1351         printf("Trapframe Register Dump:\n");
1352         printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1353             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1354
1355         printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1356             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1357 #if defined(__mips_n32) || defined(__mips_n64)
1358         printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
1359             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1360
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 #else
1364         printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1365             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1366
1367         printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1368             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1369 #endif
1370         printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1371             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1372
1373         printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1374             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1375
1376         printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1377             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1378
1379         printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1380             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1381
1382         printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1383             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1384
1385         printf("\tcause: %#jx\tpc: %#jx\n",
1386             (intmax_t)frame->cause, (intmax_t)frame->pc);
1387 }
1388
1389 #endif
1390
1391
1392 static void
1393 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1394 {
1395         pt_entry_t *ptep;
1396         pd_entry_t *pdep;
1397         struct proc *p = curproc;
1398
1399         pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1400         if (*pdep)
1401                 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1402         else
1403                 ptep = (pt_entry_t *)0;
1404
1405         *pdepp = pdep;
1406         *ptepp = ptep;
1407 }
1408
1409 static void
1410 log_illegal_instruction(const char *msg, struct trapframe *frame)
1411 {
1412         pt_entry_t *ptep;
1413         pd_entry_t *pdep;
1414         unsigned int *addr;
1415         struct thread *td;
1416         struct proc *p;
1417         register_t pc;
1418
1419         td = curthread;
1420         p = td->td_proc;
1421
1422 #ifdef SMP
1423         printf("cpuid = %d\n", PCPU_GET(cpuid));
1424 #endif
1425         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1426         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
1427             msg, p->p_pid, (long)td->td_tid, p->p_comm,
1428             p->p_ucred ? p->p_ucred->cr_uid : -1,
1429             (intmax_t)pc,
1430             (intmax_t)frame->ra);
1431
1432         /* log registers in trap frame */
1433         log_frame_dump(frame);
1434
1435         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1436
1437         /*
1438          * Dump a few words around faulting instruction, if the addres is
1439          * valid.
1440          */
1441         if (!(pc & 3) &&
1442             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1443                 /* dump page table entry for faulting instruction */
1444                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1445                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1446
1447                 addr = (unsigned int *)(intptr_t)pc;
1448                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1449                     addr);
1450                 log(LOG_ERR, "%08x %08x %08x %08x\n",
1451                     addr[0], addr[1], addr[2], addr[3]);
1452         } else {
1453                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1454                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1455         }
1456 }
1457
1458 static void
1459 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1460 {
1461         pt_entry_t *ptep;
1462         pd_entry_t *pdep;
1463         unsigned int *addr;
1464         struct thread *td;
1465         struct proc *p;
1466         char *read_or_write;
1467         register_t pc;
1468
1469         trap_type &= ~T_USER;
1470
1471         td = curthread;
1472         p = td->td_proc;
1473
1474 #ifdef SMP
1475         printf("cpuid = %d\n", PCPU_GET(cpuid));
1476 #endif
1477         switch (trap_type) {
1478         case T_TLB_MOD:
1479         case T_TLB_ST_MISS:
1480         case T_ADDR_ERR_ST:
1481                 read_or_write = "write";
1482                 break;
1483         case T_TLB_LD_MISS:
1484         case T_ADDR_ERR_LD:
1485         case T_BUS_ERR_IFETCH:
1486                 read_or_write = "read";
1487                 break;
1488         default:
1489                 read_or_write = "unknown";
1490         }
1491
1492         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1493         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
1494             "(type %#x) at %#jx\n",
1495             msg, p->p_pid, (long)td->td_tid, p->p_comm,
1496             p->p_ucred ? p->p_ucred->cr_uid : -1,
1497             (intmax_t)pc,
1498             read_or_write,
1499             trap_type,
1500             (intmax_t)frame->badvaddr);
1501
1502         /* log registers in trap frame */
1503         log_frame_dump(frame);
1504
1505         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1506
1507         /*
1508          * Dump a few words around faulting instruction, if the addres is
1509          * valid.
1510          */
1511         if (!(pc & 3) && (pc != frame->badvaddr) &&
1512             (trap_type != T_BUS_ERR_IFETCH) &&
1513             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1514                 /* dump page table entry for faulting instruction */
1515                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1516                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1517
1518                 addr = (unsigned int *)(intptr_t)pc;
1519                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1520                     addr);
1521                 log(LOG_ERR, "%08x %08x %08x %08x\n",
1522                     addr[0], addr[1], addr[2], addr[3]);
1523         } else {
1524                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1525                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1526         }
1527
1528         get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1529         log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1530             (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1531 }
1532
1533
1534 /*
1535  * Unaligned load/store emulation
1536  */
1537 static int
1538 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1539 {
1540         register_t *reg = (register_t *) frame;
1541         u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1542         register_t value_msb, value;
1543         unsigned size;
1544
1545         /*
1546          * ADDR_ERR faults have higher priority than TLB
1547          * Miss faults.  Therefore, it is necessary to
1548          * verify that the faulting address is a valid
1549          * virtual address within the process' address space
1550          * before trying to emulate the unaligned access.
1551          */
1552         switch (MIPS_INST_OPCODE(inst)) {
1553         case OP_LHU: case OP_LH:
1554         case OP_SH:
1555                 size = 2;
1556                 break;
1557         case OP_LWU: case OP_LW:
1558         case OP_SW:
1559                 size = 4;
1560                 break;
1561         case OP_LD:
1562         case OP_SD:
1563                 size = 8;
1564                 break;
1565         default:
1566                 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1567                 return (0);
1568         }
1569
1570         if (!useracc((void *)rounddown2((vm_offset_t)addr, size), size * 2, mode))
1571                 return (0);
1572
1573         /*
1574          * XXX
1575          * Handle LL/SC LLD/SCD.
1576          */
1577         switch (MIPS_INST_OPCODE(inst)) {
1578         case OP_LHU:
1579                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1580                 lbu_macro(value_msb, addr);
1581                 addr += 1;
1582                 lbu_macro(value, addr);
1583                 value |= value_msb << 8;
1584                 reg[MIPS_INST_RT(inst)] = value;
1585                 return (MIPS_LHU_ACCESS);
1586
1587         case OP_LH:
1588                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1589                 lb_macro(value_msb, addr);
1590                 addr += 1;
1591                 lbu_macro(value, addr);
1592                 value |= value_msb << 8;
1593                 reg[MIPS_INST_RT(inst)] = value;
1594                 return (MIPS_LH_ACCESS);
1595
1596         case OP_LWU:
1597                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1598                 lwl_macro(value, addr);
1599                 addr += 3;
1600                 lwr_macro(value, addr);
1601                 value &= 0xffffffff;
1602                 reg[MIPS_INST_RT(inst)] = value;
1603                 return (MIPS_LWU_ACCESS);
1604
1605         case OP_LW:
1606                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1607                 lwl_macro(value, addr);
1608                 addr += 3;
1609                 lwr_macro(value, addr);
1610                 reg[MIPS_INST_RT(inst)] = value;
1611                 return (MIPS_LW_ACCESS);
1612
1613 #if defined(__mips_n32) || defined(__mips_n64)
1614         case OP_LD:
1615                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1616                 ldl_macro(value, addr);
1617                 addr += 7;
1618                 ldr_macro(value, addr);
1619                 reg[MIPS_INST_RT(inst)] = value;
1620                 return (MIPS_LD_ACCESS);
1621 #endif
1622
1623         case OP_SH:
1624                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1625                 value = reg[MIPS_INST_RT(inst)];
1626                 value_msb = value >> 8;
1627                 sb_macro(value_msb, addr);
1628                 addr += 1;
1629                 sb_macro(value, addr);
1630                 return (MIPS_SH_ACCESS);
1631
1632         case OP_SW:
1633                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1634                 value = reg[MIPS_INST_RT(inst)];
1635                 swl_macro(value, addr);
1636                 addr += 3;
1637                 swr_macro(value, addr);
1638                 return (MIPS_SW_ACCESS);
1639
1640 #if defined(__mips_n32) || defined(__mips_n64)
1641         case OP_SD:
1642                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1643                 value = reg[MIPS_INST_RT(inst)];
1644                 sdl_macro(value, addr);
1645                 addr += 7;
1646                 sdr_macro(value, addr);
1647                 return (MIPS_SD_ACCESS);
1648 #endif
1649         }
1650         panic("%s: should not be reached.", __func__);
1651 }
1652
1653
1654 /*
1655  * XXX TODO: SMP?
1656  */
1657 static struct timeval unaligned_lasterr;
1658 static int unaligned_curerr;
1659
1660 static int unaligned_pps_log_limit = 4;
1661
1662 SYSCTL_INT(_machdep, OID_AUTO, unaligned_log_pps_limit, CTLFLAG_RWTUN,
1663     &unaligned_pps_log_limit, 0,
1664     "limit number of userland unaligned log messages per second");
1665
1666 static int
1667 emulate_unaligned_access(struct trapframe *frame, int mode)
1668 {
1669         register_t pc;
1670         int access_type = 0;
1671         struct thread *td = curthread;
1672         struct proc *p = curproc;
1673
1674         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1675
1676         /*
1677          * Fall through if it's instruction fetch exception
1678          */
1679         if (!((pc & 3) || (pc == frame->badvaddr))) {
1680
1681                 /*
1682                  * Handle unaligned load and store
1683                  */
1684
1685                 /*
1686                  * Return access type if the instruction was emulated.
1687                  * Otherwise restore pc and fall through.
1688                  */
1689                 access_type = mips_unaligned_load_store(frame,
1690                     mode, frame->badvaddr, pc);
1691
1692                 if (access_type) {
1693                         if (DELAYBRANCH(frame->cause))
1694                                 frame->pc = MipsEmulateBranch(frame, frame->pc,
1695                                     0, 0);
1696                         else
1697                                 frame->pc += 4;
1698
1699                         if (ppsratecheck(&unaligned_lasterr,
1700                             &unaligned_curerr, unaligned_pps_log_limit)) {
1701                                 /* XXX TODO: keep global/tid/pid counters? */
1702                                 log(LOG_INFO,
1703                                     "Unaligned %s: pid=%ld (%s), tid=%ld, "
1704                                     "pc=%#jx, badvaddr=%#jx\n",
1705                                     access_name[access_type - 1],
1706                                     (long) p->p_pid,
1707                                     p->p_comm,
1708                                     (long) td->td_tid,
1709                                     (intmax_t)pc,
1710                                     (intmax_t)frame->badvaddr);
1711                         }
1712                 }
1713         }
1714         return access_type;
1715 }