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