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