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