Annotation of sys/arch/mips64/mips64/trap.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: trap.c,v 1.37 2007/07/16 20:21:20 miod Exp $ */
! 2: /* tracked to 1.23 */
! 3:
! 4: /*
! 5: * Copyright (c) 1988 University of Utah.
! 6: * Copyright (c) 1992, 1993
! 7: * The Regents of the University of California. All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to Berkeley by
! 10: * the Systems Programming Group of the University of Utah Computer
! 11: * Science Department and Ralph Campbell.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that the following conditions
! 15: * are met:
! 16: * 1. Redistributions of source code must retain the above copyright
! 17: * notice, this list of conditions and the following disclaimer.
! 18: * 2. Redistributions in binary form must reproduce the above copyright
! 19: * notice, this list of conditions and the following disclaimer in the
! 20: * documentation and/or other materials provided with the distribution.
! 21: * 3. All advertising materials mentioning features or use of this software
! 22: * must display the following acknowledgement:
! 23: * This product includes software developed by the University of
! 24: * California, Berkeley and its contributors.
! 25: * 4. Neither the name of the University nor the names of its contributors
! 26: * may be used to endorse or promote products derived from this software
! 27: * without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
! 40: *
! 41: * from: Utah Hdr: trap.c 1.32 91/04/06
! 42: *
! 43: * from: @(#)trap.c 8.5 (Berkeley) 1/11/94
! 44: */
! 45:
! 46: /*
! 47: * THIS CODE SHOULD BE REWRITTEN!
! 48: */
! 49:
! 50: #include <sys/param.h>
! 51: #include <sys/systm.h>
! 52: #include <sys/exec.h>
! 53: #include <sys/proc.h>
! 54: #include <sys/kernel.h>
! 55: #include <sys/signalvar.h>
! 56: #include <sys/syscall.h>
! 57: #include <sys/user.h>
! 58: #include <sys/buf.h>
! 59: #include <sys/device.h>
! 60: #ifdef KTRACE
! 61: #include <sys/ktrace.h>
! 62: #endif
! 63: #ifdef PTRACE
! 64: #include <sys/ptrace.h>
! 65: #endif
! 66: #include <net/netisr.h>
! 67:
! 68: #include <uvm/uvm_extern.h>
! 69:
! 70: #include <machine/trap.h>
! 71: #include <machine/psl.h>
! 72: #include <machine/cpu.h>
! 73: #include <machine/pio.h>
! 74: #include <machine/intr.h>
! 75: #include <machine/autoconf.h>
! 76: #include <machine/pte.h>
! 77: #include <machine/pmap.h>
! 78: #include <machine/mips_opcode.h>
! 79: #include <machine/frame.h>
! 80: #include <machine/regnum.h>
! 81:
! 82: #include <mips64/rm7000.h>
! 83:
! 84: #include <mips64/archtype.h>
! 85:
! 86: #ifdef DDB
! 87: #include <mips64/db_machdep.h>
! 88: #include <ddb/db_sym.h>
! 89: #endif
! 90:
! 91: #include <sys/cdefs.h>
! 92: #include <sys/syslog.h>
! 93:
! 94: #include "systrace.h"
! 95: #include <dev/systrace.h>
! 96:
! 97: int want_resched; /* resched() was called */
! 98: struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */
! 99:
! 100: char *trap_type[] = {
! 101: "external interrupt",
! 102: "TLB modification",
! 103: "TLB miss (load or instr. fetch)",
! 104: "TLB miss (store)",
! 105: "address error (load or I-fetch)",
! 106: "address error (store)",
! 107: "bus error (I-fetch)",
! 108: "bus error (load or store)",
! 109: "system call",
! 110: "breakpoint",
! 111: "reserved instruction",
! 112: "coprocessor unusable",
! 113: "arithmetic overflow",
! 114: "trap",
! 115: "virtual coherency instruction",
! 116: "floating point",
! 117: "reserved 16",
! 118: "reserved 17",
! 119: "reserved 18",
! 120: "reserved 19",
! 121: "reserved 20",
! 122: "reserved 21",
! 123: "reserved 22",
! 124: "watch",
! 125: "reserved 24",
! 126: "reserved 25",
! 127: "reserved 26",
! 128: "reserved 27",
! 129: "reserved 28",
! 130: "reserved 29",
! 131: "reserved 30",
! 132: "virtual coherency data",
! 133: };
! 134:
! 135: #if defined(DDB) || defined(DEBUG)
! 136: extern register_t *tlbtrcptr;
! 137: struct trapdebug trapdebug[TRAPSIZE], *trp = trapdebug;
! 138:
! 139: void stacktrace(struct trap_frame *);
! 140: void logstacktrace(struct trap_frame *);
! 141: int kdbpeek(void *);
! 142: /* extern functions printed by name in stack backtraces */
! 143: extern void idle(void);
! 144: #endif /* DDB || DEBUG */
! 145:
! 146: #if defined(DDB)
! 147: int kdb_trap(int, db_regs_t *);
! 148: #endif
! 149:
! 150: extern void MipsSwitchFPState(struct proc *, struct trap_frame *);
! 151: extern void MipsSwitchFPState16(struct proc *, struct trap_frame *);
! 152: extern void MipsFPTrap(u_int, u_int, u_int, union sigval);
! 153:
! 154: void trap(struct trap_frame *);
! 155: #ifdef PTRACE
! 156: int cpu_singlestep(struct proc *);
! 157: #endif
! 158: u_long MipsEmulateBranch(struct trap_frame *, long, int, u_int);
! 159:
! 160: static __inline__ void
! 161: userret(struct proc *p)
! 162: {
! 163: int sig;
! 164:
! 165: /* take pending signals */
! 166: while ((sig = CURSIG(p)) != 0)
! 167: postsig(sig);
! 168:
! 169: p->p_cpu->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri;
! 170: }
! 171:
! 172: /*
! 173: * Handle an exception.
! 174: * In the case of a kernel trap, we return the pc where to resume if
! 175: * pcb_onfault is set, otherwise, return old pc.
! 176: */
! 177: void
! 178: trap(trapframe)
! 179: struct trap_frame *trapframe;
! 180: {
! 181: int type, i;
! 182: unsigned ucode = 0;
! 183: struct proc *p = curproc;
! 184: vm_prot_t ftype;
! 185: extern vaddr_t onfault_table[];
! 186: int onfault;
! 187: int typ = 0;
! 188: union sigval sv;
! 189:
! 190: trapdebug_enter(trapframe, -1);
! 191:
! 192: type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
! 193: if (USERMODE(trapframe->sr)) {
! 194: type |= T_USER;
! 195: }
! 196:
! 197: /*
! 198: * Enable hardware interrupts if they were on before the trap.
! 199: * If it was off disable all (splhigh) so we don't accidently
! 200: * enable it when doing a spllower().
! 201: */
! 202: if (trapframe->sr & SR_INT_ENAB) {
! 203: if (type != T_BREAK) {
! 204: #ifndef IMASK_EXTERNAL
! 205: updateimask(trapframe->cpl);
! 206: #endif
! 207: enableintr();
! 208: }
! 209: } else
! 210: splhigh();
! 211:
! 212:
! 213: switch (type) {
! 214: case T_TLB_MOD:
! 215: /* check for kernel address */
! 216: if (trapframe->badvaddr < 0) {
! 217: pt_entry_t *pte;
! 218: unsigned int entry;
! 219: paddr_t pa;
! 220: vm_page_t pg;
! 221:
! 222: pte = kvtopte(trapframe->badvaddr);
! 223: entry = pte->pt_entry;
! 224: #ifdef DIAGNOSTIC
! 225: if (!(entry & PG_V) || (entry & PG_M))
! 226: panic("trap: ktlbmod: invalid pte");
! 227: #endif
! 228: if (pmap_is_page_ro(pmap_kernel(),
! 229: trunc_page(trapframe->badvaddr), entry)) {
! 230: /* write to read only page in the kernel */
! 231: ftype = VM_PROT_WRITE;
! 232: goto kernel_fault;
! 233: }
! 234: entry |= PG_M;
! 235: pte->pt_entry = entry;
! 236: tlb_update(trapframe->badvaddr & ~PGOFSET, entry);
! 237: pa = pfn_to_pad(entry);
! 238: pg = PHYS_TO_VM_PAGE(pa);
! 239: if (pg == NULL)
! 240: panic("trap: ktlbmod: unmanaged page");
! 241: pmap_set_modify(pg);
! 242: return;
! 243: }
! 244: /* FALLTHROUGH */
! 245:
! 246: case T_TLB_MOD+T_USER:
! 247: {
! 248: pt_entry_t *pte;
! 249: unsigned int entry;
! 250: paddr_t pa;
! 251: vm_page_t pg;
! 252: pmap_t pmap = p->p_vmspace->vm_map.pmap;
! 253:
! 254: if (!(pte = pmap_segmap(pmap, trapframe->badvaddr)))
! 255: panic("trap: utlbmod: invalid segmap");
! 256: pte += uvtopte(trapframe->badvaddr);
! 257: entry = pte->pt_entry;
! 258: #ifdef DIAGNOSTIC
! 259: if (!(entry & PG_V) || (entry & PG_M))
! 260: panic("trap: utlbmod: invalid pte");
! 261: #endif
! 262: if (pmap_is_page_ro(pmap,
! 263: trunc_page(trapframe->badvaddr), entry)) {
! 264: /* write to read only page */
! 265: ftype = VM_PROT_WRITE;
! 266: goto fault_common;
! 267: }
! 268: entry |= PG_M;
! 269: pte->pt_entry = entry;
! 270: tlb_update((trapframe->badvaddr & ~PGOFSET) |
! 271: (pmap->pm_tlbpid << VMTLB_PID_SHIFT), entry);
! 272: pa = pfn_to_pad(entry);
! 273: pg = PHYS_TO_VM_PAGE(pa);
! 274: if (pg == NULL)
! 275: panic("trap: utlbmod: unmanaged page");
! 276: pmap_set_modify(pg);
! 277: if (!USERMODE(trapframe->sr))
! 278: return;
! 279: goto out;
! 280: }
! 281:
! 282: case T_TLB_LD_MISS:
! 283: case T_TLB_ST_MISS:
! 284: ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
! 285: /* check for kernel address */
! 286: if (trapframe->badvaddr < 0) {
! 287: vaddr_t va;
! 288: int rv;
! 289:
! 290: kernel_fault:
! 291: va = trunc_page((vaddr_t)trapframe->badvaddr);
! 292: onfault = p->p_addr->u_pcb.pcb_onfault;
! 293: p->p_addr->u_pcb.pcb_onfault = 0;
! 294: rv = uvm_fault(kernel_map, trunc_page(va), 0, ftype);
! 295: p->p_addr->u_pcb.pcb_onfault = onfault;
! 296: if (rv == 0)
! 297: return;
! 298: if (onfault != 0) {
! 299: p->p_addr->u_pcb.pcb_onfault = 0;
! 300: trapframe->pc = onfault_table[onfault];
! 301: return;
! 302: }
! 303: goto err;
! 304: }
! 305: /*
! 306: * It is an error for the kernel to access user space except
! 307: * through the copyin/copyout routines.
! 308: */
! 309: #if 0
! 310: /*
! 311: * However we allow accesses to the top of user stack for
! 312: * compat emul data.
! 313: */
! 314: #define szsigcode ((long)(p->p_emul->e_esigcode - p->p_emul->e_sigcode))
! 315: if (trapframe->badvaddr < VM_MAXUSER_ADDRESS &&
! 316: trapframe->badvaddr >= (long)STACKGAPBASE)
! 317: goto fault_common;
! 318: #undef szsigcode
! 319: #endif
! 320:
! 321: if (p->p_addr->u_pcb.pcb_onfault != 0) {
! 322: /*
! 323: * We want to resolve the TLB fault before invoking
! 324: * pcb_onfault if necessary.
! 325: */
! 326: goto fault_common;
! 327: } else {
! 328: goto err;
! 329: }
! 330:
! 331: case T_TLB_LD_MISS+T_USER:
! 332: ftype = VM_PROT_READ;
! 333: goto fault_common;
! 334:
! 335: case T_TLB_ST_MISS+T_USER:
! 336: ftype = VM_PROT_WRITE;
! 337: fault_common:
! 338: {
! 339: vaddr_t va;
! 340: struct vmspace *vm;
! 341: vm_map_t map;
! 342: int rv;
! 343:
! 344: vm = p->p_vmspace;
! 345: map = &vm->vm_map;
! 346: va = trunc_page((vaddr_t)trapframe->badvaddr);
! 347:
! 348: onfault = p->p_addr->u_pcb.pcb_onfault;
! 349: p->p_addr->u_pcb.pcb_onfault = 0;
! 350: rv = uvm_fault(map, trunc_page(va), 0, ftype);
! 351: p->p_addr->u_pcb.pcb_onfault = onfault;
! 352:
! 353: /*
! 354: * If this was a stack access we keep track of the maximum
! 355: * accessed stack size. Also, if vm_fault gets a protection
! 356: * failure it is due to accessing the stack region outside
! 357: * the current limit and we need to reflect that as an access
! 358: * error.
! 359: */
! 360: if ((caddr_t)va >= vm->vm_maxsaddr) {
! 361: if (rv == 0)
! 362: uvm_grow(p, va);
! 363: else if (rv == EACCES)
! 364: rv = EFAULT;
! 365: }
! 366: if (rv == 0) {
! 367: if (!USERMODE(trapframe->sr))
! 368: return;
! 369: goto out;
! 370: }
! 371: if (!USERMODE(trapframe->sr)) {
! 372: if (onfault != 0) {
! 373: p->p_addr->u_pcb.pcb_onfault = 0;
! 374: trapframe->pc = onfault_table[onfault];
! 375: return;
! 376: }
! 377: goto err;
! 378: }
! 379:
! 380: #ifdef ADEBUG
! 381: printf("SIG-SEGV @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
! 382: #endif
! 383: ucode = ftype;
! 384: i = SIGSEGV;
! 385: typ = SEGV_MAPERR;
! 386: break;
! 387: }
! 388:
! 389: case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
! 390: case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
! 391: ucode = 0; /* XXX should be VM_PROT_something */
! 392: i = SIGBUS;
! 393: typ = BUS_ADRALN;
! 394: #ifdef ADEBUG
! 395: printf("SIG-BUSA @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
! 396: #endif
! 397: break;
! 398: case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */
! 399: case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */
! 400: ucode = 0; /* XXX should be VM_PROT_something */
! 401: i = SIGBUS;
! 402: typ = BUS_OBJERR;
! 403: #ifdef ADEBUG
! 404: printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
! 405: #endif
! 406: break;
! 407:
! 408: case T_SYSCALL+T_USER:
! 409: {
! 410: struct trap_frame *locr0 = p->p_md.md_regs;
! 411: struct sysent *callp;
! 412: unsigned int code;
! 413: unsigned long tpc;
! 414: int numsys;
! 415: struct args {
! 416: register_t i[8];
! 417: } args;
! 418: register_t rval[2];
! 419:
! 420: uvmexp.syscalls++;
! 421:
! 422: /* compute next PC after syscall instruction */
! 423: tpc = trapframe->pc; /* Remember if restart */
! 424: if ((int)trapframe->cause & CR_BR_DELAY) {
! 425: locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 0);
! 426: }
! 427: else {
! 428: locr0->pc += 4;
! 429: }
! 430: callp = p->p_emul->e_sysent;
! 431: numsys = p->p_emul->e_nsysent;
! 432: code = locr0->v0;
! 433: switch (code) {
! 434: case SYS_syscall:
! 435: /*
! 436: * Code is first argument, followed by actual args.
! 437: */
! 438: code = locr0->a0;
! 439: if (code >= numsys)
! 440: callp += p->p_emul->e_nosys; /* (illegal) */
! 441: else
! 442: callp += code;
! 443: i = callp->sy_argsize / sizeof(register_t);
! 444: args.i[0] = locr0->a1;
! 445: args.i[1] = locr0->a2;
! 446: args.i[2] = locr0->a3;
! 447: if (i > 3) {
! 448: if (p->p_md.md_flags & MDP_O32) {
! 449: int32_t p[5];
! 450:
! 451: i = copyin((int32_t *)locr0->sp + 4,
! 452: p, 5 * sizeof(int32_t));
! 453: args.i[3] = p[0];
! 454: args.i[4] = p[1];
! 455: args.i[5] = p[2];
! 456: args.i[6] = p[3];
! 457: args.i[7] = p[4];
! 458: } else {
! 459: args.i[3] = locr0->a4;
! 460: args.i[4] = locr0->a5;
! 461: args.i[5] = locr0->a6;
! 462: args.i[6] = locr0->a7;
! 463: i = copyin((void *)locr0->sp,
! 464: &args.i[7], sizeof(register_t));
! 465: }
! 466: }
! 467: break;
! 468:
! 469: case SYS___syscall:
! 470: /*
! 471: * Like syscall, but code is a quad, so as to maintain
! 472: * quad alignment for the rest of the arguments.
! 473: */
! 474: if (p->p_md.md_flags & MDP_O32) {
! 475: if (_QUAD_LOWWORD == 0) {
! 476: code = locr0->a0;
! 477: } else {
! 478: code = locr0->a1;
! 479: }
! 480: args.i[0] = locr0->a2;
! 481: args.i[1] = locr0->a3;
! 482: } else {
! 483: code = locr0->a0;
! 484: args.i[0] = locr0->a1;
! 485: args.i[1] = locr0->a2;
! 486: args.i[2] = locr0->a3;
! 487: }
! 488:
! 489: if (code >= numsys)
! 490: callp += p->p_emul->e_nosys; /* (illegal) */
! 491: else
! 492: callp += code;
! 493: i = callp->sy_argsize / sizeof(int);
! 494: if (i > 2 && p->p_md.md_flags & MDP_O32) {
! 495: int32_t p[6];
! 496:
! 497: i = copyin((int32_t *)locr0->sp + 4,
! 498: p, 6 * sizeof(int32_t));
! 499: args.i[2] = p[0];
! 500: args.i[3] = p[1];
! 501: args.i[4] = p[2];
! 502: args.i[5] = p[3];
! 503: args.i[6] = p[4];
! 504: args.i[7] = p[5];
! 505: } else if (i > 3) {
! 506: args.i[3] = locr0->a4;
! 507: args.i[4] = locr0->a5;
! 508: args.i[5] = locr0->a6;
! 509: args.i[6] = locr0->a7;
! 510: i = copyin((void *)locr0->sp, &args.i[7],
! 511: sizeof(register_t));
! 512: }
! 513: break;
! 514:
! 515: default:
! 516: if (code >= numsys)
! 517: callp += p->p_emul->e_nosys; /* (illegal) */
! 518: else
! 519: callp += code;
! 520:
! 521: i = callp->sy_narg;
! 522: args.i[0] = locr0->a0;
! 523: args.i[1] = locr0->a1;
! 524: args.i[2] = locr0->a2;
! 525: args.i[3] = locr0->a3;
! 526: if (i > 4) {
! 527: if (p->p_md.md_flags & MDP_O32) {
! 528: int32_t p[4];
! 529:
! 530: i = copyin((int32_t *)locr0->sp + 4,
! 531: p, 4 * sizeof(int32_t));
! 532: args.i[4] = p[0];
! 533: args.i[5] = p[1];
! 534: args.i[6] = p[2];
! 535: args.i[7] = p[3];
! 536: } else {
! 537: args.i[4] = locr0->a4;
! 538: args.i[5] = locr0->a5;
! 539: args.i[6] = locr0->a6;
! 540: args.i[7] = locr0->a7;
! 541: }
! 542: }
! 543: }
! 544: #ifdef SYSCALL_DEBUG
! 545: scdebug_call(p, code, args.i);
! 546: #endif
! 547: #ifdef KTRACE
! 548: if (KTRPOINT(p, KTR_SYSCALL))
! 549: ktrsyscall(p, code, callp->sy_argsize, args.i);
! 550: #endif
! 551: rval[0] = 0;
! 552: rval[1] = locr0->v1;
! 553: #if defined(DDB) || defined(DEBUG)
! 554: if (trp == trapdebug)
! 555: trapdebug[TRAPSIZE - 1].code = code;
! 556: else
! 557: trp[-1].code = code;
! 558: #endif
! 559: #if NSYSTRACE > 0
! 560: if (ISSET(p->p_flag, P_SYSTRACE))
! 561: i = systrace_redirect(code, p, args.i, rval);
! 562: else
! 563: #endif
! 564: i = (*callp->sy_call)(p, &args, rval);
! 565:
! 566: switch (i) {
! 567: case 0:
! 568: locr0->v0 = rval[0];
! 569: locr0->v1 = rval[1];
! 570: locr0->a3 = 0;
! 571: break;
! 572:
! 573: case ERESTART:
! 574: locr0->pc = tpc;
! 575: break;
! 576:
! 577: case EJUSTRETURN:
! 578: break; /* nothing to do */
! 579:
! 580: default:
! 581: locr0->v0 = i;
! 582: locr0->a3 = 1;
! 583: }
! 584: if (code == SYS_ptrace)
! 585: Mips_SyncCache();
! 586: #ifdef SYSCALL_DEBUG
! 587: scdebug_ret(p, code, i, rval);
! 588: #endif
! 589: #ifdef KTRACE
! 590: if (KTRPOINT(p, KTR_SYSRET))
! 591: ktrsysret(p, code, i, rval[0]);
! 592: #endif
! 593: goto out;
! 594: }
! 595:
! 596: #ifdef DDB
! 597: case T_BREAK:
! 598: kdb_trap(type, trapframe);
! 599: return;
! 600: #endif
! 601:
! 602: case T_BREAK+T_USER:
! 603: {
! 604: caddr_t va;
! 605: u_int32_t instr;
! 606: struct trap_frame *locr0 = p->p_md.md_regs;
! 607:
! 608: /* compute address of break instruction */
! 609: va = (caddr_t)trapframe->pc;
! 610: if ((int)trapframe->cause & CR_BR_DELAY)
! 611: va += 4;
! 612:
! 613: /* read break instruction */
! 614: copyin(va, &instr, sizeof(int32_t));
! 615:
! 616: #if 0
! 617: printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
! 618: p->p_comm, p->p_pid, instr, trapframe->pc,
! 619: p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
! 620: #endif
! 621:
! 622: switch ((instr & BREAK_VAL_MASK) >> BREAK_VAL_SHIFT) {
! 623: case 6: /* gcc range error */
! 624: i = SIGFPE;
! 625: typ = FPE_FLTSUB;
! 626: /* skip instruction */
! 627: if ((int)trapframe->cause & CR_BR_DELAY)
! 628: locr0->pc = MipsEmulateBranch(locr0,
! 629: trapframe->pc, 0, 0);
! 630: else
! 631: locr0->pc += 4;
! 632: break;
! 633: case 7: /* gcc divide by zero */
! 634: i = SIGFPE;
! 635: typ = FPE_FLTDIV; /* XXX FPE_INTDIV ? */
! 636: /* skip instruction */
! 637: if ((int)trapframe->cause & CR_BR_DELAY)
! 638: locr0->pc = MipsEmulateBranch(locr0,
! 639: trapframe->pc, 0, 0);
! 640: else
! 641: locr0->pc += 4;
! 642: break;
! 643: #ifdef PTRACE
! 644: case BREAK_SSTEP_VAL:
! 645: if (p->p_md.md_ss_addr == (long)va) {
! 646: struct uio uio;
! 647: struct iovec iov;
! 648: int error;
! 649:
! 650: /*
! 651: * Restore original instruction and clear BP
! 652: */
! 653: iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
! 654: iov.iov_len = sizeof(int);
! 655: uio.uio_iov = &iov;
! 656: uio.uio_iovcnt = 1;
! 657: uio.uio_offset = (off_t)(long)va;
! 658: uio.uio_resid = sizeof(int);
! 659: uio.uio_segflg = UIO_SYSSPACE;
! 660: uio.uio_rw = UIO_WRITE;
! 661: uio.uio_procp = curproc;
! 662: error = process_domem(curproc, p, &uio,
! 663: PT_WRITE_I);
! 664: Mips_SyncCache();
! 665:
! 666: if (error)
! 667: printf("Warning: can't restore instruction at %x: %x\n",
! 668: p->p_md.md_ss_addr,
! 669: p->p_md.md_ss_instr);
! 670:
! 671: p->p_md.md_ss_addr = 0;
! 672: typ = TRAP_BRKPT;
! 673: } else {
! 674: typ = TRAP_TRACE;
! 675: }
! 676: i = SIGTRAP;
! 677: break;
! 678: #endif
! 679: default:
! 680: typ = TRAP_TRACE;
! 681: i = SIGTRAP;
! 682: break;
! 683: }
! 684:
! 685: break;
! 686: }
! 687:
! 688: case T_IWATCH+T_USER:
! 689: case T_DWATCH+T_USER:
! 690: {
! 691: caddr_t va;
! 692: /* compute address of trapped instruction */
! 693: va = (caddr_t)trapframe->pc;
! 694: if ((int)trapframe->cause & CR_BR_DELAY)
! 695: va += 4;
! 696: printf("watch exception @ %p\n", va);
! 697: if (rm7k_watchintr(trapframe)) {
! 698: /* Return to user, don't add any more overhead */
! 699: return;
! 700: }
! 701: i = SIGTRAP;
! 702: typ = TRAP_BRKPT;
! 703: break;
! 704: }
! 705:
! 706: case T_TRAP+T_USER:
! 707: {
! 708: caddr_t va;
! 709: u_int32_t instr;
! 710: struct trap_frame *locr0 = p->p_md.md_regs;
! 711:
! 712: /* compute address of trap instruction */
! 713: va = (caddr_t)trapframe->pc;
! 714: if ((int)trapframe->cause & CR_BR_DELAY)
! 715: va += 4;
! 716: /* read break instruction */
! 717: copyin(va, &instr, sizeof(int32_t));
! 718:
! 719: if ((int)trapframe->cause & CR_BR_DELAY) {
! 720: locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0, 0);
! 721: } else {
! 722: locr0->pc += 4;
! 723: }
! 724: if (instr == 0x040c0000) { /* Performance cntr trap */
! 725: int result;
! 726:
! 727: result = rm7k_perfcntr(trapframe->a0, trapframe->a1,
! 728: trapframe->a2, trapframe->a3);
! 729: locr0->v0 = -result;
! 730: /* Return to user, don't add any more overhead */
! 731: return;
! 732: }
! 733: else {
! 734: i = SIGEMT; /* Stuff it with something for now */
! 735: typ = 0;
! 736: }
! 737: break;
! 738: }
! 739:
! 740: case T_RES_INST+T_USER:
! 741: i = SIGILL;
! 742: typ = ILL_ILLOPC;
! 743: break;
! 744:
! 745: case T_COP_UNUSABLE+T_USER:
! 746: if ((trapframe->cause & CR_COP_ERR) != 0x10000000) {
! 747: i = SIGILL; /* only FPU instructions allowed */
! 748: typ = ILL_ILLOPC;
! 749: break;
! 750: }
! 751:
! 752: if (p->p_md.md_regs->sr & SR_FR_32)
! 753: MipsSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
! 754: else
! 755: MipsSwitchFPState16(machFPCurProcPtr, p->p_md.md_regs);
! 756:
! 757: machFPCurProcPtr = p;
! 758: p->p_md.md_regs->sr |= SR_COP_1_BIT;
! 759: p->p_md.md_flags |= MDP_FPUSED;
! 760: goto out;
! 761:
! 762: case T_FPE:
! 763: printf("FPU Trap: PC %x CR %x SR %x\n",
! 764: trapframe->pc, trapframe->cause, trapframe->sr);
! 765: goto err;
! 766:
! 767: case T_FPE+T_USER:
! 768: sv.sival_ptr = (void *)trapframe->pc;
! 769: MipsFPTrap(trapframe->sr, trapframe->cause, trapframe->pc, sv);
! 770: goto out;
! 771:
! 772: case T_OVFLOW+T_USER:
! 773: i = SIGFPE;
! 774: typ = FPE_FLTOVF;
! 775: break;
! 776:
! 777: case T_ADDR_ERR_LD: /* misaligned access */
! 778: case T_ADDR_ERR_ST: /* misaligned access */
! 779: case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
! 780: if ((onfault = p->p_addr->u_pcb.pcb_onfault) != 0) {
! 781: p->p_addr->u_pcb.pcb_onfault = 0;
! 782: trapframe->pc = onfault_table[onfault];
! 783: return;
! 784: }
! 785: goto err;
! 786:
! 787: default:
! 788: err:
! 789: disableintr();
! 790: #if !defined(DDB) && defined(DEBUG)
! 791: trapDump("trap");
! 792: #endif
! 793: printf("\nTrap cause = %d Frame %p\n", type, trapframe);
! 794: printf("Trap PC %p RA %p fault %p\n",
! 795: trapframe->pc, trapframe->ra, trapframe->badvaddr);
! 796: #ifdef DDB
! 797: stacktrace(!USERMODE(trapframe->sr) ? trapframe : p->p_md.md_regs);
! 798: kdb_trap(type, trapframe);
! 799: #endif
! 800: panic("trap");
! 801: }
! 802: p->p_md.md_regs->pc = trapframe->pc;
! 803: p->p_md.md_regs->cause = trapframe->cause;
! 804: p->p_md.md_regs->badvaddr = trapframe->badvaddr;
! 805: sv.sival_ptr = (void *)trapframe->badvaddr;
! 806: trapsignal(p, i, ucode, typ, sv);
! 807: out:
! 808: /*
! 809: * Note: we should only get here if returning to user mode.
! 810: */
! 811: userret(p);
! 812: }
! 813:
! 814: void
! 815: child_return(arg)
! 816: void *arg;
! 817: {
! 818: struct proc *p = arg;
! 819: struct trap_frame *trapframe;
! 820:
! 821: trapframe = p->p_md.md_regs;
! 822: trapframe->v0 = 0;
! 823: trapframe->v1 = 1;
! 824: trapframe->a3 = 0;
! 825:
! 826: userret(p);
! 827:
! 828: #ifdef KTRACE
! 829: if (KTRPOINT(p, KTR_SYSRET))
! 830: ktrsysret(p,
! 831: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
! 832: #endif
! 833: }
! 834:
! 835: #if defined(DDB) || defined(DEBUG)
! 836: void
! 837: trapDump(msg)
! 838: char *msg;
! 839: {
! 840: struct trapdebug *ptrp;
! 841: int i;
! 842: int s;
! 843:
! 844: s = splhigh();
! 845: ptrp = trp;
! 846: printf("trapDump(%s)\n", msg);
! 847: for (i = 0; i < TRAPSIZE; i++) {
! 848: if (ptrp == trapdebug) {
! 849: ptrp = &trapdebug[TRAPSIZE - 1];
! 850: }
! 851: else {
! 852: ptrp--;
! 853: }
! 854:
! 855: if (ptrp->cause == 0)
! 856: break;
! 857:
! 858: printf("%s: PC %p CR 0x%x SR 0x%x\n",
! 859: trap_type[(ptrp->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT],
! 860: ptrp->pc, ptrp->cause, ptrp->status);
! 861:
! 862: printf(" RA %p SP %p ADR %p\n", ptrp->ra, ptrp->sp, ptrp->vadr);
! 863: }
! 864:
! 865: splx(s);
! 866: }
! 867: #endif
! 868:
! 869:
! 870: /*
! 871: * Return the resulting PC as if the branch was executed.
! 872: */
! 873: unsigned long
! 874: MipsEmulateBranch(framePtr, instPC, fpcCSR, curinst)
! 875: struct trap_frame *framePtr;
! 876: long instPC;
! 877: int fpcCSR;
! 878: u_int curinst;
! 879: {
! 880: InstFmt inst;
! 881: unsigned long retAddr;
! 882: int condition;
! 883: register_t *regsPtr = (register_t *)framePtr;
! 884:
! 885: #define GetBranchDest(InstPtr, inst) \
! 886: ((unsigned long)InstPtr + 4 + ((short)inst.IType.imm << 2))
! 887:
! 888:
! 889: if (curinst) {
! 890: inst = *(InstFmt *)&curinst;
! 891: }
! 892: else {
! 893: inst = *(InstFmt *)instPC;
! 894: }
! 895: #if 0
! 896: printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
! 897: inst.word, fpcCSR); /* XXX */
! 898: #endif
! 899: regsPtr[ZERO] = 0; /* Make sure zero is 0x0 */
! 900:
! 901: switch ((int)inst.JType.op) {
! 902: case OP_SPECIAL:
! 903: switch ((int)inst.RType.func) {
! 904: case OP_JR:
! 905: case OP_JALR:
! 906: retAddr = regsPtr[inst.RType.rs];
! 907: break;
! 908:
! 909: default:
! 910: retAddr = instPC + 4;
! 911: break;
! 912: }
! 913: break;
! 914:
! 915: case OP_BCOND:
! 916: switch ((int)inst.IType.rt) {
! 917: case OP_BLTZ:
! 918: case OP_BLTZL:
! 919: case OP_BLTZAL:
! 920: case OP_BLTZALL:
! 921: if ((int)(regsPtr[inst.RType.rs]) < 0)
! 922: retAddr = GetBranchDest(instPC, inst);
! 923: else
! 924: retAddr = instPC + 8;
! 925: break;
! 926:
! 927: case OP_BGEZ:
! 928: case OP_BGEZL:
! 929: case OP_BGEZAL:
! 930: case OP_BGEZALL:
! 931: if ((int)(regsPtr[inst.RType.rs]) >= 0)
! 932: retAddr = GetBranchDest(instPC, inst);
! 933: else
! 934: retAddr = instPC + 8;
! 935: break;
! 936:
! 937: case OP_TGEI:
! 938: case OP_TGEIU:
! 939: case OP_TLTI:
! 940: case OP_TLTIU:
! 941: case OP_TEQI:
! 942: case OP_TNEI:
! 943: retAddr = instPC + 4; /* Like syscall... */
! 944: break;
! 945:
! 946: default:
! 947: panic("MipsEmulateBranch: Bad branch cond");
! 948: }
! 949: break;
! 950:
! 951: case OP_J:
! 952: case OP_JAL:
! 953: retAddr = (inst.JType.target << 2) | (instPC & ~0x0fffffff);
! 954: break;
! 955:
! 956: case OP_BEQ:
! 957: case OP_BEQL:
! 958: if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
! 959: retAddr = GetBranchDest(instPC, inst);
! 960: else
! 961: retAddr = instPC + 8;
! 962: break;
! 963:
! 964: case OP_BNE:
! 965: case OP_BNEL:
! 966: if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
! 967: retAddr = GetBranchDest(instPC, inst);
! 968: else
! 969: retAddr = instPC + 8;
! 970: break;
! 971:
! 972: case OP_BLEZ:
! 973: case OP_BLEZL:
! 974: if ((int)(regsPtr[inst.RType.rs]) <= 0)
! 975: retAddr = GetBranchDest(instPC, inst);
! 976: else
! 977: retAddr = instPC + 8;
! 978: break;
! 979:
! 980: case OP_BGTZ:
! 981: case OP_BGTZL:
! 982: if ((int)(regsPtr[inst.RType.rs]) > 0)
! 983: retAddr = GetBranchDest(instPC, inst);
! 984: else
! 985: retAddr = instPC + 8;
! 986: break;
! 987:
! 988: case OP_COP1:
! 989: switch (inst.RType.rs) {
! 990: case OP_BCx:
! 991: case OP_BCy:
! 992: if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
! 993: condition = fpcCSR & FPC_COND_BIT;
! 994: else
! 995: condition = !(fpcCSR & FPC_COND_BIT);
! 996: if (condition)
! 997: retAddr = GetBranchDest(instPC, inst);
! 998: else
! 999: retAddr = instPC + 8;
! 1000: break;
! 1001:
! 1002: default:
! 1003: retAddr = instPC + 4;
! 1004: }
! 1005: break;
! 1006:
! 1007: default:
! 1008: retAddr = instPC + 4;
! 1009: }
! 1010: return (retAddr);
! 1011: }
! 1012:
! 1013: #ifdef PTRACE
! 1014:
! 1015: /*
! 1016: * This routine is called by procxmt() to single step one instruction.
! 1017: * We do this by storing a break instruction after the current instruction,
! 1018: * resuming execution, and then restoring the old instruction.
! 1019: */
! 1020: int
! 1021: cpu_singlestep(p)
! 1022: struct proc *p;
! 1023: {
! 1024: vaddr_t va;
! 1025: struct trap_frame *locr0 = p->p_md.md_regs;
! 1026: int error;
! 1027: int bpinstr = BREAK_SSTEP;
! 1028: int curinstr;
! 1029: struct uio uio;
! 1030: struct iovec iov;
! 1031:
! 1032: /*
! 1033: * Fetch what's at the current location.
! 1034: */
! 1035: iov.iov_base = (caddr_t)&curinstr;
! 1036: iov.iov_len = sizeof(int);
! 1037: uio.uio_iov = &iov;
! 1038: uio.uio_iovcnt = 1;
! 1039: uio.uio_offset = (off_t)locr0->pc;
! 1040: uio.uio_resid = sizeof(int);
! 1041: uio.uio_segflg = UIO_SYSSPACE;
! 1042: uio.uio_rw = UIO_READ;
! 1043: uio.uio_procp = curproc;
! 1044: process_domem(curproc, p, &uio, PT_READ_I);
! 1045:
! 1046: /* compute next address after current location */
! 1047: if (curinstr != 0) {
! 1048: va = MipsEmulateBranch(locr0, locr0->pc, locr0->fsr, curinstr);
! 1049: }
! 1050: else {
! 1051: va = locr0->pc + 4;
! 1052: }
! 1053: if (p->p_md.md_ss_addr) {
! 1054: printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
! 1055: p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
! 1056: return (EFAULT);
! 1057: }
! 1058:
! 1059: /*
! 1060: * Fetch what's at the current location.
! 1061: */
! 1062: iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
! 1063: iov.iov_len = sizeof(int);
! 1064: uio.uio_iov = &iov;
! 1065: uio.uio_iovcnt = 1;
! 1066: uio.uio_offset = (off_t)va;
! 1067: uio.uio_resid = sizeof(int);
! 1068: uio.uio_segflg = UIO_SYSSPACE;
! 1069: uio.uio_rw = UIO_READ;
! 1070: uio.uio_procp = curproc;
! 1071: process_domem(curproc, p, &uio, PT_READ_I);
! 1072:
! 1073: /*
! 1074: * Store breakpoint instruction at the "next" location now.
! 1075: */
! 1076: iov.iov_base = (caddr_t)&bpinstr;
! 1077: iov.iov_len = sizeof(int);
! 1078: uio.uio_iov = &iov;
! 1079: uio.uio_iovcnt = 1;
! 1080: uio.uio_offset = (off_t)va;
! 1081: uio.uio_resid = sizeof(int);
! 1082: uio.uio_segflg = UIO_SYSSPACE;
! 1083: uio.uio_rw = UIO_WRITE;
! 1084: uio.uio_procp = curproc;
! 1085: error = process_domem(curproc, p, &uio, PT_WRITE_I);
! 1086: Mips_SyncCache();
! 1087: if (error)
! 1088: return (EFAULT);
! 1089:
! 1090: p->p_md.md_ss_addr = va;
! 1091: #if 0
! 1092: printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
! 1093: p->p_comm, p->p_pid, p->p_md.md_ss_addr,
! 1094: p->p_md.md_ss_instr, locr0[PC], curinstr); /* XXX */
! 1095: #endif
! 1096: return (0);
! 1097: }
! 1098:
! 1099: #endif /* PTRACE */
! 1100:
! 1101: #if defined(DDB) || defined(DEBUG)
! 1102: #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
! 1103:
! 1104: /* forward */
! 1105: #if !defined(DDB)
! 1106: char *fn_name(long addr);
! 1107: #endif
! 1108: void stacktrace_subr(struct trap_frame *, int (*)(const char*, ...));
! 1109:
! 1110: /*
! 1111: * Print a stack backtrace.
! 1112: */
! 1113: void
! 1114: stacktrace(regs)
! 1115: struct trap_frame *regs;
! 1116: {
! 1117: stacktrace_subr(regs, printf);
! 1118: }
! 1119:
! 1120: void
! 1121: logstacktrace(regs)
! 1122: struct trap_frame *regs;
! 1123: {
! 1124: stacktrace_subr(regs, addlog);
! 1125: }
! 1126:
! 1127: void
! 1128: stacktrace_subr(regs, printfn)
! 1129: struct trap_frame *regs;
! 1130: int (*printfn)(const char*, ...);
! 1131: {
! 1132: long pc, sp, fp, ra, va, subr;
! 1133: long a0, a1, a2, a3;
! 1134: unsigned instr, mask;
! 1135: InstFmt i;
! 1136: int more, stksize;
! 1137: extern char edata[];
! 1138: unsigned int frames = 0;
! 1139:
! 1140: /* get initial values from the exception frame */
! 1141: sp = regs->sp;
! 1142: pc = regs->pc;
! 1143: fp = regs->s8;
! 1144: ra = regs->ra; /* May be a 'leaf' function */
! 1145: a0 = regs->a0;
! 1146: a1 = regs->a1;
! 1147: a2 = regs->a2;
! 1148: a3 = regs->a3;
! 1149:
! 1150: /* Jump here when done with a frame, to start a new one */
! 1151: loop:
! 1152:
! 1153: /* Jump here after a nonstandard (interrupt handler) frame */
! 1154: stksize = 0;
! 1155: subr = 0;
! 1156: if (frames++ > 6) {
! 1157: (*printfn)("stackframe count exceeded\n");
! 1158: return;
! 1159: }
! 1160:
! 1161: /* check for bad SP: could foul up next frame */
! 1162: if (sp & 3 || (!IS_XKPHYS((vaddr_t)sp) && sp < KSEG0_BASE)) {
! 1163: (*printfn)("SP %p: not in kernel\n", sp);
! 1164: ra = 0;
! 1165: subr = 0;
! 1166: goto done;
! 1167: }
! 1168:
! 1169: #if 0
! 1170: /* Backtraces should contine through interrupts from kernel mode */
! 1171: if (pc >= (vaddr_t)MipsKernIntr && pc < (vaddr_t)MipsUserIntr) {
! 1172: (*printfn)("MipsKernIntr+%x: (%x, %x ,%x) -------\n",
! 1173: pc-(vaddr_t)MipsKernIntr, a0, a1, a2);
! 1174: regs = (struct trap_frame *)(sp + STAND_ARG_SIZE);
! 1175: a0 = kdbpeek(®s->a0);
! 1176: a1 = kdbpeek(®s->a1);
! 1177: a2 = kdbpeek(®s->a2);
! 1178: a3 = kdbpeek(®s->a3);
! 1179:
! 1180: pc = kdbpeek(®s->pc); /* exc_pc - pc at time of exception */
! 1181: ra = kdbpeek(®s->ra); /* ra at time of exception */
! 1182: sp = kdbpeek(®s->sp);
! 1183: goto specialframe;
! 1184: }
! 1185: #endif
! 1186:
! 1187:
! 1188: # define Between(x, y, z) \
! 1189: ( ((x) <= (y)) && ((y) < (z)) )
! 1190: # define pcBetween(a,b) \
! 1191: Between((vaddr_t)a, pc, (vaddr_t)b)
! 1192:
! 1193: /* check for bad PC */
! 1194: if (pc & 3 || pc < KSEG0_BASE || pc >= (unsigned)edata) {
! 1195: (*printfn)("PC %p: not in kernel\n", pc);
! 1196: ra = 0;
! 1197: goto done;
! 1198: }
! 1199:
! 1200: /*
! 1201: * Find the beginning of the current subroutine by scanning backwards
! 1202: * from the current PC for the end of the previous subroutine.
! 1203: */
! 1204: if (!subr) {
! 1205: va = pc - sizeof(int);
! 1206: while ((instr = kdbpeek((void *)va)) != MIPS_JR_RA)
! 1207: va -= sizeof(int);
! 1208: va += 2 * sizeof(int); /* skip back over branch & delay slot */
! 1209: /* skip over nulls which might separate .o files */
! 1210: while ((instr = kdbpeek((void *)va)) == 0)
! 1211: va += sizeof(int);
! 1212: subr = va;
! 1213: }
! 1214:
! 1215: /*
! 1216: * Jump here for locore entry points for which the preceding
! 1217: * function doesn't end in "j ra"
! 1218: */
! 1219: /* scan forwards to find stack size and any saved registers */
! 1220: stksize = 0;
! 1221: more = 3;
! 1222: mask = 0;
! 1223: for (va = subr; more; va += sizeof(int),
! 1224: more = (more == 3) ? 3 : more - 1) {
! 1225: /* stop if hit our current position */
! 1226: if (va >= pc)
! 1227: break;
! 1228: instr = kdbpeek((void *)va);
! 1229: i.word = instr;
! 1230: switch (i.JType.op) {
! 1231: case OP_SPECIAL:
! 1232: switch (i.RType.func) {
! 1233: case OP_JR:
! 1234: case OP_JALR:
! 1235: more = 2; /* stop after next instruction */
! 1236: break;
! 1237:
! 1238: case OP_SYSCALL:
! 1239: case OP_BREAK:
! 1240: more = 1; /* stop now */
! 1241: };
! 1242: break;
! 1243:
! 1244: case OP_BCOND:
! 1245: case OP_J:
! 1246: case OP_JAL:
! 1247: case OP_BEQ:
! 1248: case OP_BNE:
! 1249: case OP_BLEZ:
! 1250: case OP_BGTZ:
! 1251: more = 2; /* stop after next instruction */
! 1252: break;
! 1253:
! 1254: case OP_COP0:
! 1255: case OP_COP1:
! 1256: case OP_COP2:
! 1257: case OP_COP3:
! 1258: switch (i.RType.rs) {
! 1259: case OP_BCx:
! 1260: case OP_BCy:
! 1261: more = 2; /* stop after next instruction */
! 1262: };
! 1263: break;
! 1264:
! 1265: case OP_SW:
! 1266: case OP_SD:
! 1267: /* look for saved registers on the stack */
! 1268: if (i.IType.rs != 29)
! 1269: break;
! 1270: /* only restore the first one */
! 1271: if (mask & (1 << i.IType.rt))
! 1272: break;
! 1273: mask |= (1 << i.IType.rt);
! 1274: switch (i.IType.rt) {
! 1275: case 4: /* a0 */
! 1276: a0 = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1277: break;
! 1278:
! 1279: case 5: /* a1 */
! 1280: a1 = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1281: break;
! 1282:
! 1283: case 6: /* a2 */
! 1284: a2 = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1285: break;
! 1286:
! 1287: case 7: /* a3 */
! 1288: a3 = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1289: break;
! 1290:
! 1291: case 30: /* fp */
! 1292: fp = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1293: break;
! 1294:
! 1295: case 31: /* ra */
! 1296: ra = kdbpeek((void *)(sp + (short)i.IType.imm));
! 1297: }
! 1298: break;
! 1299:
! 1300: case OP_ADDI:
! 1301: case OP_ADDIU:
! 1302: case OP_DADDI:
! 1303: case OP_DADDIU:
! 1304: /* look for stack pointer adjustment */
! 1305: if (i.IType.rs != 29 || i.IType.rt != 29)
! 1306: break;
! 1307: stksize = - ((short)i.IType.imm);
! 1308: }
! 1309: }
! 1310:
! 1311: done:
! 1312: #ifdef DDB
! 1313: db_printsym(pc, DB_STGY_ANY, printfn);
! 1314: #else
! 1315: (*printfn)("%s+%x", fn_name(subr), pc - subr);
! 1316: #endif
! 1317: if (frames == 1)
! 1318: (*printfn)(" ra %p sp %p (%p,%p,%p,%p)\n",
! 1319: ra, sp, a0, a1, a2, a3);
! 1320: else
! 1321: (*printfn)(" ra %p sp %p\n", ra, sp);
! 1322:
! 1323: if (ra) {
! 1324: if (pc == ra && stksize == 0)
! 1325: (*printfn)("stacktrace: loop!\n");
! 1326: else {
! 1327: pc = ra;
! 1328: sp += stksize;
! 1329: ra = 0;
! 1330: goto loop;
! 1331: }
! 1332: } else {
! 1333: if (curproc)
! 1334: (*printfn)("User-level: pid %d\n", curproc->p_pid);
! 1335: else
! 1336: (*printfn)("User-level: curproc NULL\n");
! 1337: }
! 1338: }
! 1339:
! 1340: #if !defined(DDB)
! 1341: /*
! 1342: * Functions ``special'' enough to print by name
! 1343: */
! 1344: #ifdef __STDC__
! 1345: #define Name(_fn) { (void*)_fn, # _fn }
! 1346: #else
! 1347: #define Name(_fn) { _fn, "_fn"}
! 1348: #endif
! 1349: static struct { void *addr; char *name;} names[] = {
! 1350: Name(trap),
! 1351: {0, 0}
! 1352: };
! 1353:
! 1354: /*
! 1355: * Map a function address to a string name, if known; or a hex string.
! 1356: */
! 1357: char *
! 1358: fn_name(long addr)
! 1359: {
! 1360: static char buf[17];
! 1361: int i = 0;
! 1362:
! 1363: for (i = 0; names[i].name; i++)
! 1364: if (names[i].addr == (void*)addr)
! 1365: return (names[i].name);
! 1366: snprintf(buf, sizeof(buf), "%x", addr);
! 1367: return (buf);
! 1368: }
! 1369: #endif /* !DDB */
! 1370:
! 1371: #endif /* DDB || DEBUG */
CVSweb