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