trap.c revision 210038
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 210038 2010-07-14 00:41:22Z imp $"); 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 & MIPS3_CR_EXC_CODE) >> MIPS_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 & MIPS_SR_INT_IE) { 306 set_intr_mask(~(trapframe->sr & MIPS_SR_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 pid = mips_rd_entryhi() & TLBHI_ASID_MASK; 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 (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) { 382 pmap_update_page(kernel_pmap, 383 trapframe->badvaddr, *pte); 384 PMAP_UNLOCK(kernel_pmap); 385 return (trapframe->pc); 386 } 387#else 388 if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) 389 panic("trap: ktlbmod: invalid pte"); 390#endif 391 if (pte_test(pte, PTE_RO)) { 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_set(pte, PTE_D); 398 pmap_update_page(kernel_pmap, trapframe->badvaddr, *pte); 399 pa = TLBLO_PTE_TO_PA(*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 (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) { 421 pmap_update_page(pmap, trapframe->badvaddr, *pte); 422 PMAP_UNLOCK(pmap); 423 goto out; 424 } 425#else 426 if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) 427 panic("trap: utlbmod: invalid pte"); 428#endif 429 430 if (pte_test(pte, PTE_RO)) { 431 /* write to read only page */ 432 ftype = VM_PROT_WRITE; 433 PMAP_UNLOCK(pmap); 434 goto dofault; 435 } 436 pte_set(pte, PTE_D); 437 pmap_update_page(pmap, trapframe->badvaddr, *pte); 438 pa = TLBLO_PTE_TO_PA(*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#if defined(__mips_n32) || defined(__mips_n64) 629 case SYS___syscall: 630 /* 631 * Quads fit in a single register in 632 * new ABIs. 633 * 634 * XXX o64? 635 */ 636#endif 637 case SYS_syscall: 638 /* 639 * Code is first argument, followed by 640 * actual args. 641 */ 642 code = locr0->a0; 643 args[0] = locr0->a1; 644 args[1] = locr0->a2; 645 args[2] = locr0->a3; 646 nsaved = 3; 647#if defined(__mips_n32) || defined(__mips_n64) 648 args[3] = locr0->t4; 649 args[4] = locr0->t5; 650 args[5] = locr0->t6; 651 args[6] = locr0->t7; 652 nsaved += 4; 653#endif 654 break; 655 656#if defined(__mips_o32) 657 case SYS___syscall: 658 /* 659 * Like syscall, but code is a quad, so as 660 * to maintain quad alignment for the rest 661 * of the arguments. 662 */ 663 if (_QUAD_LOWWORD == 0) { 664 code = locr0->a0; 665 } else { 666 code = locr0->a1; 667 } 668 args[0] = locr0->a2; 669 args[1] = locr0->a3; 670 nsaved = 2; 671 break; 672#endif 673 674 default: 675 args[0] = locr0->a0; 676 args[1] = locr0->a1; 677 args[2] = locr0->a2; 678 args[3] = locr0->a3; 679 nsaved = 4; 680#if defined (__mips_n32) || defined(__mips_n64) 681 args[4] = locr0->t4; 682 args[5] = locr0->t5; 683 args[6] = locr0->t6; 684 args[7] = locr0->t7; 685 nsaved += 4; 686#endif 687 } 688#ifdef TRAP_DEBUG 689 printf("SYSCALL #%d pid:%u\n", code, p->p_pid); 690#endif 691 692 if (p->p_sysent->sv_mask) 693 code &= p->p_sysent->sv_mask; 694 695 if (code >= p->p_sysent->sv_size) 696 callp = &p->p_sysent->sv_table[0]; 697 else 698 callp = &p->p_sysent->sv_table[code]; 699 700 nargs = callp->sy_narg; 701 702 if (nargs > nsaved) { 703#if defined(__mips_n32) || defined(__mips_n64) 704 /* 705 * XXX 706 * Is this right for new ABIs? I think the 4 there 707 * should be 8, size there are 8 registers to skip, 708 * not 4, but I'm not certain. 709 */ 710 printf("SYSCALL #%u pid:%u, nargs > nsaved.\n", code, p->p_pid); 711#endif 712 i = copyin((caddr_t)(intptr_t)(locr0->sp + 713 4 * sizeof(register_t)), (caddr_t)&args[nsaved], 714 (u_int)(nargs - nsaved) * sizeof(register_t)); 715 if (i) { 716 locr0->v0 = i; 717 locr0->a3 = 1; 718#ifdef KTRACE 719 if (KTRPOINT(td, KTR_SYSCALL)) 720 ktrsyscall(code, nargs, args); 721#endif 722 goto done; 723 } 724 } 725#ifdef TRAP_DEBUG 726 for (i = 0; i < nargs; i++) { 727 printf("args[%d] = %#jx\n", i, (intmax_t)args[i]); 728 } 729#endif 730#ifdef SYSCALL_TRACING 731 printf("%s(", syscallnames[code]); 732 for (i = 0; i < nargs; i++) { 733 printf("%s%#jx", i == 0 ? "" : ", ", (intmax_t)args[i]); 734 } 735 printf(")\n"); 736#endif 737#ifdef KTRACE 738 if (KTRPOINT(td, KTR_SYSCALL)) 739 ktrsyscall(code, nargs, args); 740#endif 741 td->td_retval[0] = 0; 742 td->td_retval[1] = locr0->v1; 743 744#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 745 if (trp == trapdebug) 746 trapdebug[TRAPSIZE - 1].code = code; 747 else 748 trp[-1].code = code; 749#endif 750 STOPEVENT(p, S_SCE, nargs); 751 752 PTRACESTOP_SC(p, td, S_PT_SCE); 753 i = (*callp->sy_call) (td, args); 754#if 0 755 /* 756 * Reinitialize proc pointer `p' as it may be 757 * different if this is a child returning from fork 758 * syscall. 759 */ 760 td = curthread; 761 locr0 = td->td_frame; 762#endif 763 trapdebug_enter(locr0, -code); 764 cpu_set_syscall_retval(td, i); 765 766 /* 767 * The sync'ing of I & D caches for SYS_ptrace() is 768 * done by procfs_domem() through procfs_rwmem() 769 * instead of being done here under a special check 770 * for SYS_ptrace(). 771 */ 772 done: 773 /* 774 * Check for misbehavior. 775 */ 776 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", 777 (code >= 0 && code < SYS_MAXSYSCALL) ? 778 syscallnames[code] : "???"); 779 KASSERT(td->td_critnest == 0, 780 ("System call %s returning in a critical section", 781 (code >= 0 && code < SYS_MAXSYSCALL) ? 782 syscallnames[code] : "???")); 783 KASSERT(td->td_locks == 0, 784 ("System call %s returning with %d locks held", 785 (code >= 0 && code < SYS_MAXSYSCALL) ? 786 syscallnames[code] : "???", 787 td->td_locks)); 788 userret(td, trapframe); 789#ifdef KTRACE 790 if (KTRPOINT(td, KTR_SYSRET)) 791 ktrsysret(code, i, td->td_retval[0]); 792#endif 793 /* 794 * This works because errno is findable through the 795 * register set. If we ever support an emulation 796 * where this is not the case, this code will need 797 * to be revisited. 798 */ 799 STOPEVENT(p, S_SCX, code); 800 801 PTRACESTOP_SC(p, td, S_PT_SCX); 802 803 mtx_assert(&Giant, MA_NOTOWNED); 804 return (trapframe->pc); 805 } 806 807#ifdef DDB 808 case T_BREAK: 809 kdb_trap(type, 0, trapframe); 810 return (trapframe->pc); 811#endif 812 813 case T_BREAK + T_USER: 814 { 815 intptr_t va; 816 uint32_t instr; 817 818 /* compute address of break instruction */ 819 va = trapframe->pc; 820 if (DELAYBRANCH(trapframe->cause)) 821 va += sizeof(int); 822 823 /* read break instruction */ 824 instr = fuword((caddr_t)va); 825#if 0 826 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", 827 p->p_comm, p->p_pid, instr, trapframe->pc, 828 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ 829#endif 830 if (td->td_md.md_ss_addr != va || 831 instr != MIPS_BREAK_SSTEP) { 832 i = SIGTRAP; 833 addr = trapframe->pc; 834 break; 835 } 836 /* 837 * The restoration of the original instruction and 838 * the clearing of the berakpoint will be done later 839 * by the call to ptrace_clear_single_step() in 840 * issignal() when SIGTRAP is processed. 841 */ 842 addr = trapframe->pc; 843 i = SIGTRAP; 844 break; 845 } 846 847 case T_IWATCH + T_USER: 848 case T_DWATCH + T_USER: 849 { 850 intptr_t va; 851 852 /* compute address of trapped instruction */ 853 va = trapframe->pc; 854 if (DELAYBRANCH(trapframe->cause)) 855 va += sizeof(int); 856 printf("watch exception @ %p\n", (void *)va); 857 i = SIGTRAP; 858 addr = va; 859 break; 860 } 861 862 case T_TRAP + T_USER: 863 { 864 intptr_t va; 865 uint32_t instr; 866 struct trapframe *locr0 = td->td_frame; 867 868 /* compute address of trap instruction */ 869 va = trapframe->pc; 870 if (DELAYBRANCH(trapframe->cause)) 871 va += sizeof(int); 872 /* read break instruction */ 873 instr = fuword((caddr_t)va); 874 875 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */ 876 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 877 0); 878 } else { 879 locr0->pc += sizeof(int); 880 } 881 addr = va; 882 i = SIGEMT; /* Stuff it with something for now */ 883 break; 884 } 885 886 case T_RES_INST + T_USER: 887 log_illegal_instruction("RES_INST", trapframe); 888 i = SIGILL; 889 addr = trapframe->pc; 890 break; 891 case T_C2E: 892 case T_C2E + T_USER: 893 goto err; 894 break; 895 case T_COP_UNUSABLE: 896 goto err; 897 break; 898 case T_COP_UNUSABLE + T_USER: 899#if !defined(CPU_HAVEFPU) 900 /* FP (COP1) instruction */ 901 if ((trapframe->cause & MIPS_CR_COP_ERR) == 0x10000000) { 902 log_illegal_instruction("COP1_UNUSABLE", trapframe); 903 i = SIGILL; 904 break; 905 } 906#endif 907 if ((trapframe->cause & MIPS_CR_COP_ERR) != 0x10000000) { 908 log_illegal_instruction("COPn_UNUSABLE", trapframe); 909 i = SIGILL; /* only FPU instructions allowed */ 910 break; 911 } 912 addr = trapframe->pc; 913 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame); 914 PCPU_SET(fpcurthread, td); 915 td->td_frame->sr |= MIPS_SR_COP_1_BIT; 916 td->td_md.md_flags |= MDTD_FPUSED; 917 goto out; 918 919 case T_FPE: 920#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 921 trapDump("fpintr"); 922#else 923 printf("FPU Trap: PC %#jx CR %x SR %x\n", 924 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr); 925 goto err; 926#endif 927 928 case T_FPE + T_USER: 929 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc); 930 goto out; 931 932 case T_OVFLOW + T_USER: 933 i = SIGFPE; 934 addr = trapframe->pc; 935 break; 936 937 case T_ADDR_ERR_LD: /* misaligned access */ 938 case T_ADDR_ERR_ST: /* misaligned access */ 939#ifdef TRAP_DEBUG 940 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type, 941 (intmax_t)trapframe->badvaddr); 942#endif 943 /* Only allow emulation on a user address */ 944 if (allow_unaligned_acc && 945 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) { 946 int mode; 947 948 if (type == T_ADDR_ERR_LD) 949 mode = VM_PROT_READ; 950 else 951 mode = VM_PROT_WRITE; 952 953 /* 954 * ADDR_ERR faults have higher priority than TLB 955 * Miss faults. Therefore, it is necessary to 956 * verify that the faulting address is a valid 957 * virtual address within the process' address space 958 * before trying to emulate the unaligned access. 959 */ 960 if (useracc((caddr_t) 961 (((vm_offset_t)trapframe->badvaddr) & 962 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { 963 access_type = emulate_unaligned_access( 964 trapframe); 965 if (access_type != 0) { 966 return (trapframe->pc); 967 } 968 } 969 } 970 /* FALLTHROUGH */ 971 972 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 973 if (td->td_pcb->pcb_onfault != NULL) { 974 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 975 td->td_pcb->pcb_onfault = NULL; 976 return (pc); 977 } 978 979 /* FALLTHROUGH */ 980 981 default: 982err: 983 984#if !defined(SMP) && defined(DEBUG) 985 stacktrace(!usermode ? trapframe : td->td_frame); 986 trapDump("trap"); 987#endif 988#ifdef SMP 989 printf("cpu:%d-", PCPU_GET(cpuid)); 990#endif 991 printf("Trap cause = %d (%s - ", type, 992 trap_type[type & (~T_USER)]); 993 994 if (type & T_USER) 995 printf("user mode)\n"); 996 else 997 printf("kernel mode)\n"); 998 999#ifdef TRAP_DEBUG 1000 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n", 1001 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra, 1002 (intmax_t)trapframe->sr); 1003#endif 1004 1005#ifdef KDB 1006 if (debugger_on_panic || kdb_active) { 1007 kdb_trap(type, 0, trapframe); 1008 } 1009#endif 1010 panic("trap"); 1011 } 1012 td->td_frame->pc = trapframe->pc; 1013 td->td_frame->cause = trapframe->cause; 1014 td->td_frame->badvaddr = trapframe->badvaddr; 1015 ksiginfo_init_trap(&ksi); 1016 ksi.ksi_signo = i; 1017 ksi.ksi_code = ucode; 1018 ksi.ksi_addr = (void *)addr; 1019 ksi.ksi_trapno = type; 1020 trapsignal(td, &ksi); 1021out: 1022 1023 /* 1024 * Note: we should only get here if returning to user mode. 1025 */ 1026 userret(td, trapframe); 1027 mtx_assert(&Giant, MA_NOTOWNED); 1028 return (trapframe->pc); 1029} 1030 1031#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 1032void 1033trapDump(char *msg) 1034{ 1035 register_t s; 1036 int i; 1037 1038 s = intr_disable(); 1039 printf("trapDump(%s)\n", msg); 1040 for (i = 0; i < TRAPSIZE; i++) { 1041 if (trp == trapdebug) { 1042 trp = &trapdebug[TRAPSIZE - 1]; 1043 } else { 1044 trp--; 1045 } 1046 1047 if (trp->cause == 0) 1048 break; 1049 1050 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n", 1051 trap_type[(trp->cause & MIPS3_CR_EXC_CODE) >> 1052 MIPS_CR_EXC_CODE_SHIFT], 1053 (intmax_t)trp->vadr, (intmax_t)trp->pc, 1054 (intmax_t)trp->cause, (intmax_t)trp->status); 1055 1056 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra, 1057 (intmax_t)trp->sp, (int)trp->code); 1058 } 1059 intr_restore(s); 1060} 1061#endif 1062 1063 1064/* 1065 * Return the resulting PC as if the branch was executed. 1066 */ 1067uintptr_t 1068MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR, 1069 uintptr_t instptr) 1070{ 1071 InstFmt inst; 1072 register_t *regsPtr = (register_t *) framePtr; 1073 uintptr_t retAddr = 0; 1074 int condition; 1075 1076#define GetBranchDest(InstPtr, inst) \ 1077 (InstPtr + 4 + ((short)inst.IType.imm << 2)) 1078 1079 1080 if (instptr) { 1081 if (instptr < MIPS_KSEG0_START) 1082 inst.word = fuword32((void *)instptr); 1083 else 1084 inst = *(InstFmt *) instptr; 1085 } else { 1086 if ((vm_offset_t)instPC < MIPS_KSEG0_START) 1087 inst.word = fuword32((void *)instPC); 1088 else 1089 inst = *(InstFmt *) instPC; 1090 } 1091 1092 switch ((int)inst.JType.op) { 1093 case OP_SPECIAL: 1094 switch ((int)inst.RType.func) { 1095 case OP_JR: 1096 case OP_JALR: 1097 retAddr = regsPtr[inst.RType.rs]; 1098 break; 1099 1100 default: 1101 retAddr = instPC + 4; 1102 break; 1103 } 1104 break; 1105 1106 case OP_BCOND: 1107 switch ((int)inst.IType.rt) { 1108 case OP_BLTZ: 1109 case OP_BLTZL: 1110 case OP_BLTZAL: 1111 case OP_BLTZALL: 1112 if ((int)(regsPtr[inst.RType.rs]) < 0) 1113 retAddr = GetBranchDest(instPC, inst); 1114 else 1115 retAddr = instPC + 8; 1116 break; 1117 1118 case OP_BGEZ: 1119 case OP_BGEZL: 1120 case OP_BGEZAL: 1121 case OP_BGEZALL: 1122 if ((int)(regsPtr[inst.RType.rs]) >= 0) 1123 retAddr = GetBranchDest(instPC, inst); 1124 else 1125 retAddr = instPC + 8; 1126 break; 1127 1128 case OP_TGEI: 1129 case OP_TGEIU: 1130 case OP_TLTI: 1131 case OP_TLTIU: 1132 case OP_TEQI: 1133 case OP_TNEI: 1134 retAddr = instPC + 4; /* Like syscall... */ 1135 break; 1136 1137 default: 1138 panic("MipsEmulateBranch: Bad branch cond"); 1139 } 1140 break; 1141 1142 case OP_J: 1143 case OP_JAL: 1144 retAddr = (inst.JType.target << 2) | 1145 ((unsigned)(instPC + 4) & 0xF0000000); 1146 break; 1147 1148 case OP_BEQ: 1149 case OP_BEQL: 1150 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) 1151 retAddr = GetBranchDest(instPC, inst); 1152 else 1153 retAddr = instPC + 8; 1154 break; 1155 1156 case OP_BNE: 1157 case OP_BNEL: 1158 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) 1159 retAddr = GetBranchDest(instPC, inst); 1160 else 1161 retAddr = instPC + 8; 1162 break; 1163 1164 case OP_BLEZ: 1165 case OP_BLEZL: 1166 if ((int)(regsPtr[inst.RType.rs]) <= 0) 1167 retAddr = GetBranchDest(instPC, inst); 1168 else 1169 retAddr = instPC + 8; 1170 break; 1171 1172 case OP_BGTZ: 1173 case OP_BGTZL: 1174 if ((int)(regsPtr[inst.RType.rs]) > 0) 1175 retAddr = GetBranchDest(instPC, inst); 1176 else 1177 retAddr = instPC + 8; 1178 break; 1179 1180 case OP_COP1: 1181 switch (inst.RType.rs) { 1182 case OP_BCx: 1183 case OP_BCy: 1184 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) 1185 condition = fpcCSR & MIPS_FPU_COND_BIT; 1186 else 1187 condition = !(fpcCSR & MIPS_FPU_COND_BIT); 1188 if (condition) 1189 retAddr = GetBranchDest(instPC, inst); 1190 else 1191 retAddr = instPC + 8; 1192 break; 1193 1194 default: 1195 retAddr = instPC + 4; 1196 } 1197 break; 1198 1199 default: 1200 retAddr = instPC + 4; 1201 } 1202 return (retAddr); 1203} 1204 1205 1206#if defined(DDB) || defined(DEBUG) 1207/* 1208 * Print a stack backtrace. 1209 */ 1210void 1211stacktrace(struct trapframe *regs) 1212{ 1213 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf); 1214} 1215#endif 1216 1217static void 1218log_frame_dump(struct trapframe *frame) 1219{ 1220 log(LOG_ERR, "Trapframe Register Dump:\n"); 1221 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1222 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1223 1224 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1225 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1226 1227 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1228 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1229 1230 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1231 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1232 1233 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1234 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1235 1236 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1237 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1238 1239 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1240 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1241 1242 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1243 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1244 1245 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1246 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1247 1248#ifdef IC_REG 1249 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1250 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1251#else 1252 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n", 1253 (intmax_t)frame->cause, (intmax_t)frame->pc); 1254#endif 1255} 1256 1257#ifdef TRAP_DEBUG 1258static void 1259trap_frame_dump(struct trapframe *frame) 1260{ 1261 printf("Trapframe Register Dump:\n"); 1262 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1263 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1264 1265 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1266 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1267 1268 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1269 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1270 1271 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1272 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1273 1274 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1275 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1276 1277 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1278 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1279 1280 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1281 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1282 1283 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1284 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1285 1286 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1287 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1288 1289#ifdef IC_REG 1290 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1291 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1292#else 1293 printf("\tcause: %#jx\tpc: %#jx\n", 1294 (intmax_t)frame->cause, (intmax_t)frame->pc); 1295#endif 1296} 1297 1298#endif 1299 1300 1301static void 1302get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) 1303{ 1304 pt_entry_t *ptep; 1305 pd_entry_t *pdep; 1306 struct proc *p = curproc; 1307 1308 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)])); 1309 if (*pdep) 1310 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); 1311 else 1312 ptep = (pt_entry_t *)0; 1313 1314 *pdepp = pdep; 1315 *ptepp = ptep; 1316} 1317 1318static void 1319log_illegal_instruction(const char *msg, struct trapframe *frame) 1320{ 1321 pt_entry_t *ptep; 1322 pd_entry_t *pdep; 1323 unsigned int *addr; 1324 struct proc *p = curproc; 1325 register_t pc; 1326 1327#ifdef SMP 1328 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1329#endif 1330 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1331 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n", 1332 msg, p->p_pid, p->p_comm, 1333 p->p_ucred ? p->p_ucred->cr_uid : -1, 1334 (intmax_t)pc, 1335 (intmax_t)frame->ra); 1336 1337 /* log registers in trap frame */ 1338 log_frame_dump(frame); 1339 1340 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1341 1342 /* 1343 * Dump a few words around faulting instruction, if the addres is 1344 * valid. 1345 */ 1346 if (!(pc & 3) && 1347 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1348 /* dump page table entry for faulting instruction */ 1349 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n", 1350 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1351 1352 addr = (unsigned int *)(intptr_t)pc; 1353 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1354 addr); 1355 log(LOG_ERR, "%08x %08x %08x %08x\n", 1356 addr[0], addr[1], addr[2], addr[3]); 1357 } else { 1358 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n", 1359 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1360 } 1361} 1362 1363static void 1364log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type) 1365{ 1366 pt_entry_t *ptep; 1367 pd_entry_t *pdep; 1368 unsigned int *addr; 1369 struct proc *p = curproc; 1370 char *read_or_write; 1371 register_t pc; 1372 1373 trap_type &= ~T_USER; 1374 1375#ifdef SMP 1376 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1377#endif 1378 switch (trap_type) { 1379 case T_TLB_ST_MISS: 1380 case T_ADDR_ERR_ST: 1381 read_or_write = "write"; 1382 break; 1383 case T_TLB_LD_MISS: 1384 case T_ADDR_ERR_LD: 1385 case T_BUS_ERR_IFETCH: 1386 read_or_write = "read"; 1387 break; 1388 default: 1389 read_or_write = ""; 1390 } 1391 1392 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1393 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n", 1394 msg, p->p_pid, p->p_comm, 1395 p->p_ucred ? p->p_ucred->cr_uid : -1, 1396 (intmax_t)pc, 1397 read_or_write, 1398 (intmax_t)frame->badvaddr); 1399 1400 /* log registers in trap frame */ 1401 log_frame_dump(frame); 1402 1403 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1404 1405 /* 1406 * Dump a few words around faulting instruction, if the addres is 1407 * valid. 1408 */ 1409 if (!(pc & 3) && (pc != frame->badvaddr) && 1410 (trap_type != T_BUS_ERR_IFETCH) && 1411 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1412 /* dump page table entry for faulting instruction */ 1413 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n", 1414 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1415 1416 addr = (unsigned int *)(intptr_t)pc; 1417 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1418 addr); 1419 log(LOG_ERR, "%08x %08x %08x %08x\n", 1420 addr[0], addr[1], addr[2], addr[3]); 1421 } else { 1422 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n", 1423 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1424 } 1425 1426 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep); 1427 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#x\n", 1428 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1429} 1430 1431 1432/* 1433 * Unaligned load/store emulation 1434 */ 1435static int 1436mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc) 1437{ 1438 register_t *reg = (register_t *) frame; 1439 u_int32_t inst = *((u_int32_t *)(intptr_t)pc); 1440 u_int32_t value_msb, value; 1441 int access_type = 0; 1442 1443 switch (MIPS_INST_OPCODE(inst)) { 1444 case OP_LHU: 1445 lbu_macro(value_msb, addr); 1446 addr += 1; 1447 lbu_macro(value, addr); 1448 value |= value_msb << 8; 1449 reg[MIPS_INST_RT(inst)] = value; 1450 access_type = MIPS_LHU_ACCESS; 1451 break; 1452 1453 case OP_LH: 1454 lb_macro(value_msb, addr); 1455 addr += 1; 1456 lbu_macro(value, addr); 1457 value |= value_msb << 8; 1458 reg[MIPS_INST_RT(inst)] = value; 1459 access_type = MIPS_LH_ACCESS; 1460 break; 1461 1462 case OP_LWU: 1463 lwl_macro(value, addr); 1464 addr += 3; 1465 lwr_macro(value, addr); 1466 value &= 0xffffffff; 1467 reg[MIPS_INST_RT(inst)] = value; 1468 access_type = MIPS_LWU_ACCESS; 1469 break; 1470 1471 case OP_LW: 1472 lwl_macro(value, addr); 1473 addr += 3; 1474 lwr_macro(value, addr); 1475 reg[MIPS_INST_RT(inst)] = value; 1476 access_type = MIPS_LW_ACCESS; 1477 break; 1478 1479 case OP_SH: 1480 value = reg[MIPS_INST_RT(inst)]; 1481 value_msb = value >> 8; 1482 sb_macro(value_msb, addr); 1483 addr += 1; 1484 sb_macro(value, addr); 1485 access_type = MIPS_SH_ACCESS; 1486 break; 1487 1488 case OP_SW: 1489 value = reg[MIPS_INST_RT(inst)]; 1490 swl_macro(value, addr); 1491 addr += 3; 1492 swr_macro(value, addr); 1493 access_type = MIPS_SW_ACCESS; 1494 break; 1495 1496 default: 1497 break; 1498 } 1499 1500 return access_type; 1501} 1502 1503 1504static int 1505emulate_unaligned_access(struct trapframe *frame) 1506{ 1507 register_t pc; 1508 int access_type = 0; 1509 1510 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1511 1512 /* 1513 * Fall through if it's instruction fetch exception 1514 */ 1515 if (!((pc & 3) || (pc == frame->badvaddr))) { 1516 1517 /* 1518 * Handle unaligned load and store 1519 */ 1520 1521 /* 1522 * Return access type if the instruction was emulated. 1523 * Otherwise restore pc and fall through. 1524 */ 1525 access_type = mips_unaligned_load_store(frame, 1526 frame->badvaddr, pc); 1527 1528 if (access_type) { 1529 if (DELAYBRANCH(frame->cause)) 1530 frame->pc = MipsEmulateBranch(frame, frame->pc, 1531 0, 0); 1532 else 1533 frame->pc += 4; 1534 1535 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n", 1536 access_name[access_type - 1], (intmax_t)pc, 1537 (intmax_t)frame->badvaddr); 1538 } 1539 } 1540 return access_type; 1541} 1542