trap.c revision 209500
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 209500 2010-06-24 08:08:43Z jchandra $"); 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 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 || instr != BREAK_SSTEP) { 831 i = SIGTRAP; 832 addr = trapframe->pc; 833 break; 834 } 835 /* 836 * The restoration of the original instruction and 837 * the clearing of the berakpoint will be done later 838 * by the call to ptrace_clear_single_step() in 839 * issignal() when SIGTRAP is processed. 840 */ 841 addr = trapframe->pc; 842 i = SIGTRAP; 843 break; 844 } 845 846 case T_IWATCH + T_USER: 847 case T_DWATCH + T_USER: 848 { 849 intptr_t va; 850 851 /* compute address of trapped instruction */ 852 va = trapframe->pc; 853 if (DELAYBRANCH(trapframe->cause)) 854 va += sizeof(int); 855 printf("watch exception @ %p\n", (void *)va); 856 i = SIGTRAP; 857 addr = va; 858 break; 859 } 860 861 case T_TRAP + T_USER: 862 { 863 intptr_t va; 864 uint32_t instr; 865 struct trapframe *locr0 = td->td_frame; 866 867 /* compute address of trap instruction */ 868 va = trapframe->pc; 869 if (DELAYBRANCH(trapframe->cause)) 870 va += sizeof(int); 871 /* read break instruction */ 872 instr = fuword((caddr_t)va); 873 874 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */ 875 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 876 0); 877 } else { 878 locr0->pc += sizeof(int); 879 } 880 addr = va; 881 i = SIGEMT; /* Stuff it with something for now */ 882 break; 883 } 884 885 case T_RES_INST + T_USER: 886 log_illegal_instruction("RES_INST", trapframe); 887 i = SIGILL; 888 addr = trapframe->pc; 889 break; 890 case T_C2E: 891 case T_C2E + T_USER: 892 goto err; 893 break; 894 case T_COP_UNUSABLE: 895 goto err; 896 break; 897 case T_COP_UNUSABLE + T_USER: 898#if !defined(CPU_HAVEFPU) 899 /* FP (COP1) instruction */ 900 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) { 901 log_illegal_instruction("COP1_UNUSABLE", trapframe); 902 i = SIGILL; 903 break; 904 } 905#endif 906 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) { 907 log_illegal_instruction("COPn_UNUSABLE", trapframe); 908 i = SIGILL; /* only FPU instructions allowed */ 909 break; 910 } 911 addr = trapframe->pc; 912 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame); 913 PCPU_SET(fpcurthread, td); 914 td->td_frame->sr |= SR_COP_1_BIT; 915 td->td_md.md_flags |= MDTD_FPUSED; 916 goto out; 917 918 case T_FPE: 919#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 920 trapDump("fpintr"); 921#else 922 printf("FPU Trap: PC %#jx CR %x SR %x\n", 923 (intmax_t)trapframe->pc, (unsigned)trapframe->cause, (unsigned)trapframe->sr); 924 goto err; 925#endif 926 927 case T_FPE + T_USER: 928 MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc); 929 goto out; 930 931 case T_OVFLOW + T_USER: 932 i = SIGFPE; 933 addr = trapframe->pc; 934 break; 935 936 case T_ADDR_ERR_LD: /* misaligned access */ 937 case T_ADDR_ERR_ST: /* misaligned access */ 938#ifdef TRAP_DEBUG 939 printf("+++ ADDR_ERR: type = %d, badvaddr = %#jx\n", type, 940 (intmax_t)trapframe->badvaddr); 941#endif 942 /* Only allow emulation on a user address */ 943 if (allow_unaligned_acc && 944 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) { 945 int mode; 946 947 if (type == T_ADDR_ERR_LD) 948 mode = VM_PROT_READ; 949 else 950 mode = VM_PROT_WRITE; 951 952 /* 953 * ADDR_ERR faults have higher priority than TLB 954 * Miss faults. Therefore, it is necessary to 955 * verify that the faulting address is a valid 956 * virtual address within the process' address space 957 * before trying to emulate the unaligned access. 958 */ 959 if (useracc((caddr_t) 960 (((vm_offset_t)trapframe->badvaddr) & 961 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { 962 access_type = emulate_unaligned_access( 963 trapframe); 964 if (access_type != 0) { 965 return (trapframe->pc); 966 } 967 } 968 } 969 /* FALLTHROUGH */ 970 971 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 972 if (td->td_pcb->pcb_onfault != NULL) { 973 pc = (register_t)(intptr_t)td->td_pcb->pcb_onfault; 974 td->td_pcb->pcb_onfault = NULL; 975 return (pc); 976 } 977 978 /* FALLTHROUGH */ 979 980 default: 981err: 982 983#if !defined(SMP) && defined(DEBUG) 984 stacktrace(!usermode ? trapframe : td->td_frame); 985 trapDump("trap"); 986#endif 987#ifdef SMP 988 printf("cpu:%d-", PCPU_GET(cpuid)); 989#endif 990 printf("Trap cause = %d (%s - ", type, 991 trap_type[type & (~T_USER)]); 992 993 if (type & T_USER) 994 printf("user mode)\n"); 995 else 996 printf("kernel mode)\n"); 997 998#ifdef TRAP_DEBUG 999 printf("badvaddr = %#jx, pc = %#jx, ra = %#jx, sr = %#jxx\n", 1000 (intmax_t)trapframe->badvaddr, (intmax_t)trapframe->pc, (intmax_t)trapframe->ra, 1001 (intmax_t)trapframe->sr); 1002#endif 1003 1004#ifdef KDB 1005 if (debugger_on_panic || kdb_active) { 1006 kdb_trap(type, 0, trapframe); 1007 } 1008#endif 1009 panic("trap"); 1010 } 1011 td->td_frame->pc = trapframe->pc; 1012 td->td_frame->cause = trapframe->cause; 1013 td->td_frame->badvaddr = trapframe->badvaddr; 1014 ksiginfo_init_trap(&ksi); 1015 ksi.ksi_signo = i; 1016 ksi.ksi_code = ucode; 1017 ksi.ksi_addr = (void *)addr; 1018 ksi.ksi_trapno = type; 1019 trapsignal(td, &ksi); 1020out: 1021 1022 /* 1023 * Note: we should only get here if returning to user mode. 1024 */ 1025 userret(td, trapframe); 1026 mtx_assert(&Giant, MA_NOTOWNED); 1027 return (trapframe->pc); 1028} 1029 1030#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 1031void 1032trapDump(char *msg) 1033{ 1034 register_t s; 1035 int i; 1036 1037 s = intr_disable(); 1038 printf("trapDump(%s)\n", msg); 1039 for (i = 0; i < TRAPSIZE; i++) { 1040 if (trp == trapdebug) { 1041 trp = &trapdebug[TRAPSIZE - 1]; 1042 } else { 1043 trp--; 1044 } 1045 1046 if (trp->cause == 0) 1047 break; 1048 1049 printf("%s: ADR %jx PC %jx CR %jx SR %jx\n", 1050 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT], 1051 (intmax_t)trp->vadr, (intmax_t)trp->pc, (intmax_t)trp->cause, (intmax_t)trp->status); 1052 1053 printf(" RA %jx SP %jx code %d\n", (intmax_t)trp->ra, (intmax_t)trp->sp, (int)trp->code); 1054 } 1055 intr_restore(s); 1056} 1057#endif 1058 1059 1060/* 1061 * Return the resulting PC as if the branch was executed. 1062 */ 1063uintptr_t 1064MipsEmulateBranch(struct trapframe *framePtr, uintptr_t instPC, int fpcCSR, 1065 uintptr_t instptr) 1066{ 1067 InstFmt inst; 1068 register_t *regsPtr = (register_t *) framePtr; 1069 uintptr_t retAddr = 0; 1070 int condition; 1071 1072#define GetBranchDest(InstPtr, inst) \ 1073 (InstPtr + 4 + ((short)inst.IType.imm << 2)) 1074 1075 1076 if (instptr) { 1077 if (instptr < MIPS_KSEG0_START) 1078 inst.word = fuword32((void *)instptr); 1079 else 1080 inst = *(InstFmt *) instptr; 1081 } else { 1082 if ((vm_offset_t)instPC < MIPS_KSEG0_START) 1083 inst.word = fuword32((void *)instPC); 1084 else 1085 inst = *(InstFmt *) instPC; 1086 } 1087 1088 switch ((int)inst.JType.op) { 1089 case OP_SPECIAL: 1090 switch ((int)inst.RType.func) { 1091 case OP_JR: 1092 case OP_JALR: 1093 retAddr = regsPtr[inst.RType.rs]; 1094 break; 1095 1096 default: 1097 retAddr = instPC + 4; 1098 break; 1099 } 1100 break; 1101 1102 case OP_BCOND: 1103 switch ((int)inst.IType.rt) { 1104 case OP_BLTZ: 1105 case OP_BLTZL: 1106 case OP_BLTZAL: 1107 case OP_BLTZALL: 1108 if ((int)(regsPtr[inst.RType.rs]) < 0) 1109 retAddr = GetBranchDest(instPC, inst); 1110 else 1111 retAddr = instPC + 8; 1112 break; 1113 1114 case OP_BGEZ: 1115 case OP_BGEZL: 1116 case OP_BGEZAL: 1117 case OP_BGEZALL: 1118 if ((int)(regsPtr[inst.RType.rs]) >= 0) 1119 retAddr = GetBranchDest(instPC, inst); 1120 else 1121 retAddr = instPC + 8; 1122 break; 1123 1124 case OP_TGEI: 1125 case OP_TGEIU: 1126 case OP_TLTI: 1127 case OP_TLTIU: 1128 case OP_TEQI: 1129 case OP_TNEI: 1130 retAddr = instPC + 4; /* Like syscall... */ 1131 break; 1132 1133 default: 1134 panic("MipsEmulateBranch: Bad branch cond"); 1135 } 1136 break; 1137 1138 case OP_J: 1139 case OP_JAL: 1140 retAddr = (inst.JType.target << 2) | 1141 ((unsigned)(instPC + 4) & 0xF0000000); 1142 break; 1143 1144 case OP_BEQ: 1145 case OP_BEQL: 1146 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) 1147 retAddr = GetBranchDest(instPC, inst); 1148 else 1149 retAddr = instPC + 8; 1150 break; 1151 1152 case OP_BNE: 1153 case OP_BNEL: 1154 if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt]) 1155 retAddr = GetBranchDest(instPC, inst); 1156 else 1157 retAddr = instPC + 8; 1158 break; 1159 1160 case OP_BLEZ: 1161 case OP_BLEZL: 1162 if ((int)(regsPtr[inst.RType.rs]) <= 0) 1163 retAddr = GetBranchDest(instPC, inst); 1164 else 1165 retAddr = instPC + 8; 1166 break; 1167 1168 case OP_BGTZ: 1169 case OP_BGTZL: 1170 if ((int)(regsPtr[inst.RType.rs]) > 0) 1171 retAddr = GetBranchDest(instPC, inst); 1172 else 1173 retAddr = instPC + 8; 1174 break; 1175 1176 case OP_COP1: 1177 switch (inst.RType.rs) { 1178 case OP_BCx: 1179 case OP_BCy: 1180 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) 1181 condition = fpcCSR & FPC_COND_BIT; 1182 else 1183 condition = !(fpcCSR & FPC_COND_BIT); 1184 if (condition) 1185 retAddr = GetBranchDest(instPC, inst); 1186 else 1187 retAddr = instPC + 8; 1188 break; 1189 1190 default: 1191 retAddr = instPC + 4; 1192 } 1193 break; 1194 1195 default: 1196 retAddr = instPC + 4; 1197 } 1198 return (retAddr); 1199} 1200 1201 1202#if defined(DDB) || defined(DEBUG) 1203/* 1204 * Print a stack backtrace. 1205 */ 1206void 1207stacktrace(struct trapframe *regs) 1208{ 1209 stacktrace_subr(regs->pc, regs->sp, regs->ra, printf); 1210} 1211#endif 1212 1213static void 1214log_frame_dump(struct trapframe *frame) 1215{ 1216 log(LOG_ERR, "Trapframe Register Dump:\n"); 1217 log(LOG_ERR, "\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1218 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1219 1220 log(LOG_ERR, "\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1221 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1222 1223 log(LOG_ERR, "\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1224 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1225 1226 log(LOG_ERR, "\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1227 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1228 1229 log(LOG_ERR, "\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1230 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1231 1232 log(LOG_ERR, "\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1233 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1234 1235 log(LOG_ERR, "\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1236 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1237 1238 log(LOG_ERR, "\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1239 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1240 1241 log(LOG_ERR, "\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1242 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1243 1244#ifdef IC_REG 1245 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1246 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1247#else 1248 log(LOG_ERR, "\tcause: %#jx\tpc: %#jx\n", 1249 (intmax_t)frame->cause, (intmax_t)frame->pc); 1250#endif 1251} 1252 1253#ifdef TRAP_DEBUG 1254static void 1255trap_frame_dump(struct trapframe *frame) 1256{ 1257 printf("Trapframe Register Dump:\n"); 1258 printf("\tzero: %#jx\tat: %#jx\tv0: %#jx\tv1: %#jx\n", 1259 (intmax_t)0, (intmax_t)frame->ast, (intmax_t)frame->v0, (intmax_t)frame->v1); 1260 1261 printf("\ta0: %#jx\ta1: %#jx\ta2: %#jx\ta3: %#jx\n", 1262 (intmax_t)frame->a0, (intmax_t)frame->a1, (intmax_t)frame->a2, (intmax_t)frame->a3); 1263 1264 printf("\tt0: %#jx\tt1: %#jx\tt2: %#jx\tt3: %#jx\n", 1265 (intmax_t)frame->t0, (intmax_t)frame->t1, (intmax_t)frame->t2, (intmax_t)frame->t3); 1266 1267 printf("\tt4: %#jx\tt5: %#jx\tt6: %#jx\tt7: %#jx\n", 1268 (intmax_t)frame->t4, (intmax_t)frame->t5, (intmax_t)frame->t6, (intmax_t)frame->t7); 1269 1270 printf("\tt8: %#jx\tt9: %#jx\ts0: %#jx\ts1: %#jx\n", 1271 (intmax_t)frame->t8, (intmax_t)frame->t9, (intmax_t)frame->s0, (intmax_t)frame->s1); 1272 1273 printf("\ts2: %#jx\ts3: %#jx\ts4: %#jx\ts5: %#jx\n", 1274 (intmax_t)frame->s2, (intmax_t)frame->s3, (intmax_t)frame->s4, (intmax_t)frame->s5); 1275 1276 printf("\ts6: %#jx\ts7: %#jx\tk0: %#jx\tk1: %#jx\n", 1277 (intmax_t)frame->s6, (intmax_t)frame->s7, (intmax_t)frame->k0, (intmax_t)frame->k1); 1278 1279 printf("\tgp: %#jx\tsp: %#jx\ts8: %#jx\tra: %#jx\n", 1280 (intmax_t)frame->gp, (intmax_t)frame->sp, (intmax_t)frame->s8, (intmax_t)frame->ra); 1281 1282 printf("\tsr: %#jx\tmullo: %#jx\tmulhi: %#jx\tbadvaddr: %#jx\n", 1283 (intmax_t)frame->sr, (intmax_t)frame->mullo, (intmax_t)frame->mulhi, (intmax_t)frame->badvaddr); 1284 1285#ifdef IC_REG 1286 printf("\tcause: %#jx\tpc: %#jx\tic: %#jx\n", 1287 (intmax_t)frame->cause, (intmax_t)frame->pc, (intmax_t)frame->ic); 1288#else 1289 printf("\tcause: %#jx\tpc: %#jx\n", 1290 (intmax_t)frame->cause, (intmax_t)frame->pc); 1291#endif 1292} 1293 1294#endif 1295 1296 1297static void 1298get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) 1299{ 1300 pt_entry_t *ptep; 1301 pd_entry_t *pdep; 1302 struct proc *p = curproc; 1303 1304 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)])); 1305 if (*pdep) 1306 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); 1307 else 1308 ptep = (pt_entry_t *)0; 1309 1310 *pdepp = pdep; 1311 *ptepp = ptep; 1312} 1313 1314static void 1315log_illegal_instruction(const char *msg, struct trapframe *frame) 1316{ 1317 pt_entry_t *ptep; 1318 pd_entry_t *pdep; 1319 unsigned int *addr; 1320 struct proc *p = curproc; 1321 register_t pc; 1322 1323#ifdef SMP 1324 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1325#endif 1326 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1327 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx ra %#jx\n", 1328 msg, p->p_pid, p->p_comm, 1329 p->p_ucred ? p->p_ucred->cr_uid : -1, 1330 (intmax_t)pc, 1331 (intmax_t)frame->ra); 1332 1333 /* log registers in trap frame */ 1334 log_frame_dump(frame); 1335 1336 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1337 1338 /* 1339 * Dump a few words around faulting instruction, if the addres is 1340 * valid. 1341 */ 1342 if (!(pc & 3) && 1343 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1344 /* dump page table entry for faulting instruction */ 1345 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n", 1346 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1347 1348 addr = (unsigned int *)(intptr_t)pc; 1349 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1350 addr); 1351 log(LOG_ERR, "%08x %08x %08x %08x\n", 1352 addr[0], addr[1], addr[2], addr[3]); 1353 } else { 1354 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n", 1355 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1356 } 1357} 1358 1359static void 1360log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type) 1361{ 1362 pt_entry_t *ptep; 1363 pd_entry_t *pdep; 1364 unsigned int *addr; 1365 struct proc *p = curproc; 1366 char *read_or_write; 1367 register_t pc; 1368 1369 trap_type &= ~T_USER; 1370 1371#ifdef SMP 1372 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1373#endif 1374 switch (trap_type) { 1375 case T_TLB_ST_MISS: 1376 case T_ADDR_ERR_ST: 1377 read_or_write = "write"; 1378 break; 1379 case T_TLB_LD_MISS: 1380 case T_ADDR_ERR_LD: 1381 case T_BUS_ERR_IFETCH: 1382 read_or_write = "read"; 1383 break; 1384 default: 1385 read_or_write = ""; 1386 } 1387 1388 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1389 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc %#jx got a %s fault at %#jx\n", 1390 msg, p->p_pid, p->p_comm, 1391 p->p_ucred ? p->p_ucred->cr_uid : -1, 1392 (intmax_t)pc, 1393 read_or_write, 1394 (intmax_t)frame->badvaddr); 1395 1396 /* log registers in trap frame */ 1397 log_frame_dump(frame); 1398 1399 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1400 1401 /* 1402 * Dump a few words around faulting instruction, if the addres is 1403 * valid. 1404 */ 1405 if (!(pc & 3) && (pc != frame->badvaddr) && 1406 (trap_type != T_BUS_ERR_IFETCH) && 1407 useracc((caddr_t)(intptr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1408 /* dump page table entry for faulting instruction */ 1409 log(LOG_ERR, "Page table info for pc address %#jx: pde = %p, pte = %#x\n", 1410 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1411 1412 addr = (unsigned int *)(intptr_t)pc; 1413 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1414 addr); 1415 log(LOG_ERR, "%08x %08x %08x %08x\n", 1416 addr[0], addr[1], addr[2], addr[3]); 1417 } else { 1418 log(LOG_ERR, "pc address %#jx is inaccessible, pde = %p, pte = %#x\n", 1419 (intmax_t)pc, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1420 } 1421 1422 get_mapping_info((vm_offset_t)frame->badvaddr, &pdep, &ptep); 1423 log(LOG_ERR, "Page table info for bad address %#jx: pde = %p, pte = %#x\n", 1424 (intmax_t)frame->badvaddr, (void *)(intptr_t)*pdep, ptep ? *ptep : 0); 1425} 1426 1427 1428/* 1429 * Unaligned load/store emulation 1430 */ 1431static int 1432mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc) 1433{ 1434 register_t *reg = (register_t *) frame; 1435 u_int32_t inst = *((u_int32_t *)(intptr_t)pc); 1436 u_int32_t value_msb, value; 1437 int access_type = 0; 1438 1439 switch (MIPS_INST_OPCODE(inst)) { 1440 case OP_LHU: 1441 lbu_macro(value_msb, addr); 1442 addr += 1; 1443 lbu_macro(value, addr); 1444 value |= value_msb << 8; 1445 reg[MIPS_INST_RT(inst)] = value; 1446 access_type = MIPS_LHU_ACCESS; 1447 break; 1448 1449 case OP_LH: 1450 lb_macro(value_msb, addr); 1451 addr += 1; 1452 lbu_macro(value, addr); 1453 value |= value_msb << 8; 1454 reg[MIPS_INST_RT(inst)] = value; 1455 access_type = MIPS_LH_ACCESS; 1456 break; 1457 1458 case OP_LWU: 1459 lwl_macro(value, addr); 1460 addr += 3; 1461 lwr_macro(value, addr); 1462 value &= 0xffffffff; 1463 reg[MIPS_INST_RT(inst)] = value; 1464 access_type = MIPS_LWU_ACCESS; 1465 break; 1466 1467 case OP_LW: 1468 lwl_macro(value, addr); 1469 addr += 3; 1470 lwr_macro(value, addr); 1471 reg[MIPS_INST_RT(inst)] = value; 1472 access_type = MIPS_LW_ACCESS; 1473 break; 1474 1475 case OP_SH: 1476 value = reg[MIPS_INST_RT(inst)]; 1477 value_msb = value >> 8; 1478 sb_macro(value_msb, addr); 1479 addr += 1; 1480 sb_macro(value, addr); 1481 access_type = MIPS_SH_ACCESS; 1482 break; 1483 1484 case OP_SW: 1485 value = reg[MIPS_INST_RT(inst)]; 1486 swl_macro(value, addr); 1487 addr += 3; 1488 swr_macro(value, addr); 1489 access_type = MIPS_SW_ACCESS; 1490 break; 1491 1492 default: 1493 break; 1494 } 1495 1496 return access_type; 1497} 1498 1499 1500static int 1501emulate_unaligned_access(struct trapframe *frame) 1502{ 1503 register_t pc; 1504 int access_type = 0; 1505 1506 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1507 1508 /* 1509 * Fall through if it's instruction fetch exception 1510 */ 1511 if (!((pc & 3) || (pc == frame->badvaddr))) { 1512 1513 /* 1514 * Handle unaligned load and store 1515 */ 1516 1517 /* 1518 * Return access type if the instruction was emulated. 1519 * Otherwise restore pc and fall through. 1520 */ 1521 access_type = mips_unaligned_load_store(frame, 1522 frame->badvaddr, pc); 1523 1524 if (access_type) { 1525 if (DELAYBRANCH(frame->cause)) 1526 frame->pc = MipsEmulateBranch(frame, frame->pc, 1527 0, 0); 1528 else 1529 frame->pc += 4; 1530 1531 log(LOG_INFO, "Unaligned %s: pc=%#jx, badvaddr=%#jx\n", 1532 access_name[access_type - 1], (intmax_t)pc, 1533 (intmax_t)frame->badvaddr); 1534 } 1535 } 1536 return access_type; 1537} 1538