]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/trap.c
Merge ^/vendor/llvm-project/release-10.x up to its last change (upstream
[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 = (vm_offset_t)trapframe->badvaddr;
673                         rv = vm_fault_trap(kernel_map, va, ftype,
674                             VM_FAULT_NORMAL, NULL, NULL);
675                         if (rv == KERN_SUCCESS)
676                                 return (trapframe->pc);
677                         if (td->td_pcb->pcb_onfault != NULL) {
678                                 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
679                                 td->td_pcb->pcb_onfault = NULL;
680                                 return (pc);
681                         }
682                         goto err;
683                 }
684
685                 /*
686                  * It is an error for the kernel to access user space except
687                  * through the copyin/copyout routines.
688                  */
689                 if (td->td_pcb->pcb_onfault == NULL)
690                         goto err;
691
692                 goto dofault;
693
694         case T_TLB_LD_MISS + T_USER:
695                 ftype = VM_PROT_READ;
696                 goto dofault;
697
698         case T_TLB_ST_MISS + T_USER:
699                 ftype = VM_PROT_WRITE;
700 dofault:
701                 {
702                         vm_offset_t va;
703                         struct vmspace *vm;
704                         vm_map_t map;
705                         int rv = 0;
706
707                         vm = p->p_vmspace;
708                         map = &vm->vm_map;
709                         va = (vm_offset_t)trapframe->badvaddr;
710                         if (KERNLAND(trapframe->badvaddr)) {
711                                 /*
712                                  * Don't allow user-mode faults in kernel
713                                  * address space.
714                                  */
715                                 goto nogo;
716                         }
717
718                         rv = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL,
719                             &i, &ucode);
720                         /*
721                          * XXXDTRACE: add dtrace_doubletrap_func here?
722                          */
723 #ifdef VMFAULT_TRACE
724                         printf("vm_fault(%p (pmap %p), %p (%p), %x, %d) -> %x at pc %p\n",
725                             map, &vm->vm_pmap, (void *)va, (void *)(intptr_t)trapframe->badvaddr,
726                             ftype, VM_FAULT_NORMAL, rv, (void *)(intptr_t)trapframe->pc);
727 #endif
728
729                         if (rv == KERN_SUCCESS) {
730                                 if (!usermode) {
731                                         return (trapframe->pc);
732                                 }
733                                 goto out;
734                         }
735         nogo:
736                         if (!usermode) {
737                                 if (td->td_pcb->pcb_onfault != NULL) {
738                                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
739                                         td->td_pcb->pcb_onfault = NULL;
740                                         return (pc);
741                                 }
742                                 goto err;
743                         }
744                         addr = trapframe->pc;
745
746                         msg = "BAD_PAGE_FAULT";
747                         log_bad_page_fault(msg, trapframe, type);
748
749                         break;
750                 }
751
752         case T_ADDR_ERR_LD + T_USER:    /* misaligned or kseg access */
753         case T_ADDR_ERR_ST + T_USER:    /* misaligned or kseg access */
754                 if (trapframe->badvaddr < 0 ||
755                     trapframe->badvaddr >= VM_MAXUSER_ADDRESS) {
756                         msg = "ADDRESS_SPACE_ERR";
757                 } else if (allow_unaligned_acc) {
758                         int mode;
759
760                         if (type == (T_ADDR_ERR_LD + T_USER))
761                                 mode = VM_PROT_READ;
762                         else
763                                 mode = VM_PROT_WRITE;
764
765                         access_type = emulate_unaligned_access(trapframe, mode);
766                         if (access_type != 0)
767                                 goto out;
768                         msg = "ALIGNMENT_FIX_ERR";
769                 } else {
770                         msg = "ADDRESS_ERR";
771                 }
772
773                 /* FALL THROUGH */
774
775         case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */
776         case T_BUS_ERR_LD_ST + T_USER:  /* BERR asserted to cpu */
777                 ucode = 0;      /* XXX should be VM_PROT_something */
778                 i = SIGBUS;
779                 addr = trapframe->pc;
780                 if (!msg)
781                         msg = "BUS_ERR";
782                 log_bad_page_fault(msg, trapframe, type);
783                 break;
784
785         case T_SYSCALL + T_USER:
786                 {
787                         td->td_sa.trapframe = trapframe;
788                         syscallenter(td);
789
790 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
791                         if (trp == trapdebug)
792                                 trapdebug[TRAPSIZE - 1].code = td->td_sa.code;
793                         else
794                                 trp[-1].code = td->td_sa.code;
795 #endif
796                         trapdebug_enter(td->td_frame, -td->td_sa.code);
797
798                         /*
799                          * The sync'ing of I & D caches for SYS_ptrace() is
800                          * done by procfs_domem() through procfs_rwmem()
801                          * instead of being done here under a special check
802                          * for SYS_ptrace().
803                          */
804                         syscallret(td);
805                         return (trapframe->pc);
806                 }
807
808 #if defined(KDTRACE_HOOKS) || defined(DDB)
809         case T_BREAK:
810 #ifdef KDTRACE_HOOKS
811                 if (!usermode && dtrace_invop_jump_addr != 0) {
812                         dtrace_invop_jump_addr(trapframe);
813                         return (trapframe->pc);
814                 }
815 #endif
816 #ifdef DDB
817                 kdb_trap(type, 0, trapframe);
818                 return (trapframe->pc);
819 #endif
820 #endif
821
822         case T_BREAK + T_USER:
823                 {
824                         intptr_t va;
825                         uint32_t instr;
826
827                         i = SIGTRAP;
828                         ucode = TRAP_BRKPT;
829                         addr = trapframe->pc;
830
831                         /* compute address of break instruction */
832                         va = trapframe->pc;
833                         if (DELAYBRANCH(trapframe->cause))
834                                 va += sizeof(int);
835
836                         if (td->td_md.md_ss_addr != va)
837                                 break;
838
839                         /* read break instruction */
840                         instr = fuword32((caddr_t)va);
841
842                         if (instr != MIPS_BREAK_SSTEP)
843                                 break;
844
845                         CTR3(KTR_PTRACE,
846                             "trap: tid %d, single step at %#lx: %#08x",
847                             td->td_tid, va, instr);
848                         PROC_LOCK(p);
849                         _PHOLD(p);
850                         error = ptrace_clear_single_step(td);
851                         _PRELE(p);
852                         PROC_UNLOCK(p);
853                         if (error == 0)
854                                 ucode = TRAP_TRACE;
855                         break;
856                 }
857
858         case T_IWATCH + T_USER:
859         case T_DWATCH + T_USER:
860                 {
861                         intptr_t va;
862
863                         /* compute address of trapped instruction */
864                         va = trapframe->pc;
865                         if (DELAYBRANCH(trapframe->cause))
866                                 va += sizeof(int);
867                         printf("watch exception @ %p\n", (void *)va);
868                         i = SIGTRAP;
869                         ucode = TRAP_BRKPT;
870                         addr = va;
871                         break;
872                 }
873
874         case T_TRAP + T_USER:
875                 {
876                         intptr_t va;
877                         struct trapframe *locr0 = td->td_frame;
878
879                         /* compute address of trap instruction */
880                         va = trapframe->pc;
881                         if (DELAYBRANCH(trapframe->cause))
882                                 va += sizeof(int);
883
884                         if (DELAYBRANCH(trapframe->cause)) {    /* Check BD bit */
885                                 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
886                                     0);
887                         } else {
888                                 locr0->pc += sizeof(int);
889                         }
890                         addr = va;
891                         i = SIGEMT;     /* Stuff it with something for now */
892                         break;
893                 }
894
895         case T_RES_INST + T_USER:
896                 {
897                         InstFmt inst;
898                         inst = *(InstFmt *)(intptr_t)trapframe->pc;
899                         switch (inst.RType.op) {
900                         case OP_SPECIAL3:
901                                 switch (inst.RType.func) {
902                                 case OP_RDHWR:
903                                         /* Register 29 used for TLS */
904                                         if (inst.RType.rd == 29) {
905                                                 frame_regs = &(trapframe->zero);
906                                                 frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls;
907                                                 frame_regs[inst.RType.rt] += td->td_md.md_tls_tcb_offset;
908                                                 trapframe->pc += sizeof(int);
909                                                 goto out;
910                                         }
911                                 break;
912                                 }
913                         break;
914                         }
915
916                         log_illegal_instruction("RES_INST", trapframe);
917                         i = SIGILL;
918                         addr = trapframe->pc;
919                 }
920                 break;
921         case T_C2E:
922         case T_C2E + T_USER:
923                 goto err;
924                 break;
925         case T_COP_UNUSABLE:
926 #ifdef  CPU_CNMIPS
927                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
928                 /* Handle only COP2 exception */
929                 if (cop != 2)
930                         goto err;
931
932                 addr = trapframe->pc;
933                 /* save userland cop2 context if it has been touched */
934                 if ((td->td_md.md_flags & MDTD_COP2USED) &&
935                     (td->td_md.md_cop2owner == COP2_OWNER_USERLAND)) {
936                         if (td->td_md.md_ucop2)
937                                 octeon_cop2_save(td->td_md.md_ucop2);
938                         else
939                                 panic("COP2 was used in user mode but md_ucop2 is NULL");
940                 }
941
942                 if (td->td_md.md_cop2 == NULL) {
943                         td->td_md.md_cop2 = octeon_cop2_alloc_ctx();
944                         if (td->td_md.md_cop2 == NULL)
945                                 panic("Failed to allocate COP2 context");
946                         memset(td->td_md.md_cop2, 0, sizeof(*td->td_md.md_cop2));
947                 }
948
949                 octeon_cop2_restore(td->td_md.md_cop2);
950                 
951                 /* Make userland re-request its context */
952                 td->td_frame->sr &= ~MIPS_SR_COP_2_BIT;
953                 td->td_md.md_flags |= MDTD_COP2USED;
954                 td->td_md.md_cop2owner = COP2_OWNER_KERNEL;
955                 /* Enable COP2, it will be disabled in cpu_switch */
956                 mips_wr_status(mips_rd_status() | MIPS_SR_COP_2_BIT);
957                 return (trapframe->pc);
958 #else
959                 goto err;
960                 break;
961 #endif
962
963         case T_COP_UNUSABLE + T_USER:
964                 cop = (trapframe->cause & MIPS_CR_COP_ERR) >> MIPS_CR_COP_ERR_SHIFT;
965                 if (cop == 1) {
966                         /* FP (COP1) instruction */
967                         if (cpuinfo.fpu_id == 0) {
968                                 log_illegal_instruction("COP1_UNUSABLE",
969                                     trapframe);
970                                 i = SIGILL;
971                                 break;
972                         }
973                         addr = trapframe->pc;
974                         MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
975                         PCPU_SET(fpcurthread, td);
976 #if defined(__mips_n32) || defined(__mips_n64)
977                         td->td_frame->sr |= MIPS_SR_COP_1_BIT | MIPS_SR_FR;
978 #else
979                         td->td_frame->sr |= MIPS_SR_COP_1_BIT;
980 #endif
981                         td->td_md.md_flags |= MDTD_FPUSED;
982                         goto out;
983                 }
984 #ifdef  CPU_CNMIPS
985                 else  if (cop == 2) {
986                         addr = trapframe->pc;
987                         if ((td->td_md.md_flags & MDTD_COP2USED) &&
988                             (td->td_md.md_cop2owner == COP2_OWNER_KERNEL)) {
989                                 if (td->td_md.md_cop2)
990                                         octeon_cop2_save(td->td_md.md_cop2);
991                                 else
992                                         panic("COP2 was used in kernel mode but md_cop2 is NULL");
993                         }
994
995                         if (td->td_md.md_ucop2 == NULL) {
996                                 td->td_md.md_ucop2 = octeon_cop2_alloc_ctx();
997                                 if (td->td_md.md_ucop2 == NULL)
998                                         panic("Failed to allocate userland COP2 context");
999                                 memset(td->td_md.md_ucop2, 0, sizeof(*td->td_md.md_ucop2));
1000                         }
1001
1002                         octeon_cop2_restore(td->td_md.md_ucop2);
1003
1004                         td->td_frame->sr |= MIPS_SR_COP_2_BIT;
1005                         td->td_md.md_flags |= MDTD_COP2USED;
1006                         td->td_md.md_cop2owner = COP2_OWNER_USERLAND;
1007                         goto out;
1008                 }
1009 #endif
1010                 else {
1011                         log_illegal_instruction("COPn_UNUSABLE", trapframe);
1012                         i = SIGILL;     /* only FPU instructions allowed */
1013                         break;
1014                 }
1015
1016         case T_FPE:
1017 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1018                 trapDump("fpintr");
1019 #else
1020                 printf("FPU Trap: PC %#jx CR %x SR %x\n",
1021                     (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr);
1022                 goto err;
1023 #endif
1024
1025         case T_FPE + T_USER:
1026                 if (!emulate_fp) {
1027                         i = SIGFPE;
1028                         addr = trapframe->pc;
1029                         break;
1030                 }
1031                 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc);
1032                 goto out;
1033
1034         case T_OVFLOW + T_USER:
1035                 i = SIGFPE;
1036                 addr = trapframe->pc;
1037                 break;
1038
1039         case T_ADDR_ERR_LD:     /* misaligned access */
1040         case T_ADDR_ERR_ST:     /* misaligned access */
1041 #ifdef TRAP_DEBUG
1042                 if (trap_debug) {
1043                         printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type,
1044                             (intmax_t)trapframe->badvaddr);
1045                 }
1046 #endif
1047                 /* Only allow emulation on a user address */
1048                 if (allow_unaligned_acc &&
1049                     ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) {
1050                         int mode;
1051
1052                         if (type == T_ADDR_ERR_LD)
1053                                 mode = VM_PROT_READ;
1054                         else
1055                                 mode = VM_PROT_WRITE;
1056
1057                         access_type = emulate_unaligned_access(trapframe, mode);
1058                         if (access_type != 0)
1059                                 return (trapframe->pc);
1060                 }
1061                 /* FALLTHROUGH */
1062
1063         case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
1064                 if (td->td_pcb->pcb_onfault != NULL) {
1065                         pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault;
1066                         td->td_pcb->pcb_onfault = NULL;
1067                         return (pc);
1068                 }
1069
1070                 /* FALLTHROUGH */
1071
1072         default:
1073 err:
1074
1075 #if !defined(SMP) && defined(DEBUG)
1076                 trapDump("trap");
1077 #endif
1078 #ifdef SMP
1079                 printf("cpu:%d-", PCPU_GET(cpuid));
1080 #endif
1081                 printf("Trap cause = %d (%s - ", type,
1082                     trap_type[type & (~T_USER)]);
1083
1084                 if (type & T_USER)
1085                         printf("user mode)\n");
1086                 else
1087                         printf("kernel mode)\n");
1088
1089 #ifdef TRAP_DEBUG
1090                 if (trap_debug)
1091                         printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n",
1092                                (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra,
1093                                (intmax_t)trapframe->sr);
1094 #endif
1095
1096 #ifdef KDB
1097                 if (debugger_on_trap) {
1098                         kdb_why = KDB_WHY_TRAP;
1099                         kdb_trap(type, 0, trapframe);
1100                         kdb_why = KDB_WHY_UNSET;
1101                 }
1102 #endif
1103                 panic("trap");
1104         }
1105         td->td_frame->pc = trapframe->pc;
1106         td->td_frame->cause = trapframe->cause;
1107         td->td_frame->badvaddr = trapframe->badvaddr;
1108         ksiginfo_init_trap(&ksi);
1109         ksi.ksi_signo = i;
1110         ksi.ksi_code = ucode;
1111         ksi.ksi_addr = (void *)addr;
1112         ksi.ksi_trapno = type;
1113         trapsignal(td, &ksi);
1114 out:
1115
1116         /*
1117          * Note: we should only get here if returning to user mode.
1118          */
1119         userret(td, trapframe);
1120         return (trapframe->pc);
1121 }
1122
1123 #if !defined(SMP) && (defined(DDB) || defined(DEBUG))
1124 void
1125 trapDump(char *msg)
1126 {
1127         register_t s;
1128         int i;
1129
1130         s = intr_disable();
1131         printf("trapDump(%s)\n", msg);
1132         for (i = 0; i < TRAPSIZE; i++) {
1133                 if (trp == trapdebug) {
1134                         trp = &trapdebug[TRAPSIZE - 1];
1135                 } else {
1136                         trp--;
1137                 }
1138
1139                 if (trp->cause == 0)
1140                         break;
1141
1142                 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n",
1143                     trap_type[(trp->cause & MIPS_CR_EXC_CODE) >> 
1144                         MIPS_CR_EXC_CODE_SHIFT],
1145                     (intmax_t)trp->vadr, (intmax_t)trp->pc,
1146                     (intmax_t)trp->cause, (intmax_t)trp->status);
1147
1148                 printf("   RA %jx SP %jx code %d\n", (intmax_t)trp->ra,
1149                     (intmax_t)trp->sp, (int)trp->code);
1150         }
1151         intr_restore(s);
1152 }
1153 #endif
1154
1155
1156 /*
1157  * Return the resulting PC as if the branch was executed.
1158  */
1159 uintptr_t
1160 MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR,
1161     uintptr_t instptr)
1162 {
1163         InstFmt inst;
1164         register_t *regsPtr = (register_t *) framePtr;
1165         uintptr_t retAddr = 0;
1166         int condition;
1167
1168 #define GetBranchDest(InstPtr, inst) \
1169         (InstPtr + 4 + ((short)inst.IType.imm << 2))
1170
1171
1172         if (instptr) {
1173                 if (instptr < MIPS_KSEG0_START)
1174                         inst.word = fuword32((void *)instptr);
1175                 else
1176                         inst = *(InstFmt *) instptr;
1177         } else {
1178                 if ((vm_offset_t)instPC < MIPS_KSEG0_START)
1179                         inst.word = fuword32((void *)instPC);
1180                 else
1181                         inst = *(InstFmt *) instPC;
1182         }
1183
1184         switch ((int)inst.JType.op) {
1185         case OP_SPECIAL:
1186                 switch ((int)inst.RType.func) {
1187                 case OP_JR:
1188                 case OP_JALR:
1189                         retAddr = regsPtr[inst.RType.rs];
1190                         break;
1191
1192                 default:
1193                         retAddr = instPC + 4;
1194                         break;
1195                 }
1196                 break;
1197
1198         case OP_BCOND:
1199                 switch ((int)inst.IType.rt) {
1200                 case OP_BLTZ:
1201                 case OP_BLTZL:
1202                 case OP_BLTZAL:
1203                 case OP_BLTZALL:
1204                         if ((int)(regsPtr[inst.RType.rs]) < 0)
1205                                 retAddr = GetBranchDest(instPC, inst);
1206                         else
1207                                 retAddr = instPC + 8;
1208                         break;
1209
1210                 case OP_BGEZ:
1211                 case OP_BGEZL:
1212                 case OP_BGEZAL:
1213                 case OP_BGEZALL:
1214                         if ((int)(regsPtr[inst.RType.rs]) >= 0)
1215                                 retAddr = GetBranchDest(instPC, inst);
1216                         else
1217                                 retAddr = instPC + 8;
1218                         break;
1219
1220                 case OP_TGEI:
1221                 case OP_TGEIU:
1222                 case OP_TLTI:
1223                 case OP_TLTIU:
1224                 case OP_TEQI:
1225                 case OP_TNEI:
1226                         retAddr = instPC + 4;   /* Like syscall... */
1227                         break;
1228
1229                 default:
1230                         panic("MipsEmulateBranch: Bad branch cond");
1231                 }
1232                 break;
1233
1234         case OP_J:
1235         case OP_JAL:
1236                 retAddr = (inst.JType.target << 2) |
1237                     ((unsigned)(instPC + 4) & 0xF0000000);
1238                 break;
1239
1240         case OP_BEQ:
1241         case OP_BEQL:
1242                 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1243                         retAddr = GetBranchDest(instPC, inst);
1244                 else
1245                         retAddr = instPC + 8;
1246                 break;
1247
1248         case OP_BNE:
1249         case OP_BNEL:
1250                 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1251                         retAddr = GetBranchDest(instPC, inst);
1252                 else
1253                         retAddr = instPC + 8;
1254                 break;
1255
1256         case OP_BLEZ:
1257         case OP_BLEZL:
1258                 if ((int)(regsPtr[inst.RType.rs]) <= 0)
1259                         retAddr = GetBranchDest(instPC, inst);
1260                 else
1261                         retAddr = instPC + 8;
1262                 break;
1263
1264         case OP_BGTZ:
1265         case OP_BGTZL:
1266                 if ((int)(regsPtr[inst.RType.rs]) > 0)
1267                         retAddr = GetBranchDest(instPC, inst);
1268                 else
1269                         retAddr = instPC + 8;
1270                 break;
1271
1272         case OP_COP1:
1273                 switch (inst.RType.rs) {
1274                 case OP_BCx:
1275                 case OP_BCy:
1276                         if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1277                                 condition = fpcCSR & MIPS_FPU_COND_BIT;
1278                         else
1279                                 condition = !(fpcCSR & MIPS_FPU_COND_BIT);
1280                         if (condition)
1281                                 retAddr = GetBranchDest(instPC, inst);
1282                         else
1283                                 retAddr = instPC + 8;
1284                         break;
1285
1286                 default:
1287                         retAddr = instPC + 4;
1288                 }
1289                 break;
1290
1291         default:
1292                 retAddr = instPC + 4;
1293         }
1294         return (retAddr);
1295 }
1296
1297 static void
1298 log_frame_dump(struct trapframe *frame)
1299 {
1300         log(LOG_ERR, "Trapframe Register Dump:\n");
1301         log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1302             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1303
1304         log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1305             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1306
1307 #if defined(__mips_n32) || defined(__mips_n64)
1308         log(LOG_ERR, "\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta6: %#jx\n",
1309             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1310
1311         log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1312             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1313 #else
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
1317         log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1318             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1319 #endif
1320         log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1321             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1322
1323         log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1324             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1325
1326         log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1327             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1328
1329         log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1330             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1331
1332         log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1333             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1334
1335         log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n",
1336             (intmax_t)frame->cause, (intmax_t)frame->pc);
1337 }
1338
1339 #ifdef TRAP_DEBUG
1340 static void
1341 trap_frame_dump(struct trapframe *frame)
1342 {
1343         printf("Trapframe Register Dump:\n");
1344         printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n",
1345             (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1);
1346
1347         printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n",
1348             (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3);
1349 #if defined(__mips_n32) || defined(__mips_n64)
1350         printf("\ta4: %#jx\ta5: %#jx\ta6: %#jx\ta7: %#jx\n",
1351             (intmax_t)frame->a4, (intmax_t)frame->a5, (intmax_t)frame->a6, (intmax_t)frame->a7);
1352
1353         printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n",
1354             (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3);
1355 #else
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
1359         printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n",
1360             (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7);
1361 #endif
1362         printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n",
1363             (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1);
1364
1365         printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n",
1366             (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5);
1367
1368         printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n",
1369             (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1);
1370
1371         printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n",
1372             (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra);
1373
1374         printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n",
1375             (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr);
1376
1377         printf("\tcause: %#jx\tpc: %#jx\n",
1378             (intmax_t)frame->cause, (intmax_t)frame->pc);
1379 }
1380
1381 #endif
1382
1383
1384 static void
1385 get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp)
1386 {
1387         pt_entry_t *ptep;
1388         pd_entry_t *pdep;
1389         struct proc *p = curproc;
1390
1391         pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)]));
1392         if (*pdep)
1393                 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va);
1394         else
1395                 ptep = (pt_entry_t *)0;
1396
1397         *pdepp = pdep;
1398         *ptepp = ptep;
1399 }
1400
1401 static void
1402 log_illegal_instruction(const char *msg, struct trapframe *frame)
1403 {
1404         pt_entry_t *ptep;
1405         pd_entry_t *pdep;
1406         unsigned int *addr;
1407         struct thread *td;
1408         struct proc *p;
1409         register_t pc;
1410
1411         td = curthread;
1412         p = td->td_proc;
1413
1414 #ifdef SMP
1415         printf("cpuid = %d\n", PCPU_GET(cpuid));
1416 #endif
1417         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1418         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx ra %#jx\n",
1419             msg, p->p_pid, (long)td->td_tid, p->p_comm,
1420             p->p_ucred ? p->p_ucred->cr_uid : -1,
1421             (intmax_t)pc,
1422             (intmax_t)frame->ra);
1423
1424         /* log registers in trap frame */
1425         log_frame_dump(frame);
1426
1427         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1428
1429         /*
1430          * Dump a few words around faulting instruction, if the addres is
1431          * valid.
1432          */
1433         if (!(pc & 3) &&
1434             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1435                 /* dump page table entry for faulting instruction */
1436                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1437                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1438
1439                 addr = (unsigned int *)(intptr_t)pc;
1440                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1441                     addr);
1442                 log(LOG_ERR, "%08x %08x %08x %08x\n",
1443                     addr[0], addr[1], addr[2], addr[3]);
1444         } else {
1445                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1446                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1447         }
1448 }
1449
1450 static void
1451 log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type)
1452 {
1453         pt_entry_t *ptep;
1454         pd_entry_t *pdep;
1455         unsigned int *addr;
1456         struct thread *td;
1457         struct proc *p;
1458         char *read_or_write;
1459         register_t pc;
1460
1461         trap_type &= ~T_USER;
1462
1463         td = curthread;
1464         p = td->td_proc;
1465
1466 #ifdef SMP
1467         printf("cpuid = %d\n", PCPU_GET(cpuid));
1468 #endif
1469         switch (trap_type) {
1470         case T_TLB_MOD:
1471         case T_TLB_ST_MISS:
1472         case T_ADDR_ERR_ST:
1473                 read_or_write = "write";
1474                 break;
1475         case T_TLB_LD_MISS:
1476         case T_ADDR_ERR_LD:
1477         case T_BUS_ERR_IFETCH:
1478                 read_or_write = "read";
1479                 break;
1480         default:
1481                 read_or_write = "unknown";
1482         }
1483
1484         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1485         log(LOG_ERR, "%s: pid %d tid %ld (%s), uid %d: pc %#jx got a %s fault "
1486             "(type %#x) at %#jx\n",
1487             msg, p->p_pid, (long)td->td_tid, p->p_comm,
1488             p->p_ucred ? p->p_ucred->cr_uid : -1,
1489             (intmax_t)pc,
1490             read_or_write,
1491             trap_type,
1492             (intmax_t)frame->badvaddr);
1493
1494         /* log registers in trap frame */
1495         log_frame_dump(frame);
1496
1497         get_mapping_info((vm_offset_t)pc, &pdep, &ptep);
1498
1499         /*
1500          * Dump a few words around faulting instruction, if the addres is
1501          * valid.
1502          */
1503         if (!(pc & 3) && (pc != frame->badvaddr) &&
1504             (trap_type != T_BUS_ERR_IFETCH) &&
1505             useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) {
1506                 /* dump page table entry for faulting instruction */
1507                 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#jx\n",
1508                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1509
1510                 addr = (unsigned int *)(intptr_t)pc;
1511                 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n",
1512                     addr);
1513                 log(LOG_ERR, "%08x %08x %08x %08x\n",
1514                     addr[0], addr[1], addr[2], addr[3]);
1515         } else {
1516                 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#jx\n",
1517                     (intmax_t)pc, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1518         }
1519
1520         get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep);
1521         log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#jx\n",
1522             (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, (uintmax_t)(ptep ? *ptep : 0));
1523 }
1524
1525
1526 /*
1527  * Unaligned load/store emulation
1528  */
1529 static int
1530 mips_unaligned_load_store(struct trapframe *frame, int mode, register_t addr, register_t pc)
1531 {
1532         register_t *reg = (register_t *) frame;
1533         u_int32_t inst = *((u_int32_t *)(intptr_t)pc);
1534         register_t value_msb, value;
1535         unsigned size;
1536
1537         /*
1538          * ADDR_ERR faults have higher priority than TLB
1539          * Miss faults.  Therefore, it is necessary to
1540          * verify that the faulting address is a valid
1541          * virtual address within the process' address space
1542          * before trying to emulate the unaligned access.
1543          */
1544         switch (MIPS_INST_OPCODE(inst)) {
1545         case OP_LHU: case OP_LH:
1546         case OP_SH:
1547                 size = 2;
1548                 break;
1549         case OP_LWU: case OP_LW:
1550         case OP_SW:
1551                 size = 4;
1552                 break;
1553         case OP_LD:
1554         case OP_SD:
1555                 size = 8;
1556                 break;
1557         default:
1558                 printf("%s: unhandled opcode in address error: %#x\n", __func__, MIPS_INST_OPCODE(inst));
1559                 return (0);
1560         }
1561
1562         if (!useracc((void *)rounddown2((vm_offset_t)addr, size), size * 2, mode))
1563                 return (0);
1564
1565         /*
1566          * XXX
1567          * Handle LL/SC LLD/SCD.
1568          */
1569         switch (MIPS_INST_OPCODE(inst)) {
1570         case OP_LHU:
1571                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1572                 lbu_macro(value_msb, addr);
1573                 addr += 1;
1574                 lbu_macro(value, addr);
1575                 value |= value_msb << 8;
1576                 reg[MIPS_INST_RT(inst)] = value;
1577                 return (MIPS_LHU_ACCESS);
1578
1579         case OP_LH:
1580                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1581                 lb_macro(value_msb, addr);
1582                 addr += 1;
1583                 lbu_macro(value, addr);
1584                 value |= value_msb << 8;
1585                 reg[MIPS_INST_RT(inst)] = value;
1586                 return (MIPS_LH_ACCESS);
1587
1588         case OP_LWU:
1589                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1590                 lwl_macro(value, addr);
1591                 addr += 3;
1592                 lwr_macro(value, addr);
1593                 value &= 0xffffffff;
1594                 reg[MIPS_INST_RT(inst)] = value;
1595                 return (MIPS_LWU_ACCESS);
1596
1597         case OP_LW:
1598                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1599                 lwl_macro(value, addr);
1600                 addr += 3;
1601                 lwr_macro(value, addr);
1602                 reg[MIPS_INST_RT(inst)] = value;
1603                 return (MIPS_LW_ACCESS);
1604
1605 #if defined(__mips_n32) || defined(__mips_n64)
1606         case OP_LD:
1607                 KASSERT(mode == VM_PROT_READ, ("access mode must be read for load instruction."));
1608                 ldl_macro(value, addr);
1609                 addr += 7;
1610                 ldr_macro(value, addr);
1611                 reg[MIPS_INST_RT(inst)] = value;
1612                 return (MIPS_LD_ACCESS);
1613 #endif
1614
1615         case OP_SH:
1616                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1617                 value = reg[MIPS_INST_RT(inst)];
1618                 value_msb = value >> 8;
1619                 sb_macro(value_msb, addr);
1620                 addr += 1;
1621                 sb_macro(value, addr);
1622                 return (MIPS_SH_ACCESS);
1623
1624         case OP_SW:
1625                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1626                 value = reg[MIPS_INST_RT(inst)];
1627                 swl_macro(value, addr);
1628                 addr += 3;
1629                 swr_macro(value, addr);
1630                 return (MIPS_SW_ACCESS);
1631
1632 #if defined(__mips_n32) || defined(__mips_n64)
1633         case OP_SD:
1634                 KASSERT(mode == VM_PROT_WRITE, ("access mode must be write for store instruction."));
1635                 value = reg[MIPS_INST_RT(inst)];
1636                 sdl_macro(value, addr);
1637                 addr += 7;
1638                 sdr_macro(value, addr);
1639                 return (MIPS_SD_ACCESS);
1640 #endif
1641         }
1642         panic("%s: should not be reached.", __func__);
1643 }
1644
1645
1646 /*
1647  * XXX TODO: SMP?
1648  */
1649 static struct timeval unaligned_lasterr;
1650 static int unaligned_curerr;
1651
1652 static int unaligned_pps_log_limit = 4;
1653
1654 SYSCTL_INT(_machdep, OID_AUTO, unaligned_log_pps_limit, CTLFLAG_RWTUN,
1655     &unaligned_pps_log_limit, 0,
1656     "limit number of userland unaligned log messages per second");
1657
1658 static int
1659 emulate_unaligned_access(struct trapframe *frame, int mode)
1660 {
1661         register_t pc;
1662         int access_type = 0;
1663         struct thread *td = curthread;
1664         struct proc *p = curproc;
1665
1666         pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0);
1667
1668         /*
1669          * Fall through if it's instruction fetch exception
1670          */
1671         if (!((pc & 3) || (pc == frame->badvaddr))) {
1672
1673                 /*
1674                  * Handle unaligned load and store
1675                  */
1676
1677                 /*
1678                  * Return access type if the instruction was emulated.
1679                  * Otherwise restore pc and fall through.
1680                  */
1681                 access_type = mips_unaligned_load_store(frame,
1682                     mode, frame->badvaddr, pc);
1683
1684                 if (access_type) {
1685                         if (DELAYBRANCH(frame->cause))
1686                                 frame->pc = MipsEmulateBranch(frame, frame->pc,
1687                                     0, 0);
1688                         else
1689                                 frame->pc += 4;
1690
1691                         if (ppsratecheck(&unaligned_lasterr,
1692                             &unaligned_curerr, unaligned_pps_log_limit)) {
1693                                 /* XXX TODO: keep global/tid/pid counters? */
1694                                 log(LOG_INFO,
1695                                     "Unaligned %s: pid=%ld (%s), tid=%ld, "
1696                                     "pc=%#jx, badvaddr=%#jx\n",
1697                                     access_name[access_type - 1],
1698                                     (long) p->p_pid,
1699                                     p->p_comm,
1700                                     (long) td->td_tid,
1701                                     (intmax_t)pc,
1702                                     (intmax_t)frame->badvaddr);
1703                         }
1704                 }
1705         }
1706         return access_type;
1707 }