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