[BACK]Return to trap.c CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

Annotation of sys/arch/mips64/mips64/trap.c, Revision 1.1.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(&regs->a0);
                   1176:                a1 = kdbpeek(&regs->a1);
                   1177:                a2 = kdbpeek(&regs->a2);
                   1178:                a3 = kdbpeek(&regs->a3);
                   1179:
                   1180:                pc = kdbpeek(&regs->pc); /* exc_pc - pc at time of exception */
                   1181:                ra = kdbpeek(&regs->ra); /* ra at time of exception */
                   1182:                sp = kdbpeek(&regs->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