[BACK]Return to trap.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / mips / mips

Annotation of src/sys/arch/mips/mips/trap.c, Revision 1.165.2.8

1.165.2.8! nathanw     1: /*     $NetBSD: trap.c,v 1.165.2.7 2002/04/01 07:41:13 nathanw Exp $   */
1.165.2.2  wdk         2:
                      3: /*
                      4:  * Copyright (c) 1988 University of Utah.
                      5:  * Copyright (c) 1992, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * the Systems Programming Group of the University of Utah Computer
                     10:  * Science Department and Ralph Campbell.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
                     40:  * from: Utah Hdr: trap.c 1.32 91/04/06
                     41:  *
                     42:  *     @(#)trap.c      8.5 (Berkeley) 1/11/94
                     43:  */
                     44:
                     45: #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
                     46:
1.165.2.8! nathanw    47: __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.165.2.7 2002/04/01 07:41:13 nathanw Exp $");
1.165.2.2  wdk        48:
                     49: #include "opt_cputype.h"       /* which mips CPU levels do we support? */
                     50: #include "opt_ktrace.h"
                     51: #include "opt_ddb.h"
                     52: #include "opt_kgdb.h"
                     53:
                     54: #include <sys/param.h>
                     55: #include <sys/systm.h>
                     56: #include <sys/kernel.h>
                     57: #include <sys/proc.h>
                     58: #include <sys/signalvar.h>
                     59: #include <sys/syscall.h>
                     60: #include <sys/user.h>
                     61: #include <sys/buf.h>
                     62: #ifdef KTRACE
                     63: #include <sys/ktrace.h>
                     64: #endif
                     65: #include <sys/savar.h>
                     66:
                     67: #include <mips/cache.h>
                     68: #include <mips/locore.h>
                     69: #include <mips/mips_opcode.h>
                     70:
                     71: #include <uvm/uvm_extern.h>
                     72:
                     73: #include <machine/cpu.h>
                     74: #include <mips/trap.h>
                     75: #include <mips/reg.h>
                     76: #include <mips/regnum.h>                       /* symbolic register indices */
                     77: #include <mips/pte.h>
                     78: #include <mips/psl.h>
                     79: #include <mips/userret.h>
                     80:
                     81: #include <net/netisr.h>
                     82:
                     83: #ifdef DDB
                     84: #include <machine/db_machdep.h>
                     85: #include <ddb/db_sym.h>
                     86: #endif
                     87:
                     88: #ifdef KGDB
                     89: #include <sys/kgdb.h>
                     90: #endif
                     91:
                     92: int want_resched;
                     93:
                     94: const char *trap_type[] = {
                     95:        "external interrupt",
                     96:        "TLB modification",
                     97:        "TLB miss (load or instr. fetch)",
                     98:        "TLB miss (store)",
                     99:        "address error (load or I-fetch)",
                    100:        "address error (store)",
                    101:        "bus error (I-fetch)",
                    102:        "bus error (load or store)",
                    103:        "system call",
                    104:        "breakpoint",
                    105:        "reserved instruction",
                    106:        "coprocessor unusable",
                    107:        "arithmetic overflow",
                    108:        "r4k trap/r3k reserved 13",
                    109:        "r4k virtual coherency instruction/r3k reserved 14",
                    110:        "r4k floating point/ r3k reserved 15",
                    111:        "reserved 16",
                    112:        "reserved 17",
1.165.2.8! nathanw   113:        "mipsNN cp2 exception",
1.165.2.2  wdk       114:        "reserved 19",
                    115:        "reserved 20",
                    116:        "reserved 21",
1.165.2.8! nathanw   117:        "mips64 MDMX",
        !           118:        "r4k watch",
        !           119:        "mipsNN machine check",
1.165.2.2  wdk       120:        "reserved 25",
                    121:        "reserved 26",
                    122:        "reserved 27",
                    123:        "reserved 28",
                    124:        "reserved 29",
1.165.2.8! nathanw   125:        "mipsNN cache error",
1.165.2.2  wdk       126:        "r4000 virtual coherency data",
                    127: };
                    128:
1.165.2.8! nathanw   129: void trap(unsigned, unsigned, unsigned, unsigned, struct trapframe *);
        !           130: void ast(unsigned);
1.165.2.2  wdk       131:
1.165.2.8! nathanw   132: vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned, int);
        !           133: extern void MachEmulateFP(unsigned);
        !           134: extern void MachFPInterrupt(unsigned, unsigned, unsigned, struct frame *);
1.165.2.2  wdk       135:
                    136: #define DELAYBRANCH(x) ((int)(x)<0)
                    137:
                    138: /*
                    139:  * fork syscall returns directly to user process via proc_trampoline,
                    140:  * which will be called the very first time when child gets running.
                    141:  */
                    142: void
                    143: child_return(arg)
                    144:        void *arg;
                    145: {
                    146:        struct lwp *l = arg;
                    147:        struct proc *p = l->l_proc;
                    148:        struct frame *frame = (struct frame *)l->l_md.md_regs;
                    149:
                    150:        frame->f_regs[V0] = 0;
                    151:        frame->f_regs[V1] = 1;
                    152:        frame->f_regs[A3] = 0;
                    153:        userret(l);
                    154: #ifdef KTRACE
                    155:        if (KTRPOINT(p, KTR_SYSRET))
                    156:                ktrsysret(p, SYS_fork, 0, 0);
                    157: #endif
                    158: }
                    159:
