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