trap.c revision 199135
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 199135 2009-11-10 11:43:07Z kib $"); 43 44#include "opt_ddb.h" 45#include "opt_global.h" 46 47#define NO_REG_DEFS 1 /* Prevent asm.h from including regdef.h */ 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/sysent.h> 51#include <sys/proc.h> 52#include <sys/kernel.h> 53#include <sys/signalvar.h> 54#include <sys/syscall.h> 55#include <sys/lock.h> 56#include <vm/vm.h> 57#include <vm/vm_extern.h> 58#include <vm/vm_kern.h> 59#include <vm/vm_page.h> 60#include <vm/vm_map.h> 61#include <vm/vm_param.h> 62#include <sys/vmmeter.h> 63#include <sys/ptrace.h> 64#include <sys/user.h> 65#include <sys/buf.h> 66#include <sys/vnode.h> 67#include <sys/pioctl.h> 68#include <sys/sysctl.h> 69#include <sys/syslog.h> 70#include <sys/bus.h> 71#ifdef KTRACE 72#include <sys/ktrace.h> 73#endif 74#include <net/netisr.h> 75 76#include <machine/trap.h> 77#include <machine/psl.h> 78#include <machine/cpu.h> 79#include <machine/intr.h> 80#include <machine/pte.h> 81#include <machine/pmap.h> 82#include <machine/mips_opcode.h> 83#include <machine/frame.h> 84#include <machine/regnum.h> 85#include <machine/rm7000.h> 86#include <machine/archtype.h> 87#include <machine/asm.h> 88 89#ifdef DDB 90#include <machine/db_machdep.h> 91#include <ddb/db_sym.h> 92#include <ddb/ddb.h> 93#include <sys/kdb.h> 94#endif 95 96#include <sys/cdefs.h> 97#include <sys/syslog.h> 98 99 100#ifdef TRAP_DEBUG 101int trap_debug = 1; 102 103#endif 104 105extern unsigned onfault_table[]; 106 107extern void MipsKernGenException(void); 108extern void MipsUserGenException(void); 109extern void MipsKernIntr(void); 110extern void MipsUserIntr(void); 111extern void MipsTLBInvalidException(void); 112extern void MipsKernTLBInvalidException(void); 113extern void MipsUserTLBInvalidException(void); 114extern void MipsTLBMissException(void); 115static void log_bad_page_fault(char *, struct trapframe *, int); 116static void log_frame_dump(struct trapframe *frame); 117static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **); 118 119#ifdef TRAP_DEBUG 120static void trap_frame_dump(struct trapframe *frame); 121 122#endif 123extern char edata[]; 124 125void (*machExceptionTable[]) (void)= { 126/* 127 * The kernel exception handlers. 128 */ 129 MipsKernIntr, /* external interrupt */ 130 MipsKernGenException, /* TLB modification */ 131 MipsKernTLBInvalidException, /* TLB miss (load or instr. fetch) */ 132 MipsKernTLBInvalidException, /* TLB miss (store) */ 133 MipsKernGenException, /* address error (load or I-fetch) */ 134 MipsKernGenException, /* address error (store) */ 135 MipsKernGenException, /* bus error (I-fetch) */ 136 MipsKernGenException, /* bus error (load or store) */ 137 MipsKernGenException, /* system call */ 138 MipsKernGenException, /* breakpoint */ 139 MipsKernGenException, /* reserved instruction */ 140 MipsKernGenException, /* coprocessor unusable */ 141 MipsKernGenException, /* arithmetic overflow */ 142 MipsKernGenException, /* trap exception */ 143 MipsKernGenException, /* virtual coherence exception inst */ 144 MipsKernGenException, /* floating point exception */ 145 MipsKernGenException, /* reserved */ 146 MipsKernGenException, /* reserved */ 147 MipsKernGenException, /* reserved */ 148 MipsKernGenException, /* reserved */ 149 MipsKernGenException, /* reserved */ 150 MipsKernGenException, /* reserved */ 151 MipsKernGenException, /* reserved */ 152 MipsKernGenException, /* watch exception */ 153 MipsKernGenException, /* reserved */ 154 MipsKernGenException, /* reserved */ 155 MipsKernGenException, /* reserved */ 156 MipsKernGenException, /* reserved */ 157 MipsKernGenException, /* reserved */ 158 MipsKernGenException, /* reserved */ 159 MipsKernGenException, /* reserved */ 160 MipsKernGenException, /* virtual coherence exception data */ 161/* 162 * The user exception handlers. 163 */ 164 MipsUserIntr, /* 0 */ 165 MipsUserGenException, /* 1 */ 166 MipsUserTLBInvalidException, /* 2 */ 167 MipsUserTLBInvalidException, /* 3 */ 168 MipsUserGenException, /* 4 */ 169 MipsUserGenException, /* 5 */ 170 MipsUserGenException, /* 6 */ 171 MipsUserGenException, /* 7 */ 172 MipsUserGenException, /* 8 */ 173 MipsUserGenException, /* 9 */ 174 MipsUserGenException, /* 10 */ 175 MipsUserGenException, /* 11 */ 176 MipsUserGenException, /* 12 */ 177 MipsUserGenException, /* 13 */ 178 MipsUserGenException, /* 14 */ 179 MipsUserGenException, /* 15 */ 180 MipsUserGenException, /* 16 */ 181 MipsUserGenException, /* 17 */ 182 MipsUserGenException, /* 18 */ 183 MipsUserGenException, /* 19 */ 184 MipsUserGenException, /* 20 */ 185 MipsUserGenException, /* 21 */ 186 MipsUserGenException, /* 22 */ 187 MipsUserGenException, /* 23 */ 188 MipsUserGenException, /* 24 */ 189 MipsUserGenException, /* 25 */ 190 MipsUserGenException, /* 26 */ 191 MipsUserGenException, /* 27 */ 192 MipsUserGenException, /* 28 */ 193 MipsUserGenException, /* 29 */ 194 MipsUserGenException, /* 20 */ 195 MipsUserGenException, /* 31 */ 196}; 197 198char *trap_type[] = { 199 "external interrupt", 200 "TLB modification", 201 "TLB miss (load or instr. fetch)", 202 "TLB miss (store)", 203 "address error (load or I-fetch)", 204 "address error (store)", 205 "bus error (I-fetch)", 206 "bus error (load or store)", 207 "system call", 208 "breakpoint", 209 "reserved instruction", 210 "coprocessor unusable", 211 "arithmetic overflow", 212 "trap", 213 "virtual coherency instruction", 214 "floating point", 215 "reserved 16", 216 "reserved 17", 217 "reserved 18", 218 "reserved 19", 219 "reserved 20", 220 "reserved 21", 221 "reserved 22", 222 "watch", 223 "reserved 24", 224 "reserved 25", 225 "reserved 26", 226 "reserved 27", 227 "reserved 28", 228 "reserved 29", 229 "reserved 30", 230 "virtual coherency data", 231}; 232 233#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 234struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug; 235 236#endif 237 238#if defined(DDB) || defined(DEBUG) 239void stacktrace(struct trapframe *); 240void logstacktrace(struct trapframe *); 241int kdbpeek(int *); 242 243/* extern functions printed by name in stack backtraces */ 244extern void MipsTLBMiss(void); 245extern void MipsUserSyscallException(void); 246extern char _locore[]; 247extern char _locoreEnd[]; 248 249#endif /* DDB || DEBUG */ 250 251extern void MipsSwitchFPState(struct thread *, struct trapframe *); 252extern void MipsFPTrap(u_int, u_int, u_int); 253 254u_int trap(struct trapframe *); 255u_int MipsEmulateBranch(struct trapframe *, int, int, u_int); 256 257#define KERNLAND(x) ((int)(x) < 0) 258#define DELAYBRANCH(x) ((int)(x) < 0) 259 260/* 261 * kdbpeekD(addr) - skip one word starting at 'addr', then read the second word 262 */ 263#define kdbpeekD(addr) kdbpeek(((int *)(addr)) + 1) 264int rrs_debug = 0; 265 266/* 267 * MIPS load/store access type 268 */ 269enum { 270 MIPS_LHU_ACCESS = 1, 271 MIPS_LH_ACCESS, 272 MIPS_LWU_ACCESS, 273 MIPS_LW_ACCESS, 274 MIPS_LD_ACCESS, 275 MIPS_SH_ACCESS, 276 MIPS_SW_ACCESS, 277 MIPS_SD_ACCESS 278}; 279 280char *access_name[] = { 281 "Load Halfword Unsigned", 282 "Load Halfword", 283 "Load Word Unsigned", 284 "Load Word", 285 "Load Doubleword", 286 "Store Halfword", 287 "Store Word", 288 "Store Doubleword" 289}; 290 291 292static int allow_unaligned_acc = 1; 293 294SYSCTL_INT(_vm, OID_AUTO, allow_unaligned_acc, CTLFLAG_RW, 295 &allow_unaligned_acc, 0, "Allow unaligned accesses"); 296 297static int emulate_unaligned_access(struct trapframe *frame); 298 299extern char *syscallnames[]; 300 301/* 302 * Handle an exception. 303 * Called from MipsKernGenException() or MipsUserGenException() 304 * when a processor trap occurs. 305 * In the case of a kernel trap, we return the pc where to resume if 306 * p->p_addr->u_pcb.pcb_onfault is set, otherwise, return old pc. 307 */ 308u_int 309trap(trapframe) 310 struct trapframe *trapframe; 311{ 312 int type, usermode; 313 int i = 0; 314 unsigned ucode = 0; 315 struct thread *td = curthread; 316 struct proc *p = curproc; 317 vm_prot_t ftype; 318 pt_entry_t *pte; 319 unsigned int entry; 320 pmap_t pmap; 321 int quad_syscall = 0; 322 int access_type; 323 ksiginfo_t ksi; 324 char *msg = NULL; 325 register_t addr = 0; 326 327 trapdebug_enter(trapframe, 0); 328 329 type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT; 330 if (USERMODE(trapframe->sr)) { 331 type |= T_USER; 332 usermode = 1; 333 } else { 334 usermode = 0; 335 } 336 337 /* 338 * Enable hardware interrupts if they were on before the trap. If it 339 * was off disable all so we don't accidently enable it when doing a 340 * return to userland. 341 */ 342 if (trapframe->sr & SR_INT_ENAB) { 343 set_intr_mask(~(trapframe->sr & ALL_INT_MASK)); 344 enableintr(); 345 } else { 346 disableintr(); 347 } 348 349#ifdef TRAP_DEBUG 350 if (trap_debug) { 351 static vm_offset_t last_badvaddr = 0; 352 static vm_offset_t this_badvaddr = 0; 353 static int count = 0; 354 u_int32_t pid; 355 356 printf("trap type %x (%s - ", type, 357 trap_type[type & (~T_USER)]); 358 359 if (type & T_USER) 360 printf("user mode)\n"); 361 else 362 printf("kernel mode)\n"); 363 364#ifdef SMP 365 printf("cpuid = %d\n", PCPU_GET(cpuid)); 366#endif 367 MachTLBGetPID(pid); 368 printf("badaddr = %p, pc = %p, ra = %p, sp = %p, sr = 0x%x, pid = %d, ASID = 0x%x\n", 369 trapframe->badvaddr, trapframe->pc, trapframe->ra, 370 trapframe->sp, trapframe->sr, 371 (curproc ? curproc->p_pid : -1), pid); 372 373 switch (type & ~T_USER) { 374 case T_TLB_MOD: 375 case T_TLB_LD_MISS: 376 case T_TLB_ST_MISS: 377 case T_ADDR_ERR_LD: 378 case T_ADDR_ERR_ST: 379 this_badvaddr = trapframe->badvaddr; 380 break; 381 case T_SYSCALL: 382 this_badvaddr = trapframe->ra; 383 break; 384 default: 385 this_badvaddr = trapframe->pc; 386 break; 387 } 388 if ((last_badvaddr == this_badvaddr) && 389 ((type & ~T_USER) != T_SYSCALL)) { 390 if (++count == 3) { 391 trap_frame_dump(trapframe); 392 panic("too many faults at %p\n", last_badvaddr); 393 } 394 } else { 395 last_badvaddr = this_badvaddr; 396 count = 0; 397 } 398 } 399#endif 400 switch (type) { 401 case T_MCHECK: 402#ifdef DDB 403 kdb_trap(type, 0, trapframe); 404#endif 405 panic("MCHECK\n"); 406 break; 407 case T_TLB_MOD: 408 /* check for kernel address */ 409 if (KERNLAND(trapframe->badvaddr)) { 410 vm_offset_t pa; 411 412 PMAP_LOCK(kernel_pmap); 413 if (!(pte = pmap_segmap(kernel_pmap, 414 trapframe->badvaddr))) 415 panic("trap: ktlbmod: invalid segmap"); 416 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1); 417 entry = *pte; 418#ifdef SMP 419 /* It is possible that some other CPU changed m-bit */ 420 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { 421 trapframe->badvaddr &= ~PGOFSET; 422 pmap_update_page(kernel_pmap, 423 trapframe->badvaddr, entry); 424 PMAP_UNLOCK(kernel_pmap); 425 return (trapframe->pc); 426 } 427#else 428 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) 429 panic("trap: ktlbmod: invalid pte"); 430#endif 431 if (entry & mips_pg_ro_bit()) { 432 /* write to read only page in the kernel */ 433 ftype = VM_PROT_WRITE; 434 PMAP_UNLOCK(kernel_pmap); 435 goto kernel_fault; 436 } 437 entry |= mips_pg_m_bit(); 438 *pte = entry; 439 trapframe->badvaddr &= ~PGOFSET; 440 pmap_update_page(kernel_pmap, trapframe->badvaddr, entry); 441 pa = mips_tlbpfn_to_paddr(entry); 442 if (!page_is_managed(pa)) 443 panic("trap: ktlbmod: unmanaged page"); 444 pmap_set_modified(pa); 445 PMAP_UNLOCK(kernel_pmap); 446 return (trapframe->pc); 447 } 448 /* FALLTHROUGH */ 449 450 case T_TLB_MOD + T_USER: 451 { 452 vm_offset_t pa; 453 454 pmap = &p->p_vmspace->vm_pmap; 455 456 PMAP_LOCK(pmap); 457 if (!(pte = pmap_segmap(pmap, trapframe->badvaddr))) 458 panic("trap: utlbmod: invalid segmap"); 459 pte += (trapframe->badvaddr >> PGSHIFT) & (NPTEPG - 1); 460 entry = *pte; 461#ifdef SMP 462 /* It is possible that some other CPU changed m-bit */ 463 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { 464 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET); 465 pmap_update_page(pmap, trapframe->badvaddr, entry); 466 PMAP_UNLOCK(pmap); 467 goto out; 468 } 469#else 470 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { 471 panic("trap: utlbmod: invalid pte"); 472 } 473#endif 474 475 if (entry & mips_pg_ro_bit()) { 476 /* write to read only page */ 477 ftype = VM_PROT_WRITE; 478 PMAP_UNLOCK(pmap); 479 goto dofault; 480 } 481 entry |= mips_pg_m_bit(); 482 *pte = entry; 483 trapframe->badvaddr = (trapframe->badvaddr & ~PGOFSET); 484 pmap_update_page(pmap, trapframe->badvaddr, entry); 485 trapframe->badvaddr |= (pmap->pm_asid[PCPU_GET(cpuid)].asid << VMTLB_PID_SHIFT); 486 pa = mips_tlbpfn_to_paddr(entry); 487 if (!page_is_managed(pa)) 488 panic("trap: utlbmod: unmanaged page"); 489 pmap_set_modified(pa); 490 491 PMAP_UNLOCK(pmap); 492 if (!usermode) { 493 return (trapframe->pc); 494 } 495 goto out; 496 } 497 498 case T_TLB_LD_MISS: 499 case T_TLB_ST_MISS: 500 ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ; 501 /* check for kernel address */ 502 if (KERNLAND(trapframe->badvaddr)) { 503 vm_offset_t va; 504 int rv; 505 506 kernel_fault: 507 va = trunc_page((vm_offset_t)trapframe->badvaddr); 508 rv = vm_fault(kernel_map, va, ftype, VM_FAULT_NORMAL); 509 if (rv == KERN_SUCCESS) 510 return (trapframe->pc); 511 if ((i = td->td_pcb->pcb_onfault) != 0) { 512 td->td_pcb->pcb_onfault = 0; 513 return (onfault_table[i]); 514 } 515 goto err; 516 } 517 /* 518 * It is an error for the kernel to access user space except 519 * through the copyin/copyout routines. 520 */ 521 if ((i = td->td_pcb->pcb_onfault) == 0) 522 goto err; 523 /* check for fuswintr() or suswintr() getting a page fault */ 524 if (i == 4) { 525 return (onfault_table[i]); 526 } 527 goto dofault; 528 529 case T_TLB_LD_MISS + T_USER: 530 ftype = VM_PROT_READ; 531 goto dofault; 532 533 case T_TLB_ST_MISS + T_USER: 534 ftype = VM_PROT_WRITE; 535dofault: 536 { 537 vm_offset_t va; 538 struct vmspace *vm; 539 vm_map_t map; 540 int rv = 0; 541 int flag; 542 543 vm = p->p_vmspace; 544 map = &vm->vm_map; 545 va = trunc_page((vm_offset_t)trapframe->badvaddr); 546 if ((vm_offset_t)trapframe->badvaddr < VM_MIN_KERNEL_ADDRESS) { 547 if (ftype & VM_PROT_WRITE) 548 flag = VM_FAULT_DIRTY; 549 else 550 flag = VM_FAULT_NORMAL; 551 } else { 552 /* 553 * Don't allow user-mode faults in kernel 554 * address space. 555 */ 556 goto nogo; 557 } 558 559 /* 560 * Keep swapout from messing with us during this 561 * critical time. 562 */ 563 PROC_LOCK(p); 564 ++p->p_lock; 565 PROC_UNLOCK(p); 566 567 rv = vm_fault(map, va, ftype, flag); 568 569 PROC_LOCK(p); 570 --p->p_lock; 571 PROC_UNLOCK(p); 572#ifdef VMFAULT_TRACE 573 printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n", 574 map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, flag, 575 rv, trapframe->pc); 576#endif 577 578 if (rv == KERN_SUCCESS) { 579 if (!usermode) { 580 return (trapframe->pc); 581 } 582 goto out; 583 } 584 nogo: 585 if (!usermode) { 586 if ((i = td->td_pcb->pcb_onfault) != 0) { 587 td->td_pcb->pcb_onfault = 0; 588 return (onfault_table[i]); 589 } 590 goto err; 591 } 592 ucode = ftype; 593 i = ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); 594 addr = trapframe->pc; 595 596 msg = "BAD_PAGE_FAULT"; 597 log_bad_page_fault(msg, trapframe, type); 598 599 break; 600 } 601 602 case T_ADDR_ERR_LD + T_USER: /* misaligned or kseg access */ 603 case T_ADDR_ERR_ST + T_USER: /* misaligned or kseg access */ 604 if (allow_unaligned_acc) { 605 int mode; 606 607 if (type == (T_ADDR_ERR_LD + T_USER)) 608 mode = VM_PROT_READ; 609 else 610 mode = VM_PROT_WRITE; 611 612 /* 613 * ADDR_ERR faults have higher priority than TLB 614 * Miss faults. Therefore, it is necessary to 615 * verify that the faulting address is a valid 616 * virtual address within the process' address space 617 * before trying to emulate the unaligned access. 618 */ 619 if (useracc((caddr_t) 620 (((vm_offset_t)trapframe->badvaddr) & 621 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { 622 access_type = emulate_unaligned_access( 623 trapframe); 624 if (access_type != 0) 625 goto out; 626 } 627 } 628 msg = "ADDRESS_ERR"; 629 630 /* FALL THROUGH */ 631 632 case T_BUS_ERR_IFETCH + T_USER: /* BERR asserted to cpu */ 633 case T_BUS_ERR_LD_ST + T_USER: /* BERR asserted to cpu */ 634 ucode = 0; /* XXX should be VM_PROT_something */ 635 i = SIGBUS; 636 addr = trapframe->pc; 637 if (!msg) 638 msg = "BUS_ERR"; 639 log_bad_page_fault(msg, trapframe, type); 640 break; 641 642 case T_SYSCALL + T_USER: 643 { 644 struct trapframe *locr0 = td->td_frame; 645 struct sysent *callp; 646 unsigned int code; 647 int nargs, nsaved; 648 register_t args[8]; 649 650 /* 651 * note: PCPU_LAZY_INC() can only be used if we can 652 * afford occassional inaccuracy in the count. 653 */ 654 PCPU_LAZY_INC(cnt.v_syscall); 655 if (td->td_ucred != p->p_ucred) 656 cred_update_thread(td); 657#ifdef KSE 658 if (p->p_flag & P_SA) 659 thread_user_enter(td); 660#endif 661 /* compute next PC after syscall instruction */ 662 td->td_pcb->pcb_tpc = trapframe->pc; /* Remember if restart */ 663 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */ 664 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 665 0); 666 } else { 667 locr0->pc += sizeof(int); 668 } 669 code = locr0->v0; 670 671 switch (code) { 672 case SYS_syscall: 673 /* 674 * Code is first argument, followed by 675 * actual args. 676 */ 677 code = locr0->a0; 678 args[0] = locr0->a1; 679 args[1] = locr0->a2; 680 args[2] = locr0->a3; 681 nsaved = 3; 682 break; 683 684 case SYS___syscall: 685 /* 686 * Like syscall, but code is a quad, so as 687 * to maintain quad alignment for the rest 688 * of the arguments. 689 */ 690 if (_QUAD_LOWWORD == 0) { 691 code = locr0->a0; 692 } else { 693 code = locr0->a1; 694 } 695 args[0] = locr0->a2; 696 args[1] = locr0->a3; 697 nsaved = 2; 698 quad_syscall = 1; 699 break; 700 701 default: 702 args[0] = locr0->a0; 703 args[1] = locr0->a1; 704 args[2] = locr0->a2; 705 args[3] = locr0->a3; 706 nsaved = 4; 707 } 708#ifdef TRAP_DEBUG 709 printf("SYSCALL #%d pid:%u\n", code, p->p_pid); 710#endif 711 712 if (p->p_sysent->sv_mask) 713 code &= p->p_sysent->sv_mask; 714 715 if (code >= p->p_sysent->sv_size) 716 callp = &p->p_sysent->sv_table[0]; 717 else 718 callp = &p->p_sysent->sv_table[code]; 719 720 nargs = callp->sy_narg; 721 722 if (nargs > nsaved) { 723 i = copyin((caddr_t)(locr0->sp + 724 4 * sizeof(register_t)), (caddr_t)&args[nsaved], 725 (u_int)(nargs - nsaved) * sizeof(register_t)); 726 if (i) { 727 locr0->v0 = i; 728 locr0->a3 = 1; 729#ifdef KTRACE 730 if (KTRPOINT(td, KTR_SYSCALL)) 731 ktrsyscall(code, nargs, args); 732#endif 733 goto done; 734 } 735 } 736#ifdef KTRACE 737 if (KTRPOINT(td, KTR_SYSCALL)) 738 ktrsyscall(code, nargs, args); 739#endif 740 td->td_retval[0] = 0; 741 td->td_retval[1] = locr0->v1; 742 743#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 744 if (trp == trapdebug) 745 trapdebug[TRAPSIZE - 1].code = code; 746 else 747 trp[-1].code = code; 748#endif 749 STOPEVENT(p, S_SCE, nargs); 750 751 PTRACESTOP_SC(p, td, S_PT_SCE); 752 i = (*callp->sy_call) (td, args); 753#if 0 754 /* 755 * Reinitialize proc pointer `p' as it may be 756 * different if this is a child returning from fork 757 * syscall. 758 */ 759 td = curthread; 760 locr0 = td->td_frame; 761#endif 762 trapdebug_enter(locr0, -code); 763 cpu_set_syscall_retval(td, i); 764 765 /* 766 * The sync'ing of I & D caches for SYS_ptrace() is 767 * done by procfs_domem() through procfs_rwmem() 768 * instead of being done here under a special check 769 * for SYS_ptrace(). 770 */ 771 done: 772 /* 773 * Check for misbehavior. 774 */ 775 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", 776 (code >= 0 && code < SYS_MAXSYSCALL) ? 777 syscallnames[code] : "???"); 778 KASSERT(td->td_critnest == 0, 779 ("System call %s returning in a critical section", 780 (code >= 0 && code < SYS_MAXSYSCALL) ? 781 syscallnames[code] : "???")); 782 KASSERT(td->td_locks == 0, 783 ("System call %s returning with %d locks held", 784 (code >= 0 && code < SYS_MAXSYSCALL) ? 785 syscallnames[code] : "???", 786 td->td_locks)); 787 userret(td, trapframe); 788#ifdef KTRACE 789 if (KTRPOINT(p, KTR_SYSRET)) 790 ktrsysret(code, i, td->td_retval[0]); 791#endif 792 /* 793 * This works because errno is findable through the 794 * register set. If we ever support an emulation 795 * where this is not the case, this code will need 796 * to be revisited. 797 */ 798 STOPEVENT(p, S_SCX, code); 799 800 PTRACESTOP_SC(p, td, S_PT_SCX); 801 802 mtx_assert(&Giant, MA_NOTOWNED); 803 return (trapframe->pc); 804 } 805 806#ifdef DDB 807 case T_BREAK: 808 kdb_trap(type, 0, trapframe); 809 return (trapframe->pc); 810#endif 811 812 case T_BREAK + T_USER: 813 { 814 unsigned int va, instr; 815 816 /* compute address of break instruction */ 817 va = trapframe->pc; 818 if (DELAYBRANCH(trapframe->cause)) 819 va += sizeof(int); 820 821 /* read break instruction */ 822 instr = fuword((caddr_t)va); 823#if 0 824 printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n", 825 p->p_comm, p->p_pid, instr, trapframe->pc, 826 p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */ 827#endif 828 if (td->td_md.md_ss_addr != va || instr != BREAK_SSTEP) { 829 i = SIGTRAP; 830 addr = trapframe->pc; 831 break; 832 } 833 /* 834 * The restoration of the original instruction and 835 * the clearing of the berakpoint will be done later 836 * by the call to ptrace_clear_single_step() in 837 * issignal() when SIGTRAP is processed. 838 */ 839 addr = trapframe->pc; 840 i = SIGTRAP; 841 break; 842 } 843 844 case T_IWATCH + T_USER: 845 case T_DWATCH + T_USER: 846 { 847 unsigned int va; 848 849 /* compute address of trapped instruction */ 850 va = trapframe->pc; 851 if (DELAYBRANCH(trapframe->cause)) 852 va += sizeof(int); 853 printf("watch exception @ 0x%x\n", va); 854 i = SIGTRAP; 855 addr = va; 856 break; 857 } 858 859 case T_TRAP + T_USER: 860 { 861 unsigned int va, instr; 862 struct trapframe *locr0 = td->td_frame; 863 864 /* compute address of trap instruction */ 865 va = trapframe->pc; 866 if (DELAYBRANCH(trapframe->cause)) 867 va += sizeof(int); 868 /* read break instruction */ 869 instr = fuword((caddr_t)va); 870 871 if (DELAYBRANCH(trapframe->cause)) { /* Check BD bit */ 872 locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 873 0); 874 } else { 875 locr0->pc += sizeof(int); 876 } 877 addr = va; 878 i = SIGEMT; /* Stuff it with something for now */ 879 break; 880 } 881 882 case T_RES_INST + T_USER: 883 i = SIGILL; 884 addr = trapframe->pc; 885 break; 886 case T_C2E: 887 case T_C2E + T_USER: 888 goto err; 889 break; 890 case T_COP_UNUSABLE: 891 goto err; 892 break; 893 case T_COP_UNUSABLE + T_USER: 894#if defined(SOFTFLOAT) 895 /* FP (COP1) instruction */ 896 if ((trapframe->cause & CR_COP_ERR) == 0x10000000) { 897 i = SIGILL; 898 break; 899 } 900#endif 901 if ((trapframe->cause & CR_COP_ERR) != 0x10000000) { 902 i = SIGILL; /* only FPU instructions allowed */ 903 break; 904 } 905 addr = trapframe->pc; 906 MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame); 907 PCPU_SET(fpcurthread, td); 908 td->td_frame->sr |= SR_COP_1_BIT; 909 td->td_md.md_flags |= MDTD_FPUSED; 910 goto out; 911 912 case T_FPE: 913#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 914 trapDump("fpintr"); 915#else 916 printf("FPU Trap: PC %x CR %x SR %x\n", 917 trapframe->pc, trapframe->cause, trapframe->sr); 918 goto err; 919#endif 920 921 case T_FPE + T_USER: 922 MachFPTrap(trapframe->sr, trapframe->cause, trapframe->pc); 923 goto out; 924 925 case T_OVFLOW + T_USER: 926 i = SIGFPE; 927 addr = trapframe->pc; 928 break; 929 930 case T_ADDR_ERR_LD: /* misaligned access */ 931 case T_ADDR_ERR_ST: /* misaligned access */ 932#ifdef TRAP_DEBUG 933 printf("+++ ADDR_ERR: type = %d, badvaddr = %x\n", type, 934 trapframe->badvaddr); 935#endif 936 /* Only allow emulation on a user address */ 937 if (allow_unaligned_acc && 938 ((vm_offset_t)trapframe->badvaddr < VM_MAXUSER_ADDRESS)) { 939 int mode; 940 941 if (type == T_ADDR_ERR_LD) 942 mode = VM_PROT_READ; 943 else 944 mode = VM_PROT_WRITE; 945 946 /* 947 * ADDR_ERR faults have higher priority than TLB 948 * Miss faults. Therefore, it is necessary to 949 * verify that the faulting address is a valid 950 * virtual address within the process' address space 951 * before trying to emulate the unaligned access. 952 */ 953 if (useracc((caddr_t) 954 (((vm_offset_t)trapframe->badvaddr) & 955 ~(sizeof(int) - 1)), sizeof(int) * 2, mode)) { 956 access_type = emulate_unaligned_access( 957 trapframe); 958 if (access_type != 0) { 959 return (trapframe->pc); 960 } 961 } 962 } 963 /* FALLTHROUGH */ 964 965 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 966 if ((i = td->td_pcb->pcb_onfault) != 0) { 967 td->td_pcb->pcb_onfault = 0; 968 return (onfault_table[i]); 969 } 970 /* FALLTHROUGH */ 971 972 default: 973err: 974 975#if !defined(SMP) && defined(DEBUG) 976 stacktrace(!usermode ? trapframe : td->td_frame); 977 trapDump("trap"); 978#endif 979#ifdef SMP 980 printf("cpu:%d-", PCPU_GET(cpuid)); 981#endif 982 printf("Trap cause = %d (%s - ", type, 983 trap_type[type & (~T_USER)]); 984 985 if (type & T_USER) 986 printf("user mode)\n"); 987 else 988 printf("kernel mode)\n"); 989 990#ifdef TRAP_DEBUG 991 printf("badvaddr = %x, pc = %x, ra = %x, sr = 0x%x\n", 992 trapframe->badvaddr, trapframe->pc, trapframe->ra, 993 trapframe->sr); 994#endif 995 996#ifdef KDB 997 if (debugger_on_panic || kdb_active) { 998 kdb_trap(type, 0, trapframe); 999 } 1000#endif 1001 panic("trap"); 1002 } 1003 td->td_frame->pc = trapframe->pc; 1004 td->td_frame->cause = trapframe->cause; 1005 td->td_frame->badvaddr = trapframe->badvaddr; 1006 ksiginfo_init_trap(&ksi); 1007 ksi.ksi_signo = i; 1008 ksi.ksi_code = ucode; 1009 ksi.ksi_addr = (void *)addr; 1010 ksi.ksi_trapno = type; 1011 trapsignal(td, &ksi); 1012out: 1013 1014 /* 1015 * Note: we should only get here if returning to user mode. 1016 */ 1017 userret(td, trapframe); 1018 mtx_assert(&Giant, MA_NOTOWNED); 1019 return (trapframe->pc); 1020} 1021 1022#if !defined(SMP) && (defined(DDB) || defined(DEBUG)) 1023void 1024trapDump(char *msg) 1025{ 1026 int i, s; 1027 1028 s = disableintr(); 1029 printf("trapDump(%s)\n", msg); 1030 for (i = 0; i < TRAPSIZE; i++) { 1031 if (trp == trapdebug) { 1032 trp = &trapdebug[TRAPSIZE - 1]; 1033 } else { 1034 trp--; 1035 } 1036 1037 if (trp->cause == 0) 1038 break; 1039 1040 printf("%s: ADR %x PC %x CR %x SR %x\n", 1041 trap_type[(trp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT], 1042 trp->vadr, trp->pc, trp->cause, trp->status); 1043 1044 printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code); 1045 } 1046 restoreintr(s); 1047} 1048 1049#endif 1050 1051 1052/* 1053 * Return the resulting PC as if the branch was executed. 1054 */ 1055u_int 1056MipsEmulateBranch(struct trapframe *framePtr, int instPC, int fpcCSR, 1057 u_int instptr) 1058{ 1059 InstFmt inst; 1060 register_t *regsPtr = (register_t *) framePtr; 1061 unsigned retAddr = 0; 1062 int condition; 1063 1064#define GetBranchDest(InstPtr, inst) \ 1065 ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2)) 1066 1067 1068 if (instptr) { 1069 if (instptr < MIPS_KSEG0_START) 1070 inst.word = fuword((void *)instptr); 1071 else 1072 inst = *(InstFmt *) instptr; 1073 } else { 1074 if ((vm_offset_t)instPC < MIPS_KSEG0_START) 1075 inst.word = fuword((void *)instPC); 1076 else 1077 inst = *(InstFmt *) instPC; 1078 } 1079 1080 switch ((int)inst.JType.op) { 1081 case OP_SPECIAL: 1082 switch ((int)inst.RType.func) { 1083 case OP_JR: 1084 case OP_JALR: 1085 retAddr = regsPtr[inst.RType.rs]; 1086 break; 1087 1088 default: 1089 retAddr = instPC + 4; 1090 break; 1091 } 1092 break; 1093 1094 case OP_BCOND: 1095 switch ((int)inst.IType.rt) { 1096 case OP_BLTZ: 1097 case OP_BLTZL: 1098 case OP_BLTZAL: 1099 case OP_BLTZALL: 1100 if ((int)(regsPtr[inst.RType.rs]) < 0) 1101 retAddr = GetBranchDest(instPC, inst); 1102 else 1103 retAddr = instPC + 8; 1104 break; 1105 1106 case OP_BGEZ: 1107 case OP_BGEZL: 1108 case OP_BGEZAL: 1109 case OP_BGEZALL: 1110 if ((int)(regsPtr[inst.RType.rs]) >= 0) 1111 retAddr = GetBranchDest(instPC, inst); 1112 else 1113 retAddr = instPC + 8; 1114 break; 1115 1116 case OP_TGEI: 1117 case OP_TGEIU: 1118 case OP_TLTI: 1119 case OP_TLTIU: 1120 case OP_TEQI: 1121 case OP_TNEI: 1122 retAddr = instPC + 4; /* Like syscall... */ 1123 break; 1124 1125 default: 1126 panic("MipsEmulateBranch: Bad branch cond"); 1127 } 1128 break; 1129 1130 case OP_J: 1131 case OP_JAL: 1132 retAddr = (inst.JType.target << 2) | 1133 ((unsigned)instPC & 0xF0000000); 1134 break; 1135 1136 case OP_BEQ: 1137 case OP_BEQL: 1138 if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt]) 1139 retAddr = GetBranchDest(instPC, inst); 1140 else 1141 retAddr = instPC + 8; 1142 break; 1143 1144 case OP_BNE: 1145 case OP_BNEL: 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_BLEZ: 1153 case OP_BLEZL: 1154 if ((int)(regsPtr[inst.RType.rs]) <= 0) 1155 retAddr = GetBranchDest(instPC, inst); 1156 else 1157 retAddr = instPC + 8; 1158 break; 1159 1160 case OP_BGTZ: 1161 case OP_BGTZL: 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_COP1: 1169 switch (inst.RType.rs) { 1170 case OP_BCx: 1171 case OP_BCy: 1172 if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE) 1173 condition = fpcCSR & FPC_COND_BIT; 1174 else 1175 condition = !(fpcCSR & FPC_COND_BIT); 1176 if (condition) 1177 retAddr = GetBranchDest(instPC, inst); 1178 else 1179 retAddr = instPC + 8; 1180 break; 1181 1182 default: 1183 retAddr = instPC + 4; 1184 } 1185 break; 1186 1187 default: 1188 retAddr = instPC + 4; 1189 } 1190 return (retAddr); 1191} 1192 1193 1194#if defined(DDB) || defined(DEBUG) 1195#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ 1196 1197/* forward */ 1198char *fn_name(unsigned addr); 1199 1200/* 1201 * Print a stack backtrace. 1202 */ 1203void 1204stacktrace(struct trapframe *regs) 1205{ 1206 stacktrace_subr(regs, printf); 1207} 1208 1209void 1210stacktrace_subr(struct trapframe *regs, int (*printfn) (const char *,...)) 1211{ 1212 InstFmt i; 1213 unsigned a0, a1, a2, a3, pc, sp, fp, ra, va, subr; 1214 unsigned instr, mask; 1215 unsigned int frames = 0; 1216 int more, stksize; 1217 1218 /* get initial values from the exception frame */ 1219 sp = regs->sp; 1220 pc = regs->pc; 1221 fp = regs->s8; 1222 ra = regs->ra; /* May be a 'leaf' function */ 1223 a0 = regs->a0; 1224 a1 = regs->a1; 1225 a2 = regs->a2; 1226 a3 = regs->a3; 1227 1228/* Jump here when done with a frame, to start a new one */ 1229loop: 1230 1231/* Jump here after a nonstandard (interrupt handler) frame */ 1232 stksize = 0; 1233 subr = 0; 1234 if (frames++ > 100) { 1235 (*printfn) ("\nstackframe count exceeded\n"); 1236 /* return breaks stackframe-size heuristics with gcc -O2 */ 1237 goto finish; /* XXX */ 1238 } 1239 /* check for bad SP: could foul up next frame */ 1240 if (sp & 3 || sp < 0x80000000) { 1241 (*printfn) ("SP 0x%x: not in kernel\n", sp); 1242 ra = 0; 1243 subr = 0; 1244 goto done; 1245 } 1246#define Between(x, y, z) \ 1247 ( ((x) <= (y)) && ((y) < (z)) ) 1248#define pcBetween(a,b) \ 1249 Between((unsigned)a, pc, (unsigned)b) 1250 1251 /* 1252 * Check for current PC in exception handler code that don't have a 1253 * preceding "j ra" at the tail of the preceding function. Depends 1254 * on relative ordering of functions in exception.S, swtch.S. 1255 */ 1256 if (pcBetween(MipsKernGenException, MipsUserGenException)) 1257 subr = (unsigned)MipsKernGenException; 1258 else if (pcBetween(MipsUserGenException, MipsKernIntr)) 1259 subr = (unsigned)MipsUserGenException; 1260 else if (pcBetween(MipsKernIntr, MipsUserIntr)) 1261 subr = (unsigned)MipsKernIntr; 1262 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException)) 1263 subr = (unsigned)MipsUserIntr; 1264 else if (pcBetween(MipsTLBInvalidException, 1265 MipsKernTLBInvalidException)) 1266 subr = (unsigned)MipsTLBInvalidException; 1267 else if (pcBetween(MipsKernTLBInvalidException, 1268 MipsUserTLBInvalidException)) 1269 subr = (unsigned)MipsKernTLBInvalidException; 1270 else if (pcBetween(MipsUserTLBInvalidException, MipsTLBMissException)) 1271 subr = (unsigned)MipsUserTLBInvalidException; 1272 else if (pcBetween(cpu_switch, MipsSwitchFPState)) 1273 subr = (unsigned)cpu_switch; 1274 else if (pcBetween(_locore, _locoreEnd)) { 1275 subr = (unsigned)_locore; 1276 ra = 0; 1277 goto done; 1278 } 1279 /* check for bad PC */ 1280 if (pc & 3 || pc < (unsigned)0x80000000 || pc >= (unsigned)edata) { 1281 (*printfn) ("PC 0x%x: not in kernel\n", pc); 1282 ra = 0; 1283 goto done; 1284 } 1285 /* 1286 * Find the beginning of the current subroutine by scanning 1287 * backwards from the current PC for the end of the previous 1288 * subroutine. 1289 */ 1290 if (!subr) { 1291 va = pc - sizeof(int); 1292 while ((instr = kdbpeek((int *)va)) != MIPS_JR_RA) 1293 va -= sizeof(int); 1294 va += 2 * sizeof(int); /* skip back over branch & delay slot */ 1295 /* skip over nulls which might separate .o files */ 1296 while ((instr = kdbpeek((int *)va)) == 0) 1297 va += sizeof(int); 1298 subr = va; 1299 } 1300 /* scan forwards to find stack size and any saved registers */ 1301 stksize = 0; 1302 more = 3; 1303 mask = 0; 1304 for (va = subr; more; va += sizeof(int), 1305 more = (more == 3) ? 3 : more - 1) { 1306 /* stop if hit our current position */ 1307 if (va >= pc) 1308 break; 1309 instr = kdbpeek((int *)va); 1310 i.word = instr; 1311 switch (i.JType.op) { 1312 case OP_SPECIAL: 1313 switch (i.RType.func) { 1314 case OP_JR: 1315 case OP_JALR: 1316 more = 2; /* stop after next instruction */ 1317 break; 1318 1319 case OP_SYSCALL: 1320 case OP_BREAK: 1321 more = 1; /* stop now */ 1322 }; 1323 break; 1324 1325 case OP_BCOND: 1326 case OP_J: 1327 case OP_JAL: 1328 case OP_BEQ: 1329 case OP_BNE: 1330 case OP_BLEZ: 1331 case OP_BGTZ: 1332 more = 2; /* stop after next instruction */ 1333 break; 1334 1335 case OP_COP0: 1336 case OP_COP1: 1337 case OP_COP2: 1338 case OP_COP3: 1339 switch (i.RType.rs) { 1340 case OP_BCx: 1341 case OP_BCy: 1342 more = 2; /* stop after next instruction */ 1343 }; 1344 break; 1345 1346 case OP_SW: 1347 /* look for saved registers on the stack */ 1348 if (i.IType.rs != 29) 1349 break; 1350 /* only restore the first one */ 1351 if (mask & (1 << i.IType.rt)) 1352 break; 1353 mask |= (1 << i.IType.rt); 1354 switch (i.IType.rt) { 1355 case 4:/* a0 */ 1356 a0 = kdbpeek((int *)(sp + (short)i.IType.imm)); 1357 break; 1358 1359 case 5:/* a1 */ 1360 a1 = kdbpeek((int *)(sp + (short)i.IType.imm)); 1361 break; 1362 1363 case 6:/* a2 */ 1364 a2 = kdbpeek((int *)(sp + (short)i.IType.imm)); 1365 break; 1366 1367 case 7:/* a3 */ 1368 a3 = kdbpeek((int *)(sp + (short)i.IType.imm)); 1369 break; 1370 1371 case 30: /* fp */ 1372 fp = kdbpeek((int *)(sp + (short)i.IType.imm)); 1373 break; 1374 1375 case 31: /* ra */ 1376 ra = kdbpeek((int *)(sp + (short)i.IType.imm)); 1377 } 1378 break; 1379 1380 case OP_SD: 1381 /* look for saved registers on the stack */ 1382 if (i.IType.rs != 29) 1383 break; 1384 /* only restore the first one */ 1385 if (mask & (1 << i.IType.rt)) 1386 break; 1387 mask |= (1 << i.IType.rt); 1388 switch (i.IType.rt) { 1389 case 4:/* a0 */ 1390 a0 = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1391 break; 1392 1393 case 5:/* a1 */ 1394 a1 = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1395 break; 1396 1397 case 6:/* a2 */ 1398 a2 = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1399 break; 1400 1401 case 7:/* a3 */ 1402 a3 = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1403 break; 1404 1405 case 30: /* fp */ 1406 fp = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1407 break; 1408 1409 case 31: /* ra */ 1410 ra = kdbpeekD((int *)(sp + (short)i.IType.imm)); 1411 } 1412 break; 1413 1414 case OP_ADDI: 1415 case OP_ADDIU: 1416 /* look for stack pointer adjustment */ 1417 if (i.IType.rs != 29 || i.IType.rt != 29) 1418 break; 1419 stksize = -((short)i.IType.imm); 1420 } 1421 } 1422 1423done: 1424 (*printfn) ("%s+%x (%x,%x,%x,%x) ra %x sz %d\n", 1425 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize); 1426 1427 if (ra) { 1428 if (pc == ra && stksize == 0) 1429 (*printfn) ("stacktrace: loop!\n"); 1430 else { 1431 pc = ra; 1432 sp += stksize; 1433 ra = 0; 1434 goto loop; 1435 } 1436 } else { 1437finish: 1438 if (curproc) 1439 (*printfn) ("pid %d\n", curproc->p_pid); 1440 else 1441 (*printfn) ("curproc NULL\n"); 1442 } 1443} 1444 1445/* 1446 * Functions ``special'' enough to print by name 1447 */ 1448#ifdef __STDC__ 1449#define Name(_fn) { (void*)_fn, # _fn } 1450#else 1451#define Name(_fn) { _fn, "_fn"} 1452#endif 1453static struct { 1454 void *addr; 1455 char *name; 1456} names[] = { 1457 1458 Name(trap), 1459 Name(MipsKernGenException), 1460 Name(MipsUserGenException), 1461 Name(MipsKernIntr), 1462 Name(MipsUserIntr), 1463 Name(cpu_switch), 1464 { 1465 0, 0 1466 } 1467}; 1468 1469/* 1470 * Map a function address to a string name, if known; or a hex string. 1471 */ 1472char * 1473fn_name(unsigned addr) 1474{ 1475 static char buf[17]; 1476 int i = 0; 1477 1478#ifdef DDB 1479 db_expr_t diff; 1480 c_db_sym_t sym; 1481 char *symname; 1482 1483 diff = 0; 1484 symname = NULL; 1485 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff); 1486 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0); 1487 if (symname && diff == 0) 1488 return (symname); 1489#endif 1490 1491 for (i = 0; names[i].name; i++) 1492 if (names[i].addr == (void *)addr) 1493 return (names[i].name); 1494 sprintf(buf, "%x", addr); 1495 return (buf); 1496} 1497 1498#endif /* DDB */ 1499 1500static void 1501log_frame_dump(struct trapframe *frame) 1502{ 1503 log(LOG_ERR, "Trapframe Register Dump:\n"); 1504 log(LOG_ERR, "\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n", 1505 0, frame->ast, frame->v0, frame->v1); 1506 1507 log(LOG_ERR, "\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n", 1508 frame->a0, frame->a1, frame->a2, frame->a3); 1509 1510 log(LOG_ERR, "\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n", 1511 frame->t0, frame->t1, frame->t2, frame->t3); 1512 1513 log(LOG_ERR, "\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n", 1514 frame->t4, frame->t5, frame->t6, frame->t7); 1515 1516 log(LOG_ERR, "\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n", 1517 frame->t8, frame->t9, frame->s0, frame->s1); 1518 1519 log(LOG_ERR, "\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n", 1520 frame->s2, frame->s3, frame->s4, frame->s5); 1521 1522 log(LOG_ERR, "\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n", 1523 frame->s6, frame->s7, frame->k0, frame->k1); 1524 1525 log(LOG_ERR, "\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n", 1526 frame->gp, frame->sp, frame->s8, frame->ra); 1527 1528 log(LOG_ERR, "\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n", 1529 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr); 1530 1531#ifdef IC_REG 1532 log(LOG_ERR, "\tcause: %08x\tpc: %08x\tic: %08x\n", 1533 frame->cause, frame->pc, frame->ic); 1534#else 1535 log(LOG_ERR, "\tcause: %08x\tpc: %08x\n", 1536 frame->cause, frame->pc); 1537#endif 1538} 1539 1540#ifdef TRAP_DEBUG 1541static void 1542trap_frame_dump(struct trapframe *frame) 1543{ 1544 printf("Trapframe Register Dump:\n"); 1545 printf("\tzero: %08x\tat: %08x\tv0: %08x\tv1: %08x\n", 1546 0, frame->ast, frame->v0, frame->v1); 1547 1548 printf("\ta0: %08x\ta1: %08x\ta2: %08x\ta3: %08x\n", 1549 frame->a0, frame->a1, frame->a2, frame->a3); 1550 1551 printf("\tt0: %08x\tt1: %08x\tt2: %08x\tt3: %08x\n", 1552 frame->t0, frame->t1, frame->t2, frame->t3); 1553 1554 printf("\tt4: %08x\tt5: %08x\tt6: %08x\tt7: %08x\n", 1555 frame->t4, frame->t5, frame->t6, frame->t7); 1556 1557 printf("\tt8: %08x\tt9: %08x\ts0: %08x\ts1: %08x\n", 1558 frame->t8, frame->t9, frame->s0, frame->s1); 1559 1560 printf("\ts2: %08x\ts3: %08x\ts4: %08x\ts5: %08x\n", 1561 frame->s2, frame->s3, frame->s4, frame->s5); 1562 1563 printf("\ts6: %08x\ts7: %08x\tk0: %08x\tk1: %08x\n", 1564 frame->s6, frame->s7, frame->k0, frame->k1); 1565 1566 printf("\tgp: %08x\tsp: %08x\ts8: %08x\tra: %08x\n", 1567 frame->gp, frame->sp, frame->s8, frame->ra); 1568 1569 printf("\tsr: %08x\tmullo: %08x\tmulhi: %08x\tbadvaddr: %08x\n", 1570 frame->sr, frame->mullo, frame->mulhi, frame->badvaddr); 1571 1572#ifdef IC_REG 1573 printf("\tcause: %08x\tpc: %08x\tic: %08x\n", 1574 frame->cause, frame->pc, frame->ic); 1575#else 1576 printf("\tcause: %08x\tpc: %08x\n", 1577 frame->cause, frame->pc); 1578#endif 1579} 1580 1581#endif 1582 1583 1584static void 1585get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) 1586{ 1587 pt_entry_t *ptep; 1588 pd_entry_t *pdep; 1589 struct proc *p = curproc; 1590 1591 pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[va >> SEGSHIFT])); 1592 if (*pdep) 1593 ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); 1594 else 1595 ptep = (pt_entry_t *)0; 1596 1597 *pdepp = pdep; 1598 *ptepp = ptep; 1599} 1600 1601 1602static void 1603log_bad_page_fault(char *msg, struct trapframe *frame, int trap_type) 1604{ 1605 pt_entry_t *ptep; 1606 pd_entry_t *pdep; 1607 unsigned int *addr; 1608 struct proc *p = curproc; 1609 char *read_or_write; 1610 register_t pc; 1611 1612 trap_type &= ~T_USER; 1613 1614#ifdef SMP 1615 printf("cpuid = %d\n", PCPU_GET(cpuid)); 1616#endif 1617 switch (trap_type) { 1618 case T_TLB_ST_MISS: 1619 case T_ADDR_ERR_ST: 1620 read_or_write = "write"; 1621 break; 1622 case T_TLB_LD_MISS: 1623 case T_ADDR_ERR_LD: 1624 case T_BUS_ERR_IFETCH: 1625 read_or_write = "read"; 1626 break; 1627 default: 1628 read_or_write = ""; 1629 } 1630 1631 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1632 log(LOG_ERR, "%s: pid %d (%s), uid %d: pc 0x%x got a %s fault at 0x%x\n", 1633 msg, p->p_pid, p->p_comm, 1634 p->p_ucred ? p->p_ucred->cr_uid : -1, 1635 pc, 1636 read_or_write, 1637 frame->badvaddr); 1638 1639 /* log registers in trap frame */ 1640 log_frame_dump(frame); 1641 1642 get_mapping_info((vm_offset_t)pc, &pdep, &ptep); 1643 1644 /* 1645 * Dump a few words around faulting instruction, if the addres is 1646 * valid. 1647 */ 1648 if (!(pc & 3) && (pc != frame->badvaddr) && 1649 (trap_type != T_BUS_ERR_IFETCH) && 1650 useracc((caddr_t)pc, sizeof(int) * 4, VM_PROT_READ)) { 1651 /* dump page table entry for faulting instruction */ 1652 log(LOG_ERR, "Page table info for pc address 0x%x: pde = %p, pte = 0x%lx\n", 1653 pc, *pdep, ptep ? *ptep : 0); 1654 1655 addr = (unsigned int *)pc; 1656 log(LOG_ERR, "Dumping 4 words starting at pc address %p: \n", 1657 addr); 1658 log(LOG_ERR, "%08x %08x %08x %08x\n", 1659 addr[0], addr[1], addr[2], addr[3]); 1660 } else { 1661 log(LOG_ERR, "pc address 0x%x is inaccessible, pde = 0x%p, pte = 0x%lx\n", 1662 pc, *pdep, ptep ? *ptep : 0); 1663 } 1664 /* panic("Bad trap");*/ 1665} 1666 1667 1668/* 1669 * Unaligned load/store emulation 1670 */ 1671static int 1672mips_unaligned_load_store(struct trapframe *frame, register_t addr, register_t pc) 1673{ 1674 register_t *reg = (register_t *) frame; 1675 u_int32_t inst = *((u_int32_t *) pc); 1676 u_int32_t value_msb, value; 1677 int access_type = 0; 1678 1679 switch (MIPS_INST_OPCODE(inst)) { 1680 case OP_LHU: 1681 lbu_macro(value_msb, addr); 1682 addr += 1; 1683 lbu_macro(value, addr); 1684 value |= value_msb << 8; 1685 reg[MIPS_INST_RT(inst)] = value; 1686 access_type = MIPS_LHU_ACCESS; 1687 break; 1688 1689 case OP_LH: 1690 lb_macro(value_msb, addr); 1691 addr += 1; 1692 lbu_macro(value, addr); 1693 value |= value_msb << 8; 1694 reg[MIPS_INST_RT(inst)] = value; 1695 access_type = MIPS_LH_ACCESS; 1696 break; 1697 1698 case OP_LWU: 1699 lwl_macro(value, addr); 1700 addr += 3; 1701 lwr_macro(value, addr); 1702 value &= 0xffffffff; 1703 reg[MIPS_INST_RT(inst)] = value; 1704 access_type = MIPS_LWU_ACCESS; 1705 break; 1706 1707 case OP_LW: 1708 lwl_macro(value, addr); 1709 addr += 3; 1710 lwr_macro(value, addr); 1711 reg[MIPS_INST_RT(inst)] = value; 1712 access_type = MIPS_LW_ACCESS; 1713 break; 1714 1715 case OP_SH: 1716 value = reg[MIPS_INST_RT(inst)]; 1717 value_msb = value >> 8; 1718 sb_macro(value_msb, addr); 1719 addr += 1; 1720 sb_macro(value, addr); 1721 access_type = MIPS_SH_ACCESS; 1722 break; 1723 1724 case OP_SW: 1725 value = reg[MIPS_INST_RT(inst)]; 1726 swl_macro(value, addr); 1727 addr += 3; 1728 swr_macro(value, addr); 1729 access_type = MIPS_SW_ACCESS; 1730 break; 1731 1732 default: 1733 break; 1734 } 1735 1736 return access_type; 1737} 1738 1739 1740static int 1741emulate_unaligned_access(struct trapframe *frame) 1742{ 1743 register_t pc; 1744 int access_type = 0; 1745 1746 pc = frame->pc + (DELAYBRANCH(frame->cause) ? 4 : 0); 1747 1748 /* 1749 * Fall through if it's instruction fetch exception 1750 */ 1751 if (!((pc & 3) || (pc == frame->badvaddr))) { 1752 1753 /* 1754 * Handle unaligned load and store 1755 */ 1756 1757 /* 1758 * Return access type if the instruction was emulated. 1759 * Otherwise restore pc and fall through. 1760 */ 1761 access_type = mips_unaligned_load_store(frame, 1762 frame->badvaddr, pc); 1763 1764 if (access_type) { 1765 if (DELAYBRANCH(frame->cause)) 1766 frame->pc = MipsEmulateBranch(frame, frame->pc, 1767 0, 0); 1768 else 1769 frame->pc += 4; 1770 1771 log(LOG_INFO, "Unaligned %s: pc=0x%x, badvaddr=0x%x\n", 1772 access_name[access_type - 1], pc, frame->badvaddr); 1773 } 1774 } 1775 return access_type; 1776} 1777