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