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