1.165.2.8! nathanw   160: #ifdef MIPS3_PLUS
1.165.2.2  wdk       161: #define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
                    162: #else
                    163: #define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
                    164: #endif
                    165: #define KERNLAND(x) ((int)(x) < 0)
                    166:
                    167: /*
                    168:  * Trap is called from locore to handle most types of processor traps.
                    169:  * System calls are broken out for efficiency.  MIPS can handle software
                    170:  * interrupts as a part of real interrupt processing.
                    171:  */
                    172: void
                    173: trap(status, cause, vaddr, opc, frame)
                    174:        unsigned status;
                    175:        unsigned cause;
                    176:        unsigned vaddr;
                    177:        unsigned opc;
                    178:        struct trapframe *frame;
                    179: {
                    180:        int type, sig;
                    181:        int ucode = 0;
                    182:        struct lwp *l = curproc;
1.165.2.3  wdk       183:        struct proc *p;
1.165.2.2  wdk       184:        vm_prot_t ftype;
1.165.2.8! nathanw   185:        extern void fswintrberr(void);
1.165.2.2  wdk       186:
1.165.2.3  wdk       187:        p = l ? l->l_proc : NULL;
1.165.2.2  wdk       188:        uvmexp.traps++;
                    189:        type = TRAPTYPE(cause);
                    190:        if (USERMODE(status))
                    191:                type |= T_USER;
                    192:
                    193:        if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV)) {
                    194:                if (type != T_BREAK) {
                    195: #ifdef IPL_ICU_MASK
                    196:                        spllowersofthigh();
                    197: #else
                    198:                        _splset((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
                    199: #endif
                    200:                }
                    201:        }
                    202:
                    203:        switch (type) {
                    204:        default:
                    205:        dopanic:
                    206:                (void)splhigh();
                    207:                printf("trap: %s in %s mode\n",
                    208:                        trap_type[TRAPTYPE(cause)],
                    209:                        USERMODE(status) ? "user" : "kernel");
                    210:                printf("status=0x%x, cause=0x%x, epc=0x%x, vaddr=0x%x\n",
                    211:                        status, cause, opc, vaddr);
                    212:                if (curproc != NULL)
                    213:                        printf("pid=%d cmd=%s usp=0x%x ",
                    214:                            p->p_pid, p->p_comm,
                    215:                            (int)((struct frame *)l->l_md.md_regs)->f_regs[SP]);
                    216:                else
                    217:                        printf("curproc == NULL ");
                    218:                printf("ksp=0x%x\n", (int)&status);
                    219: #if defined(DDB)
                    220:                kdb_trap(type, (mips_reg_t *) frame);
                    221:                /* XXX force halt XXX */
                    222: #elif defined(KGDB)
                    223:                {
                    224:                        struct frame *f = (struct frame *)&ddb_regs;
                    225:                        extern mips_reg_t kgdb_cause, kgdb_vaddr;
                    226:                        kgdb_cause = cause;
                    227:                        kgdb_vaddr = vaddr;
                    228:
                    229:                        /*
                    230:                         * init global ddb_regs, used in db_interface.c routines
                    231:                         * shared between ddb and gdb. Send ddb_regs to gdb so
                    232:                         * that db_machdep.h macros will work with it, and
                    233:                         * allow gdb to alter the PC.
                    234:                         */
                    235:                        db_set_ddb_regs(type, (mips_reg_t *) frame);
                    236:                        PC_BREAK_ADVANCE(f);
                    237:                        if (kgdb_trap(type, &ddb_regs)) {
                    238:                                ((mips_reg_t *)frame)[21] = f->f_regs[PC];
                    239:                                return;
                    240:                        }
                    241:                }
                    242: #else
                    243:                panic("trap");
                    244: #endif
                    245:                /*NOTREACHED*/
                    246:        case T_TLB_MOD:
                    247:                if (KERNLAND(vaddr)) {
                    248:                        pt_entry_t *pte;
                    249:                        unsigned entry;
                    250:                        paddr_t pa;
                    251:
                    252:                        pte = kvtopte(vaddr);
                    253:                        entry = pte->pt_entry;
                    254:                        if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
                    255:                                panic("ktlbmod: invalid pte");
                    256:                        }
                    257:                        if (entry & mips_pg_ro_bit()) {
                    258:                                /* write to read only page in the kernel */
                    259:                                ftype = VM_PROT_WRITE;
                    260:                                goto kernelfault;
                    261:                        }
                    262:                        entry |= mips_pg_m_bit();
                    263:                        pte->pt_entry = entry;
                    264:                        vaddr &= ~PGOFSET;
                    265:                        MachTLBUpdate(vaddr, entry);
                    266:                        pa = mips_tlbpfn_to_paddr(entry);
                    267:                        if (!IS_VM_PHYSADDR(pa)) {
                    268:                                printf("ktlbmod: va %x pa %llx\n",
                    269:                                    vaddr, (long long)pa);
                    270:                                panic("ktlbmod: unmanaged page");
                    271:                        }
                    272:                        pmap_set_modified(pa);
                    273:                        return; /* KERN */
                    274:                }
                    275:                /*FALLTHROUGH*/
                    276:        case T_TLB_MOD+T_USER:
                    277:            {
                    278:                pt_entry_t *pte;
                    279:                unsigned entry;
                    280:                paddr_t pa;
                    281:                pmap_t pmap;
                    282:
                    283:                pmap  = p->p_vmspace->vm_map.pmap;
                    284:                if (!(pte = pmap_segmap(pmap, vaddr)))
                    285:                        panic("utlbmod: invalid segmap");
                    286:                pte += (vaddr >> PGSHIFT) & (NPTEPG - 1);
                    287:                entry = pte->pt_entry;
                    288:                if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
                    289:                        panic("utlbmod: invalid pte");
                    290:
                    291:                if (entry & mips_pg_ro_bit()) {
                    292:                        /* write to read only page */
                    293:                        ftype = VM_PROT_WRITE;
                    294:                        goto pagefault;
                    295:                }
                    296:                entry |= mips_pg_m_bit();
                    297:                pte->pt_entry = entry;
                    298:                vaddr = (vaddr & ~PGOFSET) |
                    299:                        (pmap->pm_asid << MIPS_TLB_PID_SHIFT);
                    300:                MachTLBUpdate(vaddr, entry);
                    301:                pa = mips_tlbpfn_to_paddr(entry);
                    302:                if (!IS_VM_PHYSADDR(pa)) {
                    303:                        printf("utlbmod: va %x pa %llx\n",
                    304:                            vaddr, (long long)pa);
                    305:                        panic("utlbmod: unmanaged page");
                    306:                }
                    307:                pmap_set_modified(pa);
                    308:                if (type & T_USER)
                    309:                        userret(l);
                    310:                return; /* GEN */
                    311:            }
                    312:        case T_TLB_LD_MISS:
                    313:        case T_TLB_ST_MISS:
                    314:                ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
                    315:                if (KERNLAND(vaddr))
                    316:                        goto kernelfault;
                    317:                /*
                    318:                 * It is an error for the kernel to access user space except
                    319:                 * through the copyin/copyout routines.
                    320:                 */
1.165.2.4  nathanw   321:                if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
1.165.2.2  wdk       322:                        goto dopanic;
                    323:                /* check for fuswintr() or suswintr() getting a page fault */
                    324:                if (l->l_addr->u_pcb.pcb_onfault == (caddr_t)fswintrberr) {
                    325:                        frame->tf_epc = (int)fswintrberr;
                    326:                        return; /* KERN */
                    327:                }
                    328:                goto pagefault;
                    329:        case T_TLB_LD_MISS+T_USER:
                    330:                ftype = VM_PROT_READ;
                    331:                goto pagefault;
                    332:        case T_TLB_ST_MISS+T_USER:
                    333:                ftype = VM_PROT_WRITE;
                    334:        pagefault: ;
                    335:            {
                    336:                vaddr_t va;
                    337:                struct vmspace *vm;
                    338:                struct vm_map *map;
                    339:                int rv;
                    340:
                    341:                vm = p->p_vmspace;
                    342:                map = &vm->vm_map;
                    343:                va = trunc_page(vaddr);
                    344:                rv = uvm_fault(map, va, 0, ftype);
                    345: #ifdef VMFAULT_TRACE
                    346:                printf(
1.165.2.8! nathanw   347:            "uvm_fault(%p (pmap %p), %lx (0x%x), 0, %d) -> %d at pc %p\n",
1.165.2.2  wdk       348:                    map, vm->vm_map.pmap, va, vaddr, ftype, rv, (void*)opc);
                    349: #endif
                    350:                /*
                    351:                 * If this was a stack access we keep track of the maximum
                    352:                 * accessed stack size.  Also, if vm_fault gets a protection
                    353:                 * failure it is due to accessing the stack region outside
                    354:                 * the current limit and we need to reflect that as an access
                    355:                 * error.
                    356:                 */
                    357:                if ((caddr_t)va >= vm->vm_maxsaddr) {
                    358:                        if (rv == 0) {
                    359:                                unsigned nss;
                    360:
                    361:                                nss = btoc(USRSTACK-(unsigned)va);
                    362:                                if (nss > vm->vm_ssize)
                    363:                                        vm->vm_ssize = nss;
                    364:                        }
                    365:                        else if (rv == EACCES)
                    366:                                rv = EFAULT;
                    367:                }
                    368:                if (rv == 0) {
                    369:                        if (type & T_USER) {
                    370:                                userret(l);
                    371:                        }
                    372:                        return; /* GEN */
                    373:                }
                    374:                if ((type & T_USER) == 0)
                    375:                        goto copyfault;
                    376:                if (rv == ENOMEM) {
                    377:                        printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
                    378:                               p->p_pid, p->p_comm,
                    379:                               p->p_cred && p->p_ucred ?
                    380:                               p->p_ucred->cr_uid : -1);
                    381:                        sig = SIGKILL;
                    382:                } else {
                    383:                        sig = (rv == EACCES) ? SIGBUS : SIGSEGV;
                    384:                }
                    385:                ucode = vaddr;
                    386:                break; /* SIGNAL */
                    387:            }
                    388:        kernelfault: ;
                    389:            {
                    390:                vaddr_t va;
                    391:                int rv;
                    392:
                    393:                va = trunc_page(vaddr);
                    394:                rv = uvm_fault(kernel_map, va, 0, ftype);
                    395:                if (rv == 0)
                    396:                        return; /* KERN */
                    397:                /*FALLTHROUGH*/
                    398:            }
                    399:        case T_ADDR_ERR_LD:     /* misaligned access */
                    400:        case T_ADDR_ERR_ST:     /* misaligned access */
                    401:        case T_BUS_ERR_LD_ST:   /* BERR asserted to cpu */
                    402:        copyfault:
1.165.2.4  nathanw   403:                if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
1.165.2.2  wdk       404:                        goto dopanic;
                    405:                frame->tf_epc = (int)l->l_addr->u_pcb.pcb_onfault;
                    406:                return; /* KERN */
                    407:
                    408:        case T_ADDR_ERR_LD+T_USER:      /* misaligned or kseg access */
                    409:        case T_ADDR_ERR_ST+T_USER:      /* misaligned or kseg access */
                    410:        case T_BUS_ERR_IFETCH+T_USER:   /* BERR asserted to cpu */
                    411:        case T_BUS_ERR_LD_ST+T_USER:    /* BERR asserted to cpu */
                    412:                sig = SIGSEGV;
                    413:                ucode = vaddr;
                    414:                break; /* SIGNAL */
                    415:
                    416:        case T_BREAK:
                    417: #if defined(DDB)
                    418:                kdb_trap(type, (mips_reg_t *) frame);
                    419:                return; /* KERN */
                    420: #elif defined(KGDB)
                    421:                {
                    422:                        struct frame *f = (struct frame *)&ddb_regs;
                    423:                        extern mips_reg_t kgdb_cause, kgdb_vaddr;
                    424:                        kgdb_cause = cause;
                    425:                        kgdb_vaddr = vaddr;
                    426:
                    427:                        /*
                    428:                         * init global ddb_regs, used in db_interface.c routines
                    429:                         * shared between ddb and gdb. Send ddb_regs to gdb so
                    430:                         * that db_machdep.h macros will work with it, and
                    431:                         * allow gdb to alter the PC.
                    432:                         */
                    433:                        db_set_ddb_regs(type, (mips_reg_t *) frame);
                    434:                        PC_BREAK_ADVANCE(f);
                    435:                        if (!kgdb_trap(type, &ddb_regs))
                    436:                                printf("kgdb: ignored %s\n",
                    437:                                       trap_type[TRAPTYPE(cause)]);
                    438:                        else
                    439:                                ((mips_reg_t *)frame)[21] = f->f_regs[PC];
                    440:
                    441:                        return;
                    442:                }
                    443: #else
                    444:                goto dopanic;
                    445: #endif
                    446:        case T_BREAK+T_USER:
                    447:            {
                    448:                unsigned va, instr;
                    449:                int rv;
                    450:
                    451:                /* compute address of break instruction */
                    452:                va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc;
                    453:
                    454:                /* read break instruction */
                    455:                instr = fuiword((void *)va);
                    456:
                    457:                if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
                    458:                        sig = SIGTRAP;
                    459:                        break;
                    460:                }
                    461:                /*
                    462:                 * Restore original instruction and clear BP
                    463:                 */
                    464:                rv = suiword((void *)va, l->l_md.md_ss_instr);
                    465:                if (rv < 0) {
                    466:                        vaddr_t sa, ea;
                    467:                        sa = trunc_page(va);
                    468:                        ea = round_page(va + sizeof(int) - 1);
                    469:                        rv = uvm_map_protect(&p->p_vmspace->vm_map,
                    470:                                sa, ea, VM_PROT_DEFAULT, FALSE);
                    471:                        if (rv == 0) {
                    472:                                rv = suiword((void *)va, MIPS_BREAK_SSTEP);
                    473:                                (void)uvm_map_protect(&p->p_vmspace->vm_map,
                    474:                                sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
                    475:                        }
                    476:                }
                    477:                mips_icache_sync_all();         /* XXXJRT -- necessary? */
                    478:                mips_dcache_wbinv_all();        /* XXXJRT -- necessary? */
                    479:
                    480:                if (rv < 0)
                    481:                        printf("Warning: can't restore instruction at 0x%x: 0x%x\n",
                    482:                                l->l_md.md_ss_addr, l->l_md.md_ss_instr);
                    483:                l->l_md.md_ss_addr = 0;
                    484:                sig = SIGTRAP;
                    485:                break; /* SIGNAL */
                    486:            }
                    487:        case T_RES_INST+T_USER:
                    488: #if defined(MIPS3_5900) && defined(SOFTFLOAT)
                    489:                MachFPInterrupt(status, cause, opc, p->p_md.md_regs);
                    490:                userret(l);
                    491:                return; /* GEN */
                    492: #else
                    493:                sig = SIGILL;
                    494:                break; /* SIGNAL */
                    495: #endif
                    496:                break; /* SIGNAL */
                    497:        case T_COP_UNUSABLE+T_USER:
                    498: #if defined(NOFPU) && !defined(SOFTFLOAT)
                    499:                sig = SIGILL;
                    500:                break; /* SIGNAL */
                    501: #endif
                    502:                if ((cause & MIPS_CR_COP_ERR) != 0x10000000) {
                    503:                        sig = SIGILL;   /* only FPU instructions allowed */
                    504:                        break; /* SIGNAL */
                    505:                }
                    506: #ifndef SOFTFLOAT
                    507:                {
                    508:                struct frame *f;
                    509:
                    510:                f = (struct frame *)l->l_md.md_regs;
                    511:                savefpregs(l);          /* yield FPA */
                    512:                loadfpregs(l);          /* load FPA */
                    513:                fpcurproc = l;
                    514:                l->l_md.md_flags |= MDP_FPUSED;
                    515:                f->f_regs[SR] |= MIPS_SR_COP_1_BIT;
                    516:                }
                    517: #else
                    518:                MachFPInterrupt(status, cause, opc, p->p_md.md_regs);
                    519: #endif
                    520:                userret(l);
                    521:                return; /* GEN */
                    522:        case T_FPE+T_USER:
                    523: #if !defined(NOFPU) || defined(SOFTFLOAT)
                    524:                MachFPInterrupt(status, cause, opc, l->l_md.md_regs);
                    525: #endif
                    526:                userret(l);
                    527:                return; /* GEN */
                    528:        case T_OVFLOW+T_USER:
                    529:        case T_TRAP+T_USER:
                    530:                sig = SIGFPE;
                    531:                break; /* SIGNAL */
                    532:        }
                    533:        ((struct frame *)l->l_md.md_regs)->f_regs[CAUSE] = cause;
                    534:        ((struct frame *)l->l_md.md_regs)->f_regs[BADVADDR] = vaddr;
                    535:        trapsignal(l, sig, ucode);
                    536:        if ((type & T_USER) == 0)
                    537:                panic("trapsignal");
                    538:        userret(l);
                    539:        return;
                    540: }
                    541:
                    542: /*
                    543:  * Software (low priority) network interrupt. i.e. softnet().
                    544:  */
                    545: void
                    546: netintr()
                    547: {
                    548: #define DONETISR(bit, fn)                      \
                    549:        do {                                    \
                    550:                if (n & (1 << bit))             \
                    551:                        fn();                   \
                    552:        } while (0)
                    553:
                    554:        int n;
                    555:        n = netisr; netisr = 0;
                    556:
                    557: #ifdef SOFTNET_INTR            /* XXX TEMPORARY XXX */
                    558:        intrcnt[SOFTNET_INTR]++;
                    559: #endif
                    560:
                    561: #include <net/netisr_dispatch.h>
                    562:
                    563: #undef DONETISR
                    564: }
                    565:
                    566: /*
                    567:  * Handle asynchronous software traps.
                    568:  * This is called from MachUserIntr() either to deliver signals or
                    569:  * to make involuntary context switch (preemption).
                    570:  */
                    571: void
                    572: ast(pc)
                    573:        unsigned pc;            /* program counter where to continue */
                    574: {
                    575:        struct lwp *l = curproc;
                    576:        struct proc *p = l->l_proc;
                    577:        int sig;
                    578:
                    579:        while (p->p_md.md_astpending) {
                    580:                uvmexp.softs++;
                    581:                p->p_md.md_astpending = 0;
                    582:
                    583:                if (p->p_flag & P_OWEUPC) {
                    584:                        p->p_flag &= ~P_OWEUPC;
                    585:                        ADDUPROF(p);
                    586:                }
                    587:
                    588:                /* Take pending signals. */
                    589:                while ((sig = CURSIG(l)) != 0)
                    590:                        postsig(sig);
                    591:
                    592:                if (want_resched) {
                    593:                        /*
                    594:                         * We are being preempted.
                    595:                         */
                    596:                        preempt(NULL);
                    597:                }
                    598:
                    599:                userret(l);
                    600:        }
                    601: }
                    602:
                    603: /*
                    604:  * Analyse 'next' PC address taking account of branch/jump instructions
                    605:  */
                    606: vaddr_t
                    607: MachEmulateBranch(f, instpc, fpuCSR, allowNonBranch)
                    608:        struct frame *f;
                    609:        vaddr_t instpc;
                    610:        unsigned fpuCSR;
                    611:        int allowNonBranch;
                    612: {
                    613: #define        BRANCHTARGET(p) (4 + (p) + ((short)((InstFmt *)(p))->IType.imm << 2))
                    614:        InstFmt inst;
                    615:        vaddr_t nextpc;
                    616:
                    617:        if (instpc < MIPS_KSEG0_START)
                    618:                inst.word = fuiword((void *)instpc);
                    619:        else
                    620:                inst.word = *(unsigned *)instpc;
                    621:
                    622:        switch ((int)inst.JType.op) {
                    623:        case OP_SPECIAL:
                    624:                if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR)
                    625:                        nextpc = f->f_regs[inst.RType.rs];
                    626:                else if (allowNonBranch)
                    627:                        nextpc = instpc + 4;
                    628:                else
                    629:                        panic("MachEmulateBranch: Non-branch");
                    630:                break;
                    631:
                    632:        case OP_BCOND:
                    633:                switch ((int)inst.IType.rt) {
                    634:                case OP_BLTZ:
                    635:                case OP_BLTZAL:
                    636:                case OP_BLTZL:          /* squashed */
                    637:                case OP_BLTZALL:        /* squashed */
                    638:                        if ((int)(f->f_regs[inst.RType.rs]) < 0)
                    639:                                nextpc = BRANCHTARGET(instpc);
                    640:                        else
                    641:                                nextpc = instpc + 8;
                    642:                        break;
                    643:
                    644:                case OP_BGEZ:
                    645:                case OP_BGEZAL:
                    646:                case OP_BGEZL:          /* squashed */
                    647:                case OP_BGEZALL:        /* squashed */
                    648:                        if ((int)(f->f_regs[inst.RType.rs]) >= 0)
                    649:                                nextpc = BRANCHTARGET(instpc);
                    650:                        else
                    651:                                nextpc = instpc + 8;
                    652:                        break;
                    653:
                    654:                default:
                    655:                        panic("MachEmulateBranch: Bad branch cond");
                    656:                }
                    657:                break;
                    658:
                    659:        case OP_J:
                    660:        case OP_JAL:
                    661:                nextpc = (inst.JType.target << 2) |
                    662:                        ((unsigned)instpc & 0xF0000000);
                    663:                break;
                    664:
                    665:        case OP_BEQ:
                    666:        case OP_BEQL:   /* squashed */
                    667:                if (f->f_regs[inst.RType.rs] == f->f_regs[inst.RType.rt])
                    668:                        nextpc = BRANCHTARGET(instpc);
                    669:                else
                    670:                        nextpc = instpc + 8;
                    671:                break;
                    672:
                    673:        case OP_BNE:
                    674:        case OP_BNEL:   /* squashed */
                    675:                if (f->f_regs[inst.RType.rs] != f->f_regs[inst.RType.rt])
                    676:                        nextpc = BRANCHTARGET(instpc);
                    677:                else
                    678:                        nextpc = instpc + 8;
                    679:                break;
                    680:
                    681:        case OP_BLEZ:
                    682:        case OP_BLEZL:  /* squashed */
                    683:                if ((int)(f->f_regs[inst.RType.rs]) <= 0)
                    684:                        nextpc = BRANCHTARGET(instpc);
                    685:                else
                    686:                        nextpc = instpc + 8;
                    687:                break;
                    688:
                    689:        case OP_BGTZ:
                    690:        case OP_BGTZL:  /* squashed */
                    691:                if ((int)(f->f_regs[inst.RType.rs]) > 0)
                    692:                        nextpc = BRANCHTARGET(instpc);
                    693:                else
                    694:                        nextpc = instpc + 8;
                    695:                break;
                    696:
                    697:        case OP_COP1:
                    698:                if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) {
                    699:                        int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0;
                    700:                        if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE)
                    701:                                condition = !condition;
                    702:                        if (condition)
                    703:                                nextpc = BRANCHTARGET(instpc);
                    704:                        else
                    705:                                nextpc = instpc + 8;
                    706:                }
                    707:                else if (allowNonBranch)
                    708:                        nextpc = instpc + 4;
                    709:                else
                    710:                        panic("MachEmulateBranch: Bad COP1 branch instruction");
                    711:                break;
                    712:
                    713:        default:
                    714:                if (!allowNonBranch)
                    715:                        panic("MachEmulateBranch: Non-branch instruction");
                    716:                nextpc = instpc + 4;
                    717:        }
                    718:        return nextpc;
                    719: #undef BRANCHTARGET
                    720: }
                    721:
                    722: /* XXX need to rewrite acient comment XXX
                    723:  * This routine is called by procxmt() to single step one instruction.
                    724:  * We do this by storing a break instruction after the current instruction,
                    725:  * resuming execution, and then restoring the old instruction.
                    726:  */
                    727: int
                    728: mips_singlestep(l)
                    729:        struct lwp *l;
                    730: {
                    731:        struct frame *f = (struct frame *)l->l_md.md_regs;
                    732:        struct proc *p = l->l_proc;
                    733:        vaddr_t pc, va;
                    734:        int rv;
                    735:
                    736:        if (l->l_md.md_ss_addr) {
                    737:                printf("SS %s (%d): breakpoint already set at %x\n",
                    738:                        p->p_comm, p->p_pid, l->l_md.md_ss_addr);
                    739:                return EFAULT;
                    740:        }
                    741:        pc = (vaddr_t)f->f_regs[PC];
                    742:        if (fuiword((void *)pc) != 0) /* not a NOP instruction */
                    743:                va = MachEmulateBranch(f, pc,
1.165.2.7  nathanw   744:                    PCB_FSR(&l->l_addr->u_pcb), 1);
1.165.2.2  wdk       745:        else
                    746:                va = pc + sizeof(int);
                    747:        l->l_md.md_ss_addr = va;
                    748:        l->l_md.md_ss_instr = fuiword((void *)va);
                    749:        rv = suiword((void *)va, MIPS_BREAK_SSTEP);
                    750:        if (rv < 0) {
                    751:                vaddr_t sa, ea;
                    752:                sa = trunc_page(va);
                    753:                ea = round_page(va + sizeof(int) - 1);
                    754:                rv = uvm_map_protect(&p->p_vmspace->vm_map,
                    755:                    sa, ea, VM_PROT_DEFAULT, FALSE);
                    756:                if (rv == 0) {
                    757:                        rv = suiword((void *)va, MIPS_BREAK_SSTEP);
                    758:                        (void)uvm_map_protect(&p->p_vmspace->vm_map,
                    759:                            sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
                    760:                }
                    761:        }
                    762: #if 0
                    763:        printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
                    764:                p->p_comm, p->p_pid, p->p_md.md_ss_addr,
                    765:                p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */
                    766: #endif
                    767:        return 0;
                    768: }
                    769:
                    770:
                    771: #ifndef DDB_TRACE
                    772:
                    773: #if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo)
1.165.2.8! nathanw   774: mips_reg_t kdbrpeek(vaddr_t);
1.165.2.2  wdk       775:
                    776: int
                    777: kdbpeek(addr)
                    778:        vaddr_t addr;
                    779: {
                    780:        int rc;
                    781:        if (addr & 3) {
                    782:                printf("kdbpeek: unaligned address %lx\n", addr);
                    783:                /* We might have been called from DDB, so do not go there. */
                    784:                stacktrace();
                    785:                rc = -1 ;
                    786:        } else if (addr == NULL) {
                    787:                printf("kdbpeek: NULL\n");
                    788:                rc = 0xdeadfeed;
                    789:        } else {
                    790:                rc = *(int *)addr;
                    791:        }
                    792:        return rc;
                    793: }
                    794:
                    795: mips_reg_t
                    796: kdbrpeek(addr)
                    797:        vaddr_t addr;
                    798: {
                    799:        mips_reg_t rc;
                    800:        if (addr & (sizeof(mips_reg_t) - 1)) {
                    801:                printf("kdbrpeek: unaligned address %lx\n", addr);
                    802:                /* We might have been called from DDB, so do not go there. */
                    803:                stacktrace();
                    804:                rc = -1 ;
                    805:        } else if (addr == NULL) {
                    806:                printf("kdbrpeek: NULL\n");
                    807:                rc = 0xdeadfeed;
                    808:        } else {
                    809:                rc = *(mips_reg_t *)addr;
                    810:        }
                    811:        return rc;
                    812: }
                    813:
                    814: extern char start[], edata[], verylocore[];
                    815: extern char mips1_KernGenException[];
                    816: extern char mips1_UserGenException[];
                    817: extern char mips1_KernIntr[];
                    818: extern char mips1_UserIntr[];
                    819: extern char mips1_SystemCall[];
                    820: extern char mips3_KernGenException[];
                    821: extern char mips3_UserGenException[];
                    822: extern char mips3_KernIntr[];
                    823: extern char mips3_UserIntr[];
                    824: extern char mips3_SystemCall[];
1.165.2.8! nathanw   825: extern int main(void *);
        !           826: extern void mips_idle(void);
        !           827: extern void cpu_switch(struct lwp *);
1.165.2.2  wdk       828:
                    829: /*
                    830:  *  stack trace code, also useful to DDB one day
                    831:  */
                    832:
                    833: /* forward */
                    834: char *fn_name(unsigned addr);
1.165.2.8! nathanw   835: void stacktrace_subr(int, int, int, int, u_int, u_int, u_int, u_int,
        !           836:            void (*)(const char*, ...));
1.165.2.2  wdk       837:
                    838: #define        MIPS_JR_RA      0x03e00008      /* instruction code for jr ra */
                    839: #define        MIPS_JR_K0      0x03400008      /* instruction code for jr k0 */
                    840: #define        MIPS_ERET       0x42000018      /* instruction code for eret */
                    841:
                    842: /*
                    843:  * Do a stack backtrace.
                    844:  * (*printfn)()  prints the output to either the system log,
                    845:  * the console, or both.
                    846:  */
                    847: void
                    848: stacktrace_subr(a0, a1, a2, a3, pc, sp, fp, ra, printfn)
                    849:        int a0, a1, a2, a3;
                    850:        u_int  pc, sp, fp, ra;
1.165.2.8! nathanw   851:        void (*printfn)(const char*, ...);
1.165.2.2  wdk       852: {
                    853:        unsigned va, subr;
                    854:        unsigned instr, mask;
                    855:        InstFmt i;
                    856:        int more, stksize;
                    857:        unsigned int frames =  0;
                    858:        int foundframesize = 0;
                    859:
                    860: /* Jump here when done with a frame, to start a new one */
                    861: loop:
                    862:        stksize = 0;
                    863:        subr = 0;
                    864:        if (frames++ > 100) {
                    865:                (*printfn)("\nstackframe count exceeded\n");
                    866:                /* return breaks stackframe-size heuristics with gcc -O2 */
                    867:                goto finish;    /*XXX*/
                    868:        }
                    869:
                    870:        /* check for bad SP: could foul up next frame */
                    871:        if (sp & 3 || sp < 0x80000000) {
                    872:                (*printfn)("SP 0x%x: not in kernel\n", sp);
                    873:                ra = 0;
                    874:                subr = 0;
                    875:                goto done;
                    876:        }
                    877:
                    878:        /* Check for bad PC */
                    879:        if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
                    880:                (*printfn)("PC 0x%x: not in kernel space\n", pc);
                    881:                ra = 0;
                    882:                goto done;
                    883:        }
                    884:
                    885:        /*
                    886:         * Find the beginning of the current subroutine by scanning backwards
                    887:         * from the current PC for the end of the previous subroutine.
                    888:         */
                    889:        va = pc;
                    890:        do {
                    891:                va -= sizeof(int);
                    892:                if (va <= (unsigned)verylocore)
                    893:                        goto finish;
                    894:                instr = kdbpeek(va);
                    895:                if (instr == MIPS_ERET)
                    896:                        goto mips3_eret;
                    897:        } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
                    898:        /* skip back over branch & delay slot */
                    899:        va += sizeof(int);
                    900: mips3_eret:
                    901:        va += sizeof(int);
                    902:        /* skip over nulls which might separate .o files */
                    903:        while ((instr = kdbpeek(va)) == 0)
                    904:                va += sizeof(int);
                    905:        subr = va;
                    906:
                    907:        /* scan forwards to find stack size and any saved registers */
                    908:        stksize = 0;
                    909:        more = 3;
                    910:        mask = 0;
                    911:        foundframesize = 0;
                    912:        for (va = subr; more; va += sizeof(int),
                    913:                              more = (more == 3) ? 3 : more - 1) {
                    914:                /* stop if hit our current position */
                    915:                if (va >= pc)
                    916:                        break;
                    917:                instr = kdbpeek(va);
                    918:                i.word = instr;
                    919:                switch (i.JType.op) {
                    920:                case OP_SPECIAL:
                    921:                        switch (i.RType.func) {
                    922:                        case OP_JR:
                    923:                        case OP_JALR:
                    924:                                more = 2; /* stop after next instruction */
                    925:                                break;
                    926:
                    927:                        case OP_SYSCALL:
                    928:                        case OP_BREAK:
                    929:                                more = 1; /* stop now */
                    930:                        };
                    931:                        break;
                    932:
                    933:                case OP_BCOND:
                    934:                case OP_J:
                    935:                case OP_JAL:
                    936:                case OP_BEQ:
                    937:                case OP_BNE:
                    938:                case OP_BLEZ:
                    939:                case OP_BGTZ:
                    940:                        more = 2; /* stop after next instruction */
                    941:                        break;
                    942:
                    943:                case OP_COP0:
                    944:                case OP_COP1:
                    945:                case OP_COP2:
                    946:                case OP_COP3:
                    947:                        switch (i.RType.rs) {
                    948:                        case OP_BCx:
                    949:                        case OP_BCy:
                    950:                                more = 2; /* stop after next instruction */
                    951:                        };
                    952:                        break;
                    953:
                    954:                case OP_SW:
                    955:                        /* look for saved registers on the stack */
                    956:                        if (i.IType.rs != 29)
                    957:                                break;
                    958:                        /* only restore the first one */
                    959:                        if (mask & (1 << i.IType.rt))
                    960:                                break;
                    961:                        mask |= (1 << i.IType.rt);
                    962:                        switch (i.IType.rt) {
                    963:                        case 4: /* a0 */
                    964:                                a0 = kdbpeek(sp + (short)i.IType.imm);
                    965:                                break;
                    966:
                    967:                        case 5: /* a1 */
                    968:                                a1 = kdbpeek(sp + (short)i.IType.imm);
                    969:                                break;
                    970:
                    971:                        case 6: /* a2 */
                    972:                                a2 = kdbpeek(sp + (short)i.IType.imm);
                    973:                                break;
                    974:
                    975:                        case 7: /* a3 */
                    976:                                a3 = kdbpeek(sp + (short)i.IType.imm);
                    977:                                break;
                    978:
                    979:                        case 30: /* fp */
                    980:                                fp = kdbpeek(sp + (short)i.IType.imm);
                    981:                                break;
                    982:
                    983:                        case 31: /* ra */
                    984:                                ra = kdbpeek(sp + (short)i.IType.imm);
                    985:                        }
                    986:                        break;
                    987:
                    988:                case OP_ADDI:
                    989:                case OP_ADDIU:
                    990:                        /* look for stack pointer adjustment */
                    991:                        if (i.IType.rs != 29 || i.IType.rt != 29)
                    992:                                break;
                    993:                        /* don't count pops for mcount */
                    994:                        if (!foundframesize) {
                    995:                                stksize = - ((short)i.IType.imm);
                    996:                                foundframesize = 1;
                    997:                        }
                    998:                }
                    999:        }
                   1000: done:
                   1001:        (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
                   1002:                fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
                   1003:
                   1004:        if (ra) {
                   1005:                if (pc == ra && stksize == 0)
                   1006:                        (*printfn)("stacktrace: loop!\n");
                   1007:                else {
                   1008:                        pc = ra;
                   1009:                        sp += stksize;
                   1010:                        ra = 0;
                   1011:                        goto loop;
                   1012:                }
                   1013:        } else {
                   1014: finish:
1.165.2.6  gmcgarry 1015:                if (curproc != NULL && curproc->l_proc != NULL)
1.165.2.2  wdk      1016:                        (*printfn)("User-level: pid %d\n",
                   1017:                                curproc->l_proc->p_pid);
                   1018:                else
                   1019:                        (*printfn)("User-level: curproc NULL\n");
                   1020:        }
                   1021: }
                   1022:
                   1023: /*
                   1024:  * Functions ``special'' enough to print by name
                   1025:  */
                   1026: #ifdef __STDC__
                   1027: #define Name(_fn)  { (void*)_fn, # _fn }
                   1028: #else
                   1029: #define Name(_fn) { _fn, "_fn"}
                   1030: #endif
                   1031: static struct { void *addr; char *name;} names[] = {
                   1032:        Name(stacktrace),
                   1033:        Name(stacktrace_subr),
                   1034:        Name(main),
                   1035:        Name(trap),
                   1036:
                   1037: #ifdef MIPS1   /*  r2000 family  (mips-I cpu) */
                   1038:        Name(mips1_KernGenException),
                   1039:        Name(mips1_UserGenException),
                   1040:        Name(mips1_SystemCall),
                   1041:        Name(mips1_KernIntr),
                   1042:        Name(mips1_UserIntr),
                   1043: #endif /* MIPS1 */
                   1044:
1.165.2.8! nathanw  1045: /* XXX simonb: need mips32 and mips64 checks here too */
        !          1046: #if defined(MIPS3) && !defined(MIPS3_5900) /* r4000 family (mips-III cpu) */
1.165.2.2  wdk      1047:        Name(mips3_KernGenException),
                   1048:        Name(mips3_UserGenException),
                   1049:        Name(mips3_SystemCall),
                   1050:        Name(mips3_KernIntr),
                   1051:        Name(mips3_UserIntr),
1.165.2.8! nathanw  1052: #endif /* MIPS3 && !MIPS3_5900 */
1.165.2.2  wdk      1053:
                   1054:        Name(mips_idle),
                   1055:        Name(cpu_switch),
                   1056:        {0, 0}
                   1057: };
                   1058:
                   1059: /*
                   1060:  * Map a function address to a string name, if known; or a hex string.
                   1061:  */
                   1062: char *
                   1063: fn_name(unsigned addr)
                   1064: {
                   1065:        static char buf[17];
                   1066:        int i = 0;
                   1067: #ifdef DDB
                   1068:        db_expr_t diff;
                   1069:        db_sym_t sym;
                   1070:        char *symname;
                   1071: #endif
                   1072:
                   1073: #ifdef DDB
                   1074:        diff = 0;
                   1075:        symname = NULL;
                   1076:        sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
                   1077:        db_symbol_values(sym, &symname, 0);
                   1078:        if (symname && diff == 0)
                   1079:                return (symname);
                   1080: #endif
                   1081:        for (i = 0; names[i].name; i++)
                   1082:                if (names[i].addr == (void*)addr)
                   1083:                        return (names[i].name);
                   1084:        sprintf(buf, "%x", addr);
                   1085:        return (buf);
                   1086: }
                   1087:
                   1088: #endif /* DEBUG */
                   1089:
                   1090: #endif /* DDB_TRACE */

CVSweb <webmaster@jp.NetBSD.org>