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