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

Annotation of sys/arch/m88k/m88k/trap.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: trap.c,v 1.40 2007/05/11 10:06:55 pedro Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2004, Miodrag Vallat.
        !             4:  * Copyright (c) 1998 Steve Murphree, Jr.
        !             5:  * Copyright (c) 1996 Nivas Madhur
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *      This product includes software developed by Nivas Madhur.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  *
        !            33:  */
        !            34: /*
        !            35:  * Mach Operating System
        !            36:  * Copyright (c) 1991 Carnegie Mellon University
        !            37:  * Copyright (c) 1991 OMRON Corporation
        !            38:  * All Rights Reserved.
        !            39:  *
        !            40:  * Permission to use, copy, modify and distribute this software and its
        !            41:  * documentation is hereby granted, provided that both the copyright
        !            42:  * notice and this permission notice appear in all copies of the
        !            43:  * software, derivative works or modified versions, and any portions
        !            44:  * thereof, and that both notices appear in supporting documentation.
        !            45:  *
        !            46:  */
        !            47:
        !            48: #include <sys/types.h>
        !            49: #include <sys/param.h>
        !            50: #include <sys/proc.h>
        !            51: #include <sys/signalvar.h>
        !            52: #include <sys/user.h>
        !            53: #include <sys/syscall.h>
        !            54: #include <sys/systm.h>
        !            55: #include <sys/ktrace.h>
        !            56:
        !            57: #include "systrace.h"
        !            58: #include <dev/systrace.h>
        !            59:
        !            60: #include <uvm/uvm_extern.h>
        !            61:
        !            62: #include <machine/asm_macro.h>   /* enable/disable interrupts */
        !            63: #include <machine/cmmu.h>
        !            64: #include <machine/cpu.h>
        !            65: #ifdef M88100
        !            66: #include <machine/m88100.h>            /* DMT_xxx */
        !            67: #include <machine/m8820x.h>            /* CMMU_PFSR_xxx */
        !            68: #endif
        !            69: #ifdef M88110
        !            70: #include <machine/m88110.h>
        !            71: #endif
        !            72: #include <machine/pcb.h>               /* FIP_E, etc. */
        !            73: #include <machine/psl.h>               /* FIP_E, etc. */
        !            74: #include <machine/trap.h>
        !            75:
        !            76: #include <machine/db_machdep.h>
        !            77:
        !            78: #define SSBREAKPOINT (0xF000D1F8U) /* Single Step Breakpoint */
        !            79:
        !            80: #define USERMODE(PSR)   (((PSR) & PSR_MODE) == 0)
        !            81: #define SYSTEMMODE(PSR) (((PSR) & PSR_MODE) != 0)
        !            82:
        !            83: __dead void panictrap(int, struct trapframe *);
        !            84: __dead void error_fatal(struct trapframe *);
        !            85: int double_reg_fixup(struct trapframe *);
        !            86: int ss_put_value(struct proc *, vaddr_t, u_int);
        !            87:
        !            88: extern void regdump(struct trapframe *f);
        !            89:
        !            90: const char *trap_type[] = {
        !            91:        "Reset",
        !            92:        "Interrupt Exception",
        !            93:        "Instruction Access",
        !            94:        "Data Access Exception",
        !            95:        "Misaligned Access",
        !            96:        "Unimplemented Opcode",
        !            97:        "Privilege Violation"
        !            98:        "Bounds Check Violation",
        !            99:        "Illegal Integer Divide",
        !           100:        "Integer Overflow",
        !           101:        "Error Exception",
        !           102:        "Non-Maskable Exception",
        !           103: };
        !           104:
        !           105: const int trap_types = sizeof trap_type / sizeof trap_type[0];
        !           106:
        !           107: #ifdef M88100
        !           108: const char *pbus_exception_type[] = {
        !           109:        "Success (No Fault)",
        !           110:        "unknown 1",
        !           111:        "unknown 2",
        !           112:        "Bus Error",
        !           113:        "Segment Fault",
        !           114:        "Page Fault",
        !           115:        "Supervisor Violation",
        !           116:        "Write Violation",
        !           117: };
        !           118: #endif
        !           119:
        !           120: static inline void
        !           121: userret(struct proc *p)
        !           122: {
        !           123:        int sig;
        !           124:
        !           125:        /* take pending signals */
        !           126:        while ((sig = CURSIG(p)) != 0)
        !           127:                postsig(sig);
        !           128:
        !           129:        curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri;
        !           130: }
        !           131:
        !           132: __dead void
        !           133: panictrap(int type, struct trapframe *frame)
        !           134: {
        !           135:        static int panicing = 0;
        !           136:
        !           137:        if (panicing++ == 0) {
        !           138: #ifdef M88100
        !           139:                if (CPU_IS88100) {
        !           140:                        if (type == 2) {
        !           141:                                /* instruction exception */
        !           142:                                printf("\nInstr access fault (%s) v = %x, "
        !           143:                                    "frame %p\n",
        !           144:                                    pbus_exception_type[
        !           145:                                      CMMU_PFSR_FAULT(frame->tf_ipfsr)],
        !           146:                                    frame->tf_sxip & XIP_ADDR, frame);
        !           147:                        } else if (type == 3) {
        !           148:                                /* data access exception */
        !           149:                                printf("\nData access fault (%s) v = %x, "
        !           150:                                    "frame %p\n",
        !           151:                                    pbus_exception_type[
        !           152:                                      CMMU_PFSR_FAULT(frame->tf_dpfsr)],
        !           153:                                    frame->tf_sxip & XIP_ADDR, frame);
        !           154:                        } else
        !           155:                                printf("\nTrap type %d, v = %x, frame %p\n",
        !           156:                                    type, frame->tf_sxip & XIP_ADDR, frame);
        !           157:                }
        !           158: #endif
        !           159: #ifdef M88110
        !           160:                if (CPU_IS88110) {
        !           161:                        printf("\nTrap type %d, v = %x, frame %p\n",
        !           162:                            type, frame->tf_exip, frame);
        !           163:                }
        !           164: #endif
        !           165: #ifdef DDB
        !           166:                regdump(frame);
        !           167: #endif
        !           168:        }
        !           169:        if ((u_int)type < trap_types)
        !           170:                panic(trap_type[type]);
        !           171:        else
        !           172:                panic("trap %d", type);
        !           173:        /*NOTREACHED*/
        !           174: }
        !           175:
        !           176: #ifdef M88100
        !           177: void
        !           178: m88100_trap(unsigned type, struct trapframe *frame)
        !           179: {
        !           180:        struct proc *p;
        !           181:        struct vm_map *map;
        !           182:        vaddr_t va, pcb_onfault;
        !           183:        vm_prot_t ftype;
        !           184:        int fault_type, pbus_type;
        !           185:        u_long fault_code;
        !           186:        unsigned fault_addr;
        !           187:        struct vmspace *vm;
        !           188:        union sigval sv;
        !           189:        int result;
        !           190: #ifdef DDB
        !           191:        int s;
        !           192:        u_int psr;
        !           193: #endif
        !           194:        int sig = 0;
        !           195:
        !           196:        extern struct vm_map *kernel_map;
        !           197:
        !           198:        uvmexp.traps++;
        !           199:        if ((p = curproc) == NULL)
        !           200:                p = &proc0;
        !           201:
        !           202:        if (USERMODE(frame->tf_epsr)) {
        !           203:                type += T_USER;
        !           204:                p->p_md.md_tf = frame;  /* for ptrace/signals */
        !           205:        }
        !           206:        fault_type = 0;
        !           207:        fault_code = 0;
        !           208:        fault_addr = frame->tf_sxip & XIP_ADDR;
        !           209:
        !           210:        switch (type) {
        !           211:        default:
        !           212:                panictrap(frame->tf_vector, frame);
        !           213:                break;
        !           214:                /*NOTREACHED*/
        !           215:
        !           216: #if defined(DDB)
        !           217:        case T_KDB_BREAK:
        !           218:                s = splhigh();
        !           219:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           220:                ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
        !           221:                set_psr(psr);
        !           222:                splx(s);
        !           223:                return;
        !           224:        case T_KDB_ENTRY:
        !           225:                s = splhigh();
        !           226:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           227:                ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
        !           228:                set_psr(psr);
        !           229:                splx(s);
        !           230:                return;
        !           231: #endif /* DDB */
        !           232:        case T_ILLFLT:
        !           233:                printf("Unimplemented opcode!\n");
        !           234:                panictrap(frame->tf_vector, frame);
        !           235:                break;
        !           236:        case T_INT:
        !           237:        case T_INT+T_USER:
        !           238:                curcpu()->ci_intrdepth++;
        !           239:                md_interrupt_func(T_INT, frame);
        !           240:                curcpu()->ci_intrdepth--;
        !           241:                return;
        !           242:
        !           243:        case T_MISALGNFLT:
        !           244:                printf("kernel misaligned access exception @ 0x%08x\n",
        !           245:                    frame->tf_sxip);
        !           246:                panictrap(frame->tf_vector, frame);
        !           247:                break;
        !           248:
        !           249:        case T_INSTFLT:
        !           250:                /* kernel mode instruction access fault.
        !           251:                 * Should never, never happen for a non-paged kernel.
        !           252:                 */
        !           253: #ifdef TRAPDEBUG
        !           254:                pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
        !           255:                printf("Kernel Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
        !           256:                    pbus_type, pbus_exception_type[pbus_type],
        !           257:                    fault_addr, frame, frame->tf_cpu);
        !           258: #endif
        !           259:                panictrap(frame->tf_vector, frame);
        !           260:                break;
        !           261:
        !           262:        case T_DATAFLT:
        !           263:                /* kernel mode data fault */
        !           264:
        !           265:                /* data fault on the user address? */
        !           266:                if ((frame->tf_dmt0 & DMT_DAS) == 0) {
        !           267:                        type = T_DATAFLT + T_USER;
        !           268:                        goto user_fault;
        !           269:                }
        !           270:
        !           271:                fault_addr = frame->tf_dma0;
        !           272:                if (frame->tf_dmt0 & (DMT_WRITE|DMT_LOCKBAR)) {
        !           273:                        ftype = VM_PROT_READ|VM_PROT_WRITE;
        !           274:                        fault_code = VM_PROT_WRITE;
        !           275:                } else {
        !           276:                        ftype = VM_PROT_READ;
        !           277:                        fault_code = VM_PROT_READ;
        !           278:                }
        !           279:
        !           280:                va = trunc_page((vaddr_t)fault_addr);
        !           281:                if (va == 0) {
        !           282:                        panic("trap: bad kernel access at %x", fault_addr);
        !           283:                }
        !           284:
        !           285:                KERNEL_LOCK();
        !           286:                vm = p->p_vmspace;
        !           287:                map = kernel_map;
        !           288:
        !           289:                pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
        !           290: #ifdef TRAPDEBUG
        !           291:                printf("Kernel Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
        !           292:                    pbus_type, pbus_exception_type[pbus_type],
        !           293:                    fault_addr, frame, frame->tf_cpu);
        !           294: #endif
        !           295:
        !           296:                switch (pbus_type) {
        !           297:                case CMMU_PFSR_SUCCESS:
        !           298:                        /*
        !           299:                         * The fault was resolved. Call data_access_emulation
        !           300:                         * to drain the data unit pipe line and reset dmt0
        !           301:                         * so that trap won't get called again.
        !           302:                         */
        !           303:                        data_access_emulation((unsigned *)frame);
        !           304:                        frame->tf_dpfsr = 0;
        !           305:                        frame->tf_dmt0 = 0;
        !           306:                        KERNEL_UNLOCK();
        !           307:                        return;
        !           308:                case CMMU_PFSR_SFAULT:
        !           309:                case CMMU_PFSR_PFAULT:
        !           310:                        if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
        !           311:                                p->p_addr->u_pcb.pcb_onfault = 0;
        !           312:                        result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           313:                        p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           314:                        if (result == 0) {
        !           315:                                /*
        !           316:                                 * We could resolve the fault. Call
        !           317:                                 * data_access_emulation to drain the data
        !           318:                                 * unit pipe line and reset dmt0 so that trap
        !           319:                                 * won't get called again.
        !           320:                                 */
        !           321:                                data_access_emulation((unsigned *)frame);
        !           322:                                frame->tf_dpfsr = 0;
        !           323:                                frame->tf_dmt0 = 0;
        !           324:                                KERNEL_UNLOCK();
        !           325:                                return;
        !           326:                        }
        !           327:                        break;
        !           328:                }
        !           329: #ifdef TRAPDEBUG
        !           330:                printf("PBUS Fault %d (%s) va = 0x%x\n", pbus_type,
        !           331:                    pbus_exception_type[pbus_type], va);
        !           332: #endif
        !           333:                KERNEL_UNLOCK();
        !           334:                panictrap(frame->tf_vector, frame);
        !           335:                /* NOTREACHED */
        !           336:        case T_INSTFLT+T_USER:
        !           337:                /* User mode instruction access fault */
        !           338:                /* FALLTHROUGH */
        !           339:        case T_DATAFLT+T_USER:
        !           340: user_fault:
        !           341:                if (type == T_INSTFLT + T_USER) {
        !           342:                        pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
        !           343: #ifdef TRAPDEBUG
        !           344:                        printf("User Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
        !           345:                            pbus_type, pbus_exception_type[pbus_type],
        !           346:                            fault_addr, frame, frame->tf_cpu);
        !           347: #endif
        !           348:                } else {
        !           349:                        fault_addr = frame->tf_dma0;
        !           350:                        pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
        !           351: #ifdef TRAPDEBUG
        !           352:                        printf("User Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
        !           353:                            pbus_type, pbus_exception_type[pbus_type],
        !           354:                            fault_addr, frame, frame->tf_cpu);
        !           355: #endif
        !           356:                }
        !           357:
        !           358:                if (frame->tf_dmt0 & (DMT_WRITE | DMT_LOCKBAR)) {
        !           359:                        ftype = VM_PROT_READ | VM_PROT_WRITE;
        !           360:                        fault_code = VM_PROT_WRITE;
        !           361:                } else {
        !           362:                        ftype = VM_PROT_READ;
        !           363:                        fault_code = VM_PROT_READ;
        !           364:                }
        !           365:
        !           366:                va = trunc_page((vaddr_t)fault_addr);
        !           367:
        !           368:                KERNEL_PROC_LOCK(p);
        !           369:                vm = p->p_vmspace;
        !           370:                map = &vm->vm_map;
        !           371:                if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
        !           372:                        p->p_addr->u_pcb.pcb_onfault = 0;
        !           373:
        !           374:                /* Call uvm_fault() to resolve non-bus error faults */
        !           375:                switch (pbus_type) {
        !           376:                case CMMU_PFSR_SUCCESS:
        !           377:                        result = 0;
        !           378:                        break;
        !           379:                case CMMU_PFSR_BERROR:
        !           380:                        result = EACCES;
        !           381:                        break;
        !           382:                default:
        !           383:                        result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           384:                        break;
        !           385:                }
        !           386:
        !           387:                p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           388:
        !           389:                if ((caddr_t)va >= vm->vm_maxsaddr) {
        !           390:                        if (result == 0)
        !           391:                                uvm_grow(p, va);
        !           392:                        else if (result == EACCES)
        !           393:                                result = EFAULT;
        !           394:                }
        !           395:                KERNEL_PROC_UNLOCK(p);
        !           396:
        !           397:                /*
        !           398:                 * This could be a fault caused in copyin*()
        !           399:                 * while accessing user space.
        !           400:                 */
        !           401:                if (result != 0 && pcb_onfault != 0) {
        !           402:                        frame->tf_snip = pcb_onfault | NIP_V;
        !           403:                        frame->tf_sfip = (pcb_onfault + 4) | FIP_V;
        !           404:                        frame->tf_sxip = 0;
        !           405:                        /*
        !           406:                         * Continue as if the fault had been resolved, but
        !           407:                         * do not try to complete the faulting access.
        !           408:                         */
        !           409:                        frame->tf_dmt0 |= DMT_SKIP;
        !           410:                        result = 0;
        !           411:                }
        !           412:
        !           413:                if (result == 0) {
        !           414:                        if (type == T_DATAFLT+T_USER) {
        !           415:                                /*
        !           416:                                 * We could resolve the fault. Call
        !           417:                                 * data_access_emulation to drain the data unit
        !           418:                                 * pipe line and reset dmt0 so that trap won't
        !           419:                                 * get called again.
        !           420:                                 */
        !           421:                                data_access_emulation((unsigned *)frame);
        !           422:                                frame->tf_dpfsr = 0;
        !           423:                                frame->tf_dmt0 = 0;
        !           424:                        } else {
        !           425:                                /*
        !           426:                                 * back up SXIP, SNIP,
        !           427:                                 * clearing the Error bit
        !           428:                                 */
        !           429:                                frame->tf_sfip = frame->tf_snip & ~FIP_E;
        !           430:                                frame->tf_snip = frame->tf_sxip & ~NIP_E;
        !           431:                                frame->tf_ipfsr = 0;
        !           432:                        }
        !           433:                } else {
        !           434:                        sig = result == EACCES ? SIGBUS : SIGSEGV;
        !           435:                        fault_type = result == EACCES ?
        !           436:                            BUS_ADRERR : SEGV_MAPERR;
        !           437:                }
        !           438:                break;
        !           439:        case T_MISALGNFLT+T_USER:
        !           440:                /* Fix any misaligned ld.d or st.d instructions */
        !           441:                sig = double_reg_fixup(frame);
        !           442:                fault_type = BUS_ADRALN;
        !           443:                break;
        !           444:        case T_PRIVINFLT+T_USER:
        !           445:        case T_ILLFLT+T_USER:
        !           446: #ifndef DDB
        !           447:        case T_KDB_BREAK:
        !           448:        case T_KDB_ENTRY:
        !           449: #endif
        !           450:        case T_KDB_BREAK+T_USER:
        !           451:        case T_KDB_ENTRY+T_USER:
        !           452:        case T_KDB_TRACE:
        !           453:        case T_KDB_TRACE+T_USER:
        !           454:                sig = SIGILL;
        !           455:                break;
        !           456:        case T_BNDFLT+T_USER:
        !           457:                sig = SIGFPE;
        !           458:                break;
        !           459:        case T_ZERODIV+T_USER:
        !           460:                sig = SIGFPE;
        !           461:                fault_type = FPE_INTDIV;
        !           462:                break;
        !           463:        case T_OVFFLT+T_USER:
        !           464:                sig = SIGFPE;
        !           465:                fault_type = FPE_INTOVF;
        !           466:                break;
        !           467:        case T_FPEPFLT+T_USER:
        !           468:                sig = SIGFPE;
        !           469:                break;
        !           470:        case T_SIGSYS+T_USER:
        !           471:                sig = SIGSYS;
        !           472:                break;
        !           473:        case T_STEPBPT+T_USER:
        !           474: #ifdef PTRACE
        !           475:                /*
        !           476:                 * This trap is used by the kernel to support single-step
        !           477:                 * debugging (although any user could generate this trap
        !           478:                 * which should probably be handled differently). When a
        !           479:                 * process is continued by a debugger with the PT_STEP
        !           480:                 * function of ptrace (single step), the kernel inserts
        !           481:                 * one or two breakpoints in the user process so that only
        !           482:                 * one instruction (or two in the case of a delayed branch)
        !           483:                 * is executed.  When this breakpoint is hit, we get the
        !           484:                 * T_STEPBPT trap.
        !           485:                 */
        !           486:                {
        !           487:                        u_int instr;
        !           488:                        vaddr_t pc = PC_REGS(&frame->tf_regs);
        !           489:
        !           490:                        /* read break instruction */
        !           491:                        copyin((caddr_t)pc, &instr, sizeof(u_int));
        !           492:
        !           493:                        /* check and see if we got here by accident */
        !           494:                        if ((p->p_md.md_bp0va != pc &&
        !           495:                             p->p_md.md_bp1va != pc) ||
        !           496:                            instr != SSBREAKPOINT) {
        !           497:                                sig = SIGTRAP;
        !           498:                                fault_type = TRAP_TRACE;
        !           499:                                break;
        !           500:                        }
        !           501:
        !           502:                        /* restore original instruction and clear breakpoint */
        !           503:                        if (p->p_md.md_bp0va == pc) {
        !           504:                                ss_put_value(p, pc, p->p_md.md_bp0save);
        !           505:                                p->p_md.md_bp0va = 0;
        !           506:                        }
        !           507:                        if (p->p_md.md_bp1va == pc) {
        !           508:                                ss_put_value(p, pc, p->p_md.md_bp1save);
        !           509:                                p->p_md.md_bp1va = 0;
        !           510:                        }
        !           511:
        !           512: #if 1
        !           513:                        frame->tf_sfip = frame->tf_snip;
        !           514:                        frame->tf_snip = pc | NIP_V;
        !           515: #endif
        !           516:                        sig = SIGTRAP;
        !           517:                        fault_type = TRAP_BRKPT;
        !           518:                }
        !           519: #else
        !           520:                sig = SIGTRAP;
        !           521:                fault_type = TRAP_TRACE;
        !           522: #endif
        !           523:                break;
        !           524:
        !           525:        case T_USERBPT+T_USER:
        !           526:                /*
        !           527:                 * This trap is meant to be used by debuggers to implement
        !           528:                 * breakpoint debugging.  When we get this trap, we just
        !           529:                 * return a signal which gets caught by the debugger.
        !           530:                 */
        !           531:                frame->tf_sfip = frame->tf_snip;
        !           532:                frame->tf_snip = frame->tf_sxip;
        !           533:                sig = SIGTRAP;
        !           534:                fault_type = TRAP_BRKPT;
        !           535:                break;
        !           536:
        !           537:        case T_ASTFLT+T_USER:
        !           538:                uvmexp.softs++;
        !           539:                p->p_md.md_astpending = 0;
        !           540:                if (p->p_flag & P_OWEUPC) {
        !           541:                        KERNEL_PROC_LOCK(p);
        !           542:                        ADDUPROF(p);
        !           543:                        KERNEL_PROC_UNLOCK(p);
        !           544:                }
        !           545:                if (curcpu()->ci_want_resched)
        !           546:                        preempt(NULL);
        !           547:                break;
        !           548:        }
        !           549:
        !           550:        /*
        !           551:         * If trap from supervisor mode, just return
        !           552:         */
        !           553:        if (type < T_USER)
        !           554:                return;
        !           555:
        !           556:        if (sig) {
        !           557:                sv.sival_int = fault_addr;
        !           558:                KERNEL_PROC_LOCK(p);
        !           559:                trapsignal(p, sig, fault_code, fault_type, sv);
        !           560:                KERNEL_PROC_UNLOCK(p);
        !           561:                /*
        !           562:                 * don't want multiple faults - we are going to
        !           563:                 * deliver signal.
        !           564:                 */
        !           565:                frame->tf_dmt0 = 0;
        !           566:                frame->tf_ipfsr = frame->tf_dpfsr = 0;
        !           567:        }
        !           568:
        !           569:        userret(p);
        !           570: }
        !           571: #endif /* M88100 */
        !           572:
        !           573: #ifdef M88110
        !           574: void
        !           575: m88110_trap(unsigned type, struct trapframe *frame)
        !           576: {
        !           577:        struct proc *p;
        !           578:        struct vm_map *map;
        !           579:        vaddr_t va, pcb_onfault;
        !           580:        vm_prot_t ftype;
        !           581:        int fault_type;
        !           582:        u_long fault_code;
        !           583:        unsigned fault_addr;
        !           584:        struct vmspace *vm;
        !           585:        union sigval sv;
        !           586:        int result;
        !           587: #ifdef DDB
        !           588:         int s;
        !           589:        u_int psr;
        !           590: #endif
        !           591:        int sig = 0;
        !           592:        pt_entry_t *pte;
        !           593:
        !           594:        extern struct vm_map *kernel_map;
        !           595:        extern pt_entry_t *pmap_pte(pmap_t, vaddr_t);
        !           596:
        !           597:        uvmexp.traps++;
        !           598:        if ((p = curproc) == NULL)
        !           599:                p = &proc0;
        !           600:
        !           601:        if (USERMODE(frame->tf_epsr)) {
        !           602:                type += T_USER;
        !           603:                p->p_md.md_tf = frame;  /* for ptrace/signals */
        !           604:        }
        !           605:        fault_type = 0;
        !           606:        fault_code = 0;
        !           607:        fault_addr = frame->tf_exip & XIP_ADDR;
        !           608:
        !           609:        switch (type) {
        !           610:        default:
        !           611:                panictrap(frame->tf_vector, frame);
        !           612:                break;
        !           613:                /*NOTREACHED*/
        !           614:
        !           615:        case T_110_DRM+T_USER:
        !           616:        case T_110_DRM:
        !           617: #ifdef DEBUG
        !           618:                printf("DMMU read miss: Hardware Table Searches should be enabled!\n");
        !           619: #endif
        !           620:                panictrap(frame->tf_vector, frame);
        !           621:                break;
        !           622:                /*NOTREACHED*/
        !           623:        case T_110_DWM+T_USER:
        !           624:        case T_110_DWM:
        !           625: #ifdef DEBUG
        !           626:                printf("DMMU write miss: Hardware Table Searches should be enabled!\n");
        !           627: #endif
        !           628:                panictrap(frame->tf_vector, frame);
        !           629:                break;
        !           630:                /*NOTREACHED*/
        !           631:        case T_110_IAM+T_USER:
        !           632:        case T_110_IAM:
        !           633: #ifdef DEBUG
        !           634:                printf("IMMU miss: Hardware Table Searches should be enabled!\n");
        !           635: #endif
        !           636:                panictrap(frame->tf_vector, frame);
        !           637:                break;
        !           638:                /*NOTREACHED*/
        !           639:
        !           640: #ifdef DDB
        !           641:        case T_KDB_TRACE:
        !           642:                s = splhigh();
        !           643:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           644:                ddb_break_trap(T_KDB_TRACE, (db_regs_t*)frame);
        !           645:                set_psr(psr);
        !           646:                splx(s);
        !           647:                return;
        !           648:        case T_KDB_BREAK:
        !           649:                s = splhigh();
        !           650:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           651:                ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
        !           652:                set_psr(psr);
        !           653:                splx(s);
        !           654:                return;
        !           655:        case T_KDB_ENTRY:
        !           656:                s = splhigh();
        !           657:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           658:                ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
        !           659:                set_psr(psr);
        !           660:                /* skip one instruction */
        !           661:                if (frame->tf_exip & 1)
        !           662:                        frame->tf_exip = frame->tf_enip;
        !           663:                else
        !           664:                        frame->tf_exip += 4;
        !           665:                splx(s);
        !           666:                return;
        !           667: #if 0
        !           668:        case T_ILLFLT:
        !           669:                s = splhigh();
        !           670:                set_psr((psr = get_psr()) & ~PSR_IND);
        !           671:                ddb_error_trap(type == T_ILLFLT ? "unimplemented opcode" :
        !           672:                       "error fault", (db_regs_t*)frame);
        !           673:                set_psr(psr);
        !           674:                splx(s);
        !           675:                return;
        !           676: #endif /* 0 */
        !           677: #endif /* DDB */
        !           678:        case T_ILLFLT:
        !           679:                printf("Unimplemented opcode!\n");
        !           680:                panictrap(frame->tf_vector, frame);
        !           681:                break;
        !           682:        case T_NON_MASK:
        !           683:        case T_NON_MASK+T_USER:
        !           684:                curcpu()->ci_intrdepth++;
        !           685:                md_interrupt_func(T_NON_MASK, frame);
        !           686:                curcpu()->ci_intrdepth--;
        !           687:                return;
        !           688:        case T_INT:
        !           689:        case T_INT+T_USER:
        !           690:                curcpu()->ci_intrdepth++;
        !           691:                md_interrupt_func(T_INT, frame);
        !           692:                curcpu()->ci_intrdepth--;
        !           693:                return;
        !           694:        case T_MISALGNFLT:
        !           695:                printf("kernel mode misaligned access exception @ 0x%08x\n",
        !           696:                    frame->tf_exip);
        !           697:                panictrap(frame->tf_vector, frame);
        !           698:                break;
        !           699:                /*NOTREACHED*/
        !           700:
        !           701:        case T_INSTFLT:
        !           702:                /* kernel mode instruction access fault.
        !           703:                 * Should never, never happen for a non-paged kernel.
        !           704:                 */
        !           705: #ifdef TRAPDEBUG
        !           706:                printf("Kernel Instruction fault exip %x isr %x ilar %x\n",
        !           707:                    frame->tf_exip, frame->tf_isr, frame->tf_ilar);
        !           708: #endif
        !           709:                panictrap(frame->tf_vector, frame);
        !           710:                break;
        !           711:                /*NOTREACHED*/
        !           712:
        !           713:        case T_DATAFLT:
        !           714:                /* kernel mode data fault */
        !           715:
        !           716:                /* data fault on the user address? */
        !           717:                if ((frame->tf_dsr & CMMU_DSR_SU) == 0) {
        !           718:                        type = T_DATAFLT + T_USER;
        !           719:                        goto m88110_user_fault;
        !           720:                }
        !           721:
        !           722: #ifdef TRAPDEBUG
        !           723:                printf("Kernel Data access fault exip %x dsr %x dlar %x\n",
        !           724:                    frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
        !           725: #endif
        !           726:
        !           727:                fault_addr = frame->tf_dlar;
        !           728:                if (frame->tf_dsr & CMMU_DSR_RW) {
        !           729:                        ftype = VM_PROT_READ;
        !           730:                        fault_code = VM_PROT_READ;
        !           731:                } else {
        !           732:                        ftype = VM_PROT_READ|VM_PROT_WRITE;
        !           733:                        fault_code = VM_PROT_WRITE;
        !           734:                }
        !           735:
        !           736:                va = trunc_page((vaddr_t)fault_addr);
        !           737:                if (va == 0) {
        !           738:                        panic("trap: bad kernel access at %x", fault_addr);
        !           739:                }
        !           740:
        !           741:                KERNEL_LOCK();
        !           742:                vm = p->p_vmspace;
        !           743:                map = kernel_map;
        !           744:
        !           745:                if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
        !           746:                        frame->tf_dsr &= ~CMMU_DSR_WE;  /* undefined */
        !           747:                        /*
        !           748:                         * On a segment or a page fault, call uvm_fault() to
        !           749:                         * resolve the fault.
        !           750:                         */
        !           751:                        if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
        !           752:                                p->p_addr->u_pcb.pcb_onfault = 0;
        !           753:                        result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           754:                        p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           755:                        if (result == 0) {
        !           756:                                KERNEL_UNLOCK();
        !           757:                                return;
        !           758:                        }
        !           759:                }
        !           760:                if (frame->tf_dsr & CMMU_DSR_WE) {      /* write fault  */
        !           761:                        /*
        !           762:                         * This could be a write protection fault or an
        !           763:                         * exception to set the used and modified bits
        !           764:                         * in the pte. Basically, if we got a write error,
        !           765:                         * then we already have a pte entry that faulted
        !           766:                         * in from a previous seg fault or page fault.
        !           767:                         * Get the pte and check the status of the
        !           768:                         * modified and valid bits to determine if this
        !           769:                         * indeed a real write fault.  XXX smurph
        !           770:                         */
        !           771:                        pte = pmap_pte(map->pmap, va);
        !           772: #ifdef DEBUG
        !           773:                        if (pte == NULL) {
        !           774:                                KERNEL_UNLOCK();
        !           775:                                panic("NULL pte on write fault??");
        !           776:                        }
        !           777: #endif
        !           778:                        if (!(*pte & PG_M) && !(*pte & PG_RO)) {
        !           779:                                /* Set modified bit and try the write again. */
        !           780: #ifdef TRAPDEBUG
        !           781:                                printf("Corrected kernel write fault, map %x pte %x\n",
        !           782:                                    map->pmap, *pte);
        !           783: #endif
        !           784:                                *pte |= PG_M;
        !           785:                                KERNEL_UNLOCK();
        !           786:                                return;
        !           787: #if 1  /* shouldn't happen */
        !           788:                        } else {
        !           789:                                /* must be a real wp fault */
        !           790: #ifdef TRAPDEBUG
        !           791:                                printf("Uncorrected kernel write fault, map %x pte %x\n",
        !           792:                                    map->pmap, *pte);
        !           793: #endif
        !           794:                                if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
        !           795:                                        p->p_addr->u_pcb.pcb_onfault = 0;
        !           796:                                result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           797:                                p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           798:                                if (result == 0) {
        !           799:                                        KERNEL_UNLOCK();
        !           800:                                        return;
        !           801:                                }
        !           802: #endif
        !           803:                        }
        !           804:                }
        !           805:                KERNEL_UNLOCK();
        !           806:                panictrap(frame->tf_vector, frame);
        !           807:                /* NOTREACHED */
        !           808:        case T_INSTFLT+T_USER:
        !           809:                /* User mode instruction access fault */
        !           810:                /* FALLTHROUGH */
        !           811:        case T_DATAFLT+T_USER:
        !           812: m88110_user_fault:
        !           813:                if (type == T_INSTFLT+T_USER) {
        !           814:                        ftype = VM_PROT_READ;
        !           815:                        fault_code = VM_PROT_READ;
        !           816: #ifdef TRAPDEBUG
        !           817:                        printf("User Instruction fault exip %x isr %x ilar %x\n",
        !           818:                            frame->tf_exip, frame->tf_isr, frame->tf_ilar);
        !           819: #endif
        !           820:                } else {
        !           821:                        fault_addr = frame->tf_dlar;
        !           822:                        if (frame->tf_dsr & CMMU_DSR_RW) {
        !           823:                                ftype = VM_PROT_READ;
        !           824:                                fault_code = VM_PROT_READ;
        !           825:                        } else {
        !           826:                                ftype = VM_PROT_READ|VM_PROT_WRITE;
        !           827:                                fault_code = VM_PROT_WRITE;
        !           828:                        }
        !           829: #ifdef TRAPDEBUG
        !           830:                        printf("User Data access fault exip %x dsr %x dlar %x\n",
        !           831:                            frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
        !           832: #endif
        !           833:                }
        !           834:
        !           835:                va = trunc_page((vaddr_t)fault_addr);
        !           836:
        !           837:                KERNEL_PROC_LOCK(p);
        !           838:                vm = p->p_vmspace;
        !           839:                map = &vm->vm_map;
        !           840:                if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
        !           841:                        p->p_addr->u_pcb.pcb_onfault = 0;
        !           842:
        !           843:                /*
        !           844:                 * Call uvm_fault() to resolve non-bus error faults
        !           845:                 * whenever possible.
        !           846:                 */
        !           847:                if (type == T_DATAFLT+T_USER) {
        !           848:                        /* data faults */
        !           849:                        if (frame->tf_dsr & CMMU_DSR_BE) {
        !           850:                                /* bus error */
        !           851:                                result = EACCES;
        !           852:                        } else
        !           853:                        if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
        !           854:                                /* segment or page fault */
        !           855:                                result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           856:                                p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           857:                        } else
        !           858:                        if (frame->tf_dsr & (CMMU_DSR_CP | CMMU_DSR_WA)) {
        !           859:                                /* copyback or write allocate error */
        !           860:                                result = EACCES;
        !           861:                        } else
        !           862:                        if (frame->tf_dsr & CMMU_DSR_WE) {
        !           863:                                /* write fault  */
        !           864:                                /* This could be a write protection fault or an
        !           865:                                 * exception to set the used and modified bits
        !           866:                                 * in the pte. Basically, if we got a write
        !           867:                                 * error, then we already have a pte entry that
        !           868:                                 * faulted in from a previous seg fault or page
        !           869:                                 * fault.
        !           870:                                 * Get the pte and check the status of the
        !           871:                                 * modified and valid bits to determine if this
        !           872:                                 * indeed a real write fault.  XXX smurph
        !           873:                                 */
        !           874:                                pte = pmap_pte(vm_map_pmap(map), va);
        !           875: #ifdef DEBUG
        !           876:                                if (pte == NULL) {
        !           877:                                        KERNEL_PROC_UNLOCK(p);
        !           878:                                        panic("NULL pte on write fault??");
        !           879:                                }
        !           880: #endif
        !           881:                                if (!(*pte & PG_M) && !(*pte & PG_RO)) {
        !           882:                                        /*
        !           883:                                         * Set modified bit and try the
        !           884:                                         * write again.
        !           885:                                         */
        !           886: #ifdef TRAPDEBUG
        !           887:                                        printf("Corrected userland write fault, map %x pte %x\n",
        !           888:                                            map->pmap, *pte);
        !           889: #endif
        !           890:                                        *pte |= PG_M;
        !           891:                                        /*
        !           892:                                         * invalidate ATCs to force
        !           893:                                         * table search
        !           894:                                         */
        !           895:                                        set_dcmd(CMMU_DCMD_INV_UATC);
        !           896:                                        KERNEL_PROC_UNLOCK(p);
        !           897:                                        return;
        !           898:                                } else {
        !           899:                                        /* must be a real wp fault */
        !           900: #ifdef TRAPDEBUG
        !           901:                                        printf("Uncorrected userland write fault, map %x pte %x\n",
        !           902:                                            map->pmap, *pte);
        !           903: #endif
        !           904:                                        result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           905:                                        p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           906:                                }
        !           907:                        } else {
        !           908: #ifdef TRAPDEBUG
        !           909:                                printf("Unexpected Data access fault dsr %x\n",
        !           910:                                    frame->tf_dsr);
        !           911: #endif
        !           912:                                KERNEL_PROC_UNLOCK(p);
        !           913:                                panictrap(frame->tf_vector, frame);
        !           914:                        }
        !           915:                } else {
        !           916:                        /* instruction faults */
        !           917:                        if (frame->tf_isr &
        !           918:                            (CMMU_ISR_BE | CMMU_ISR_SP | CMMU_ISR_TBE)) {
        !           919:                                /* bus error, supervisor protection */
        !           920:                                result = EACCES;
        !           921:                        } else
        !           922:                        if (frame->tf_isr & (CMMU_ISR_SI | CMMU_ISR_PI)) {
        !           923:                                /* segment or page fault */
        !           924:                                result = uvm_fault(map, va, VM_FAULT_INVALID, ftype);
        !           925:                                p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
        !           926:                        } else {
        !           927: #ifdef TRAPDEBUG
        !           928:                                printf("Unexpected Instruction fault isr %x\n",
        !           929:                                    frame->tf_isr);
        !           930: #endif
        !           931:                                KERNEL_PROC_UNLOCK(p);
        !           932:                                panictrap(frame->tf_vector, frame);
        !           933:                        }
        !           934:                }
        !           935:
        !           936:                if ((caddr_t)va >= vm->vm_maxsaddr) {
        !           937:                        if (result == 0)
        !           938:                                uvm_grow(p, va);
        !           939:                        else if (result == EACCES)
        !           940:                                result = EFAULT;
        !           941:                }
        !           942:                KERNEL_PROC_UNLOCK(p);
        !           943:
        !           944:                /*
        !           945:                 * This could be a fault caused in copyin*()
        !           946:                 * while accessing user space.
        !           947:                 */
        !           948:                if (result != 0 && pcb_onfault != 0) {
        !           949:                        frame->tf_exip = pcb_onfault;
        !           950:                        /*
        !           951:                         * Continue as if the fault had been resolved.
        !           952:                         */
        !           953:                        result = 0;
        !           954:                }
        !           955:
        !           956:                if (result != 0) {
        !           957:                        sig = result == EACCES ? SIGBUS : SIGSEGV;
        !           958:                        fault_type = result == EACCES ?
        !           959:                            BUS_ADRERR : SEGV_MAPERR;
        !           960:                }
        !           961:                break;
        !           962:        case T_MISALGNFLT+T_USER:
        !           963:                /* Fix any misaligned ld.d or st.d instructions */
        !           964:                sig = double_reg_fixup(frame);
        !           965:                fault_type = BUS_ADRALN;
        !           966:                break;
        !           967:        case T_PRIVINFLT+T_USER:
        !           968:        case T_ILLFLT+T_USER:
        !           969: #ifndef DDB
        !           970:        case T_KDB_BREAK:
        !           971:        case T_KDB_ENTRY:
        !           972:        case T_KDB_TRACE:
        !           973: #endif
        !           974:        case T_KDB_BREAK+T_USER:
        !           975:        case T_KDB_ENTRY+T_USER:
        !           976:        case T_KDB_TRACE+T_USER:
        !           977:                sig = SIGILL;
        !           978:                break;
        !           979:        case T_BNDFLT+T_USER:
        !           980:                sig = SIGFPE;
        !           981:                break;
        !           982:        case T_ZERODIV+T_USER:
        !           983:                sig = SIGFPE;
        !           984:                fault_type = FPE_INTDIV;
        !           985:                break;
        !           986:        case T_OVFFLT+T_USER:
        !           987:                sig = SIGFPE;
        !           988:                fault_type = FPE_INTOVF;
        !           989:                break;
        !           990:        case T_FPEPFLT+T_USER:
        !           991:                sig = SIGFPE;
        !           992:                break;
        !           993:        case T_SIGSYS+T_USER:
        !           994:                sig = SIGSYS;
        !           995:                break;
        !           996:        case T_STEPBPT+T_USER:
        !           997: #ifdef PTRACE
        !           998:                /*
        !           999:                 * This trap is used by the kernel to support single-step
        !          1000:                 * debugging (although any user could generate this trap
        !          1001:                 * which should probably be handled differently). When a
        !          1002:                 * process is continued by a debugger with the PT_STEP
        !          1003:                 * function of ptrace (single step), the kernel inserts
        !          1004:                 * one or two breakpoints in the user process so that only
        !          1005:                 * one instruction (or two in the case of a delayed branch)
        !          1006:                 * is executed.  When this breakpoint is hit, we get the
        !          1007:                 * T_STEPBPT trap.
        !          1008:                 */
        !          1009:                {
        !          1010:                        u_int instr;
        !          1011:                        vaddr_t pc = PC_REGS(&frame->tf_regs);
        !          1012:
        !          1013:                        /* read break instruction */
        !          1014:                        copyin((caddr_t)pc, &instr, sizeof(u_int));
        !          1015:
        !          1016:                        /* check and see if we got here by accident */
        !          1017:                        if ((p->p_md.md_bp0va != pc &&
        !          1018:                             p->p_md.md_bp1va != pc) ||
        !          1019:                            instr != SSBREAKPOINT) {
        !          1020:                                sig = SIGTRAP;
        !          1021:                                fault_type = TRAP_TRACE;
        !          1022:                                break;
        !          1023:                        }
        !          1024:
        !          1025:                        /* restore original instruction and clear breakpoint */
        !          1026:                        if (p->p_md.md_bp0va == pc) {
        !          1027:                                ss_put_value(p, pc, p->p_md.md_bp0save);
        !          1028:                                p->p_md.md_bp0va = 0;
        !          1029:                        }
        !          1030:                        if (p->p_md.md_bp1va == pc) {
        !          1031:                                ss_put_value(p, pc, p->p_md.md_bp1save);
        !          1032:                                p->p_md.md_bp1va = 0;
        !          1033:                        }
        !          1034:
        !          1035:                        sig = SIGTRAP;
        !          1036:                        fault_type = TRAP_BRKPT;
        !          1037:                }
        !          1038: #else
        !          1039:                sig = SIGTRAP;
        !          1040:                fault_type = TRAP_TRACE;
        !          1041: #endif
        !          1042:                break;
        !          1043:        case T_USERBPT+T_USER:
        !          1044:                /*
        !          1045:                 * This trap is meant to be used by debuggers to implement
        !          1046:                 * breakpoint debugging.  When we get this trap, we just
        !          1047:                 * return a signal which gets caught by the debugger.
        !          1048:                 */
        !          1049:                sig = SIGTRAP;
        !          1050:                fault_type = TRAP_BRKPT;
        !          1051:                break;
        !          1052:
        !          1053:        case T_ASTFLT+T_USER:
        !          1054:                uvmexp.softs++;
        !          1055:                p->p_md.md_astpending = 0;
        !          1056:                if (p->p_flag & P_OWEUPC) {
        !          1057:                        KERNEL_PROC_LOCK(p);
        !          1058:                        ADDUPROF(p);
        !          1059:                        KERNEL_PROC_UNLOCK(p);
        !          1060:                }
        !          1061:                if (curcpu()->ci_want_resched)
        !          1062:                        preempt(NULL);
        !          1063:                break;
        !          1064:        }
        !          1065:
        !          1066:        /*
        !          1067:         * If trap from supervisor mode, just return
        !          1068:         */
        !          1069:        if (type < T_USER)
        !          1070:                return;
        !          1071:
        !          1072:        if (sig) {
        !          1073:                sv.sival_int = fault_addr;
        !          1074:                KERNEL_PROC_LOCK(p);
        !          1075:                trapsignal(p, sig, fault_code, fault_type, sv);
        !          1076:                KERNEL_PROC_UNLOCK(p);
        !          1077:        }
        !          1078:
        !          1079:        userret(p);
        !          1080: }
        !          1081: #endif /* M88110 */
        !          1082:
        !          1083: __dead void
        !          1084: error_fatal(struct trapframe *frame)
        !          1085: {
        !          1086:        if (frame->tf_vector == 0)
        !          1087:                printf("\nCPU %d Reset Exception\n", cpu_number());
        !          1088:        else
        !          1089:                printf("\nCPU %d Error Exception\n", cpu_number());
        !          1090:
        !          1091: #ifdef DDB
        !          1092:        regdump((struct trapframe*)frame);
        !          1093: #endif
        !          1094:        panic("unrecoverable exception %d", frame->tf_vector);
        !          1095: }
        !          1096:
        !          1097: #ifdef M88100
        !          1098: void
        !          1099: m88100_syscall(register_t code, struct trapframe *tf)
        !          1100: {
        !          1101:        int i, nsys, nap;
        !          1102:        struct sysent *callp;
        !          1103:        struct proc *p;
        !          1104:        int error;
        !          1105:        register_t args[8], rval[2], *ap;
        !          1106:
        !          1107:        uvmexp.syscalls++;
        !          1108:
        !          1109:        p = curproc;
        !          1110:
        !          1111:        callp = p->p_emul->e_sysent;
        !          1112:        nsys  = p->p_emul->e_nsysent;
        !          1113:
        !          1114:        p->p_md.md_tf = tf;
        !          1115:
        !          1116:        /*
        !          1117:         * For 88k, all the arguments are passed in the registers (r2-r9),
        !          1118:         * and further arguments (if any) on stack.
        !          1119:         * For syscall (and __syscall), r2 (and r3) has the actual code.
        !          1120:         * __syscall  takes a quad syscall number, so that other
        !          1121:         * arguments are at their natural alignments.
        !          1122:         */
        !          1123:        ap = &tf->tf_r[2];
        !          1124:        nap = 8; /* r2-r9 */
        !          1125:
        !          1126:        switch (code) {
        !          1127:        case SYS_syscall:
        !          1128:                code = *ap++;
        !          1129:                nap--;
        !          1130:                break;
        !          1131:        case SYS___syscall:
        !          1132:                if (callp != sysent)
        !          1133:                        break;
        !          1134:                code = ap[_QUAD_LOWWORD];
        !          1135:                ap += 2;
        !          1136:                nap -= 2;
        !          1137:                break;
        !          1138:        }
        !          1139:
        !          1140:        if (code < 0 || code >= nsys)
        !          1141:                callp += p->p_emul->e_nosys;
        !          1142:        else
        !          1143:                callp += code;
        !          1144:
        !          1145:        i = callp->sy_argsize / sizeof(register_t);
        !          1146:        if (i > sizeof(args) / sizeof(register_t))
        !          1147:                panic("syscall nargs");
        !          1148:        if (i > nap) {
        !          1149:                bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
        !          1150:                error = copyin((caddr_t)tf->tf_r[31], (caddr_t)(args + nap),
        !          1151:                    (i - nap) * sizeof(register_t));
        !          1152:        } else {
        !          1153:                bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
        !          1154:                error = 0;
        !          1155:        }
        !          1156:
        !          1157:        if (error != 0)
        !          1158:                goto bad;
        !          1159:        KERNEL_PROC_LOCK(p);
        !          1160: #ifdef SYSCALL_DEBUG
        !          1161:        scdebug_call(p, code, args);
        !          1162: #endif
        !          1163: #ifdef KTRACE
        !          1164:        if (KTRPOINT(p, KTR_SYSCALL))
        !          1165:                ktrsyscall(p, code, callp->sy_argsize, args);
        !          1166: #endif
        !          1167:        rval[0] = 0;
        !          1168:        rval[1] = tf->tf_r[3];
        !          1169: #if NSYSTRACE > 0
        !          1170:        if (ISSET(p->p_flag, P_SYSTRACE))
        !          1171:                error = systrace_redirect(code, p, args, rval);
        !          1172:        else
        !          1173: #endif
        !          1174:                error = (*callp->sy_call)(p, args, rval);
        !          1175:        /*
        !          1176:         * system call will look like:
        !          1177:         *       or r13, r0, <code>
        !          1178:         *       tb0 0, r0, <128> <- sxip
        !          1179:         *       br err           <- snip
        !          1180:         *       jmp r1           <- sfip
        !          1181:         *  err: or.u r3, r0, hi16(errno)
        !          1182:         *       st r2, r3, lo16(errno)
        !          1183:         *       subu r2, r0, 1
        !          1184:         *       jmp r1
        !          1185:         *
        !          1186:         * So, when we take syscall trap, sxip/snip/sfip will be as
        !          1187:         * shown above.
        !          1188:         * Given this,
        !          1189:         * 1. If the system call returned 0, need to skip nip.
        !          1190:         *      nip = fip, fip += 4
        !          1191:         *    (doesn't matter what fip + 4 will be but we will never
        !          1192:         *    execute this since jmp r1 at nip will change the execution flow.)
        !          1193:         * 2. If the system call returned an errno > 0, plug the value
        !          1194:         *    in r2, and leave nip and fip unchanged. This will have us
        !          1195:         *    executing "br err" on return to user space.
        !          1196:         * 3. If the system call code returned ERESTART,
        !          1197:         *    we need to rexecute the trap instruction. Back up the pipe
        !          1198:         *    line.
        !          1199:         *     fip = nip, nip = xip
        !          1200:         * 4. If the system call returned EJUSTRETURN, don't need to adjust
        !          1201:         *    any pointers.
        !          1202:         */
        !          1203:
        !          1204:        KERNEL_PROC_UNLOCK(p);
        !          1205:        switch (error) {
        !          1206:        case 0:
        !          1207:                tf->tf_r[2] = rval[0];
        !          1208:                tf->tf_r[3] = rval[1];
        !          1209:                tf->tf_epsr &= ~PSR_C;
        !          1210:                tf->tf_snip = tf->tf_sfip & ~NIP_E;
        !          1211:                tf->tf_sfip = tf->tf_snip + 4;
        !          1212:                break;
        !          1213:        case ERESTART:
        !          1214:                tf->tf_epsr &= ~PSR_C;
        !          1215:                tf->tf_sfip = tf->tf_snip & ~FIP_E;
        !          1216:                tf->tf_snip = tf->tf_sxip & ~NIP_E;
        !          1217:                break;
        !          1218:        case EJUSTRETURN:
        !          1219:                tf->tf_epsr &= ~PSR_C;
        !          1220:                break;
        !          1221:        default:
        !          1222: bad:
        !          1223:                if (p->p_emul->e_errno)
        !          1224:                        error = p->p_emul->e_errno[error];
        !          1225:                tf->tf_r[2] = error;
        !          1226:                tf->tf_epsr |= PSR_C;   /* fail */
        !          1227:                tf->tf_snip = tf->tf_snip & ~NIP_E;
        !          1228:                tf->tf_sfip = tf->tf_sfip & ~FIP_E;
        !          1229:                break;
        !          1230:        }
        !          1231: #ifdef SYSCALL_DEBUG
        !          1232:        KERNEL_PROC_LOCK(p);
        !          1233:        scdebug_ret(p, code, error, rval);
        !          1234:        KERNEL_PROC_UNLOCK(p);
        !          1235: #endif
        !          1236:        userret(p);
        !          1237: #ifdef KTRACE
        !          1238:        if (KTRPOINT(p, KTR_SYSRET)) {
        !          1239:                KERNEL_PROC_LOCK(p);
        !          1240:                ktrsysret(p, code, error, rval[0]);
        !          1241:                KERNEL_PROC_UNLOCK(p);
        !          1242:        }
        !          1243: #endif
        !          1244: }
        !          1245: #endif /* M88100 */
        !          1246:
        !          1247: #ifdef M88110
        !          1248: /* Instruction pointers operate differently on mc88110 */
        !          1249: void
        !          1250: m88110_syscall(register_t code, struct trapframe *tf)
        !          1251: {
        !          1252:        int i, nsys, nap;
        !          1253:        struct sysent *callp;
        !          1254:        struct proc *p;
        !          1255:        int error;
        !          1256:        register_t args[8], rval[2], *ap;
        !          1257:
        !          1258:        uvmexp.syscalls++;
        !          1259:
        !          1260:        p = curproc;
        !          1261:
        !          1262:        callp = p->p_emul->e_sysent;
        !          1263:        nsys  = p->p_emul->e_nsysent;
        !          1264:
        !          1265:        p->p_md.md_tf = tf;
        !          1266:
        !          1267:        /*
        !          1268:         * For 88k, all the arguments are passed in the registers (r2-r9),
        !          1269:         * and further arguments (if any) on stack.
        !          1270:         * For syscall (and __syscall), r2 (and r3) has the actual code.
        !          1271:         * __syscall  takes a quad syscall number, so that other
        !          1272:         * arguments are at their natural alignments.
        !          1273:         */
        !          1274:        ap = &tf->tf_r[2];
        !          1275:        nap = 8;        /* r2-r9 */
        !          1276:
        !          1277:        switch (code) {
        !          1278:        case SYS_syscall:
        !          1279:                code = *ap++;
        !          1280:                nap--;
        !          1281:                break;
        !          1282:        case SYS___syscall:
        !          1283:                if (callp != sysent)
        !          1284:                        break;
        !          1285:                code = ap[_QUAD_LOWWORD];
        !          1286:                ap += 2;
        !          1287:                nap -= 2;
        !          1288:                break;
        !          1289:        }
        !          1290:
        !          1291:        if (code < 0 || code >= nsys)
        !          1292:                callp += p->p_emul->e_nosys;
        !          1293:        else
        !          1294:                callp += code;
        !          1295:
        !          1296:        i = callp->sy_argsize / sizeof(register_t);
        !          1297:        if (i > sizeof(args) > sizeof(register_t))
        !          1298:                panic("syscall nargs");
        !          1299:        if (i > nap) {
        !          1300:                bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
        !          1301:                error = copyin((caddr_t)tf->tf_r[31], (caddr_t)(args + nap),
        !          1302:                    (i - nap) * sizeof(register_t));
        !          1303:        } else {
        !          1304:                bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
        !          1305:                error = 0;
        !          1306:        }
        !          1307:
        !          1308:        if (error != 0)
        !          1309:                goto bad;
        !          1310:        KERNEL_PROC_LOCK(p);
        !          1311: #ifdef SYSCALL_DEBUG
        !          1312:        scdebug_call(p, code, args);
        !          1313: #endif
        !          1314: #ifdef KTRACE
        !          1315:        if (KTRPOINT(p, KTR_SYSCALL))
        !          1316:                ktrsyscall(p, code, callp->sy_argsize, args);
        !          1317: #endif
        !          1318:        rval[0] = 0;
        !          1319:        rval[1] = tf->tf_r[3];
        !          1320: #if NSYSTRACE > 0
        !          1321:        if (ISSET(p->p_flag, P_SYSTRACE))
        !          1322:                error = systrace_redirect(code, p, args, rval);
        !          1323:        else
        !          1324: #endif
        !          1325:                error = (*callp->sy_call)(p, args, rval);
        !          1326:        /*
        !          1327:         * system call will look like:
        !          1328:         *       or r13, r0, <code>
        !          1329:         *       tb0 0, r0, <128> <- exip
        !          1330:         *       br err           <- enip
        !          1331:         *       jmp r1
        !          1332:         *  err: or.u r3, r0, hi16(errno)
        !          1333:         *       st r2, r3, lo16(errno)
        !          1334:         *       subu r2, r0, 1
        !          1335:         *       jmp r1
        !          1336:         *
        !          1337:         * So, when we take syscall trap, exip/enip will be as
        !          1338:         * shown above.
        !          1339:         * Given this,
        !          1340:         * 1. If the system call returned 0, need to jmp r1.
        !          1341:         *    exip += 8
        !          1342:         * 2. If the system call returned an errno > 0, increment
        !          1343:         *    exip += 4 and plug the value in r2. This will have us
        !          1344:         *    executing "br err" on return to user space.
        !          1345:         * 3. If the system call code returned ERESTART,
        !          1346:         *    we need to rexecute the trap instruction. leave exip as is.
        !          1347:         * 4. If the system call returned EJUSTRETURN, just return.
        !          1348:         *    exip += 4
        !          1349:         */
        !          1350:
        !          1351:        KERNEL_PROC_UNLOCK(p);
        !          1352:        switch (error) {
        !          1353:        case 0:
        !          1354:                tf->tf_r[2] = rval[0];
        !          1355:                tf->tf_r[3] = rval[1];
        !          1356:                tf->tf_epsr &= ~PSR_C;
        !          1357:                /* skip two instructions */
        !          1358:                if (tf->tf_exip & 1)
        !          1359:                        tf->tf_exip = tf->tf_enip + 4;
        !          1360:                else
        !          1361:                        tf->tf_exip += 4 + 4;
        !          1362:                break;
        !          1363:        case ERESTART:
        !          1364:                /*
        !          1365:                 * Reexecute the trap.
        !          1366:                 * exip is already at the trap instruction, so
        !          1367:                 * there is nothing to do.
        !          1368:                 */
        !          1369:                tf->tf_epsr &= ~PSR_C;
        !          1370:                break;
        !          1371:        case EJUSTRETURN:
        !          1372:                tf->tf_epsr &= ~PSR_C;
        !          1373:                /* skip one instruction */
        !          1374:                if (tf->tf_exip & 1)
        !          1375:                        tf->tf_exip = tf->tf_enip;
        !          1376:                else
        !          1377:                        tf->tf_exip += 4;
        !          1378:                break;
        !          1379:        default:
        !          1380: bad:
        !          1381:                if (p->p_emul->e_errno)
        !          1382:                        error = p->p_emul->e_errno[error];
        !          1383:                tf->tf_r[2] = error;
        !          1384:                tf->tf_epsr |= PSR_C;   /* fail */
        !          1385:                /* skip one instruction */
        !          1386:                if (tf->tf_exip & 1)
        !          1387:                        tf->tf_exip = tf->tf_enip;
        !          1388:                else
        !          1389:                        tf->tf_exip += 4;
        !          1390:                break;
        !          1391:        }
        !          1392:
        !          1393: #ifdef SYSCALL_DEBUG
        !          1394:        KERNEL_PROC_LOCK(p);
        !          1395:        scdebug_ret(p, code, error, rval);
        !          1396:        KERNEL_PROC_UNLOCK(p);
        !          1397: #endif
        !          1398:        userret(p);
        !          1399: #ifdef KTRACE
        !          1400:        if (KTRPOINT(p, KTR_SYSRET)) {
        !          1401:                KERNEL_PROC_LOCK(p);
        !          1402:                ktrsysret(p, code, error, rval[0]);
        !          1403:                KERNEL_PROC_UNLOCK(p);
        !          1404:        }
        !          1405: #endif
        !          1406: }
        !          1407: #endif /* M88110 */
        !          1408:
        !          1409: /*
        !          1410:  * Set up return-value registers as fork() libc stub expects,
        !          1411:  * and do normal return-to-user-mode stuff.
        !          1412:  */
        !          1413: void
        !          1414: child_return(arg)
        !          1415:        void *arg;
        !          1416: {
        !          1417:        struct proc *p = arg;
        !          1418:        struct trapframe *tf;
        !          1419:
        !          1420:        tf = (struct trapframe *)USER_REGS(p);
        !          1421:        tf->tf_r[2] = 0;
        !          1422:        tf->tf_r[3] = 0;
        !          1423:        tf->tf_epsr &= ~PSR_C;
        !          1424:        /* skip br instruction as in syscall() */
        !          1425: #ifdef M88100
        !          1426:        if (CPU_IS88100) {
        !          1427:                tf->tf_snip = tf->tf_sfip & XIP_ADDR;
        !          1428:                tf->tf_sfip = tf->tf_snip + 4;
        !          1429:        }
        !          1430: #endif
        !          1431: #ifdef M88110
        !          1432:        if (CPU_IS88110) {
        !          1433:                /* skip two instructions */
        !          1434:                if (tf->tf_exip & 1)
        !          1435:                        tf->tf_exip = tf->tf_enip + 4;
        !          1436:                else
        !          1437:                        tf->tf_exip += 4 + 4;
        !          1438:        }
        !          1439: #endif
        !          1440:
        !          1441:        KERNEL_PROC_UNLOCK(p);
        !          1442:        userret(p);
        !          1443:
        !          1444: #ifdef KTRACE
        !          1445:        if (KTRPOINT(p, KTR_SYSRET)) {
        !          1446:                KERNEL_PROC_LOCK(p);
        !          1447:                ktrsysret(p,
        !          1448:                    (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
        !          1449:                KERNEL_PROC_UNLOCK(p);
        !          1450:        }
        !          1451: #endif
        !          1452: }
        !          1453:
        !          1454: #ifdef PTRACE
        !          1455:
        !          1456: /*
        !          1457:  * User Single Step Debugging Support
        !          1458:  */
        !          1459:
        !          1460: #include <sys/ptrace.h>
        !          1461:
        !          1462: vaddr_t        ss_branch_taken(u_int, vaddr_t, struct reg *);
        !          1463: int    ss_get_value(struct proc *, vaddr_t, u_int *);
        !          1464: int    ss_inst_branch_or_call(u_int);
        !          1465: int    ss_put_breakpoint(struct proc *, vaddr_t, vaddr_t *, u_int *);
        !          1466:
        !          1467: #define        SYSCALL_INSTR   0xf000d080      /* tb0 0,r0,128 */
        !          1468:
        !          1469: int
        !          1470: ss_get_value(struct proc *p, vaddr_t addr, u_int *value)
        !          1471: {
        !          1472:        struct uio uio;
        !          1473:        struct iovec iov;
        !          1474:
        !          1475:        iov.iov_base = (caddr_t)value;
        !          1476:        iov.iov_len = sizeof(u_int);
        !          1477:        uio.uio_iov = &iov;
        !          1478:        uio.uio_iovcnt = 1;
        !          1479:        uio.uio_offset = (off_t)addr;
        !          1480:        uio.uio_resid = sizeof(u_int);
        !          1481:        uio.uio_segflg = UIO_SYSSPACE;
        !          1482:        uio.uio_rw = UIO_READ;
        !          1483:        uio.uio_procp = curproc;
        !          1484:        return (process_domem(curproc, p, &uio, PT_READ_I));
        !          1485: }
        !          1486:
        !          1487: int
        !          1488: ss_put_value(struct proc *p, vaddr_t addr, u_int value)
        !          1489: {
        !          1490:        struct uio uio;
        !          1491:        struct iovec iov;
        !          1492:
        !          1493:        iov.iov_base = (caddr_t)&value;
        !          1494:        iov.iov_len = sizeof(u_int);
        !          1495:        uio.uio_iov = &iov;
        !          1496:        uio.uio_iovcnt = 1;
        !          1497:        uio.uio_offset = (off_t)addr;
        !          1498:        uio.uio_resid = sizeof(u_int);
        !          1499:        uio.uio_segflg = UIO_SYSSPACE;
        !          1500:        uio.uio_rw = UIO_WRITE;
        !          1501:        uio.uio_procp = curproc;
        !          1502:        return (process_domem(curproc, p, &uio, PT_WRITE_I));
        !          1503: }
        !          1504:
        !          1505: /*
        !          1506:  * ss_branch_taken(instruction, pc, regs)
        !          1507:  *
        !          1508:  * instruction will be a control flow instruction location at address pc.
        !          1509:  * Branch taken is supposed to return the address to which the instruction
        !          1510:  * would jump if the branch is taken.
        !          1511:  *
        !          1512:  * This is different from branch_taken() in ddb, as we also need to process
        !          1513:  * system calls.
        !          1514:  */
        !          1515: vaddr_t
        !          1516: ss_branch_taken(u_int inst, vaddr_t pc, struct reg *regs)
        !          1517: {
        !          1518:        u_int regno;
        !          1519:
        !          1520:        /*
        !          1521:         * Quick check of the instruction. Note that we know we are only
        !          1522:         * invoked if ss_inst_branch_or_call() returns TRUE, so we do not
        !          1523:         * need to repeat the jpm, jsr and syscall stricter checks here.
        !          1524:         */
        !          1525:        switch (inst >> (32 - 5)) {
        !          1526:        case 0x18:      /* br */
        !          1527:        case 0x19:      /* bsr */
        !          1528:                /* signed 26 bit pc relative displacement, shift left 2 bits */
        !          1529:                inst = (inst & 0x03ffffff) << 2;
        !          1530:                /* check if sign extension is needed */
        !          1531:                if (inst & 0x08000000)
        !          1532:                        inst |= 0xf0000000;
        !          1533:                return (pc + inst);
        !          1534:
        !          1535:        case 0x1a:      /* bb0 */
        !          1536:        case 0x1b:      /* bb1 */
        !          1537:        case 0x1d:      /* bcnd */
        !          1538:                /* signed 16 bit pc relative displacement, shift left 2 bits */
        !          1539:                inst = (inst & 0x0000ffff) << 2;
        !          1540:                /* check if sign extension is needed */
        !          1541:                if (inst & 0x00020000)
        !          1542:                        inst |= 0xfffc0000;
        !          1543:                return (pc + inst);
        !          1544:
        !          1545:        case 0x1e:      /* jmp or jsr */
        !          1546:                regno = inst & 0x1f;    /* get the register value */
        !          1547:                return (regno == 0 ? 0 : regs->r[regno]);
        !          1548:
        !          1549:        default:        /* system call */
        !          1550:                /*
        !          1551:                 * The regular (pc + 4) breakpoint will match the error
        !          1552:                 * return. Successfull system calls return at (pc + 8),
        !          1553:                 * so we'll set up a branch breakpoint there.
        !          1554:                 */
        !          1555:                return (pc + 8);
        !          1556:        }
        !          1557: }
        !          1558:
        !          1559: int
        !          1560: ss_inst_branch_or_call(u_int ins)
        !          1561: {
        !          1562:        /* check high five bits */
        !          1563:        switch (ins >> (32 - 5)) {
        !          1564:        case 0x18: /* br */
        !          1565:        case 0x19: /* bsr */
        !          1566:        case 0x1a: /* bb0 */
        !          1567:        case 0x1b: /* bb1 */
        !          1568:        case 0x1d: /* bcnd */
        !          1569:                return (TRUE);
        !          1570:        case 0x1e: /* could be jmp or jsr */
        !          1571:                if ((ins & 0xfffff3e0) == 0xf400c000)
        !          1572:                        return (TRUE);
        !          1573:        }
        !          1574:
        !          1575:        return (FALSE);
        !          1576: }
        !          1577:
        !          1578: int
        !          1579: ss_put_breakpoint(struct proc *p, vaddr_t va, vaddr_t *bpva, u_int *bpsave)
        !          1580: {
        !          1581:        int rc;
        !          1582:
        !          1583:        /* Restore previous breakpoint if we did not trigger it. */
        !          1584:        if (*bpva != 0) {
        !          1585:                ss_put_value(p, *bpva, *bpsave);
        !          1586:                *bpva = 0;
        !          1587:        }
        !          1588:
        !          1589:        /* Save instruction. */
        !          1590:        if ((rc = ss_get_value(p, va, bpsave)) != 0)
        !          1591:                return (rc);
        !          1592:
        !          1593:        /* Store breakpoint instruction at the location now. */
        !          1594:        *bpva = va;
        !          1595:        return (ss_put_value(p, va, SSBREAKPOINT));
        !          1596: }
        !          1597:
        !          1598: int
        !          1599: process_sstep(struct proc *p, int sstep)
        !          1600: {
        !          1601:        struct reg *sstf = USER_REGS(p);
        !          1602:        unsigned pc, brpc;
        !          1603:        unsigned instr;
        !          1604:        int rc;
        !          1605:
        !          1606:        if (sstep == 0) {
        !          1607:                /* Restore previous breakpoints if any. */
        !          1608:                if (p->p_md.md_bp0va != 0) {
        !          1609:                        ss_put_value(p, p->p_md.md_bp0va, p->p_md.md_bp0save);
        !          1610:                        p->p_md.md_bp0va = 0;
        !          1611:                }
        !          1612:                if (p->p_md.md_bp1va != 0) {
        !          1613:                        ss_put_value(p, p->p_md.md_bp1va, p->p_md.md_bp1save);
        !          1614:                        p->p_md.md_bp1va = 0;
        !          1615:                }
        !          1616:
        !          1617:                return (0);
        !          1618:        }
        !          1619:
        !          1620:        /*
        !          1621:         * User was stopped at pc, e.g. the instruction at pc was not executed.
        !          1622:         * Fetch what's at the current location.
        !          1623:         */
        !          1624:        pc = PC_REGS(sstf);
        !          1625:        if ((rc = ss_get_value(p, pc, &instr)) != 0)
        !          1626:                return (rc);
        !          1627:
        !          1628:        /*
        !          1629:         * Find if this instruction may cause a branch, and set up a breakpoint
        !          1630:         * at the branch location.
        !          1631:         */
        !          1632:        if (ss_inst_branch_or_call(instr) || instr == SYSCALL_INSTR) {
        !          1633:                brpc = ss_branch_taken(instr, pc, sstf);
        !          1634:
        !          1635:                /* self-branches are hopeless */
        !          1636:                if (brpc != pc && brpc != 0) {
        !          1637:                        if ((rc = ss_put_breakpoint(p, brpc,
        !          1638:                            &p->p_md.md_bp1va, &p->p_md.md_bp1save)) != 0)
        !          1639:                                return (rc);
        !          1640:                }
        !          1641:        }
        !          1642:
        !          1643:        if ((rc = ss_put_breakpoint(p, pc + 4,
        !          1644:            &p->p_md.md_bp0va, &p->p_md.md_bp0save)) != 0)
        !          1645:                return (rc);
        !          1646:
        !          1647:        return (0);
        !          1648: }
        !          1649:
        !          1650: #endif /* PTRACE */
        !          1651:
        !          1652: #ifdef DIAGNOSTIC
        !          1653: void
        !          1654: splassert_check(int wantipl, const char *func)
        !          1655: {
        !          1656:        int oldipl;
        !          1657:
        !          1658:        /*
        !          1659:         * This will raise the spl if too low,
        !          1660:         * in a feeble attempt to reduce further damage.
        !          1661:         */
        !          1662:        oldipl = raiseipl(wantipl);
        !          1663:
        !          1664:        if (oldipl < wantipl) {
        !          1665:                splassert_fail(wantipl, oldipl, func);
        !          1666:        }
        !          1667: }
        !          1668: #endif
        !          1669:
        !          1670: /*
        !          1671:  * ld.d and st.d instructions referencing long aligned but not long long
        !          1672:  * aligned addresses will trigger a misaligned address exception.
        !          1673:  *
        !          1674:  * This routine attempts to recover these (valid) statements, by simulating
        !          1675:  * the split form of the instruction. If it fails, it returns the appropriate
        !          1676:  * signal number to deliver.
        !          1677:  *
        !          1678:  * Note that we do not attempt to do anything for .d.usr instructions - the
        !          1679:  * kernel never issues such instructions, and they cause a privileged
        !          1680:  * isntruction exception from userland.
        !          1681:  */
        !          1682: int
        !          1683: double_reg_fixup(struct trapframe *frame)
        !          1684: {
        !          1685:        u_int32_t pc, instr, value;
        !          1686:        int regno, store;
        !          1687:        vaddr_t addr;
        !          1688:
        !          1689:        /*
        !          1690:         * Decode the faulting instruction.
        !          1691:         */
        !          1692:
        !          1693:        pc = PC_REGS(&frame->tf_regs);
        !          1694:        if (copyin((void *)pc, &instr, sizeof(u_int32_t)) != 0)
        !          1695:                return SIGSEGV;
        !          1696:
        !          1697:        switch (instr & 0xfc00ff00) {
        !          1698:        case 0xf4001000:        /* ld.d rD, rS1, rS2 */
        !          1699:                addr = frame->tf_r[(instr >> 16) & 0x1f]
        !          1700:                    + frame->tf_r[(instr & 0x1f)];
        !          1701:                store = 0;
        !          1702:                break;
        !          1703:        case 0xf4002000:        /* st.d rD, rS1, rS2 */
        !          1704:                addr = frame->tf_r[(instr >> 16) & 0x1f]
        !          1705:                    + frame->tf_r[(instr & 0x1f)];
        !          1706:                store = 1;
        !          1707:                break;
        !          1708:        default:
        !          1709:                switch (instr & 0xfc000000) {
        !          1710:                case 0x10000000:        /* ld.d rD, rS, imm16 */
        !          1711:                        addr = (instr & 0x0000ffff) +
        !          1712:                            frame->tf_r[(instr >> 16) & 0x1f];
        !          1713:                        store = 0;
        !          1714:                        break;
        !          1715:                case 0x20000000:        /* st.d rD, rS, imm16 */
        !          1716:                        addr = (instr & 0x0000ffff) +
        !          1717:                            frame->tf_r[(instr >> 16) & 0x1f];
        !          1718:                        store = 1;
        !          1719:                        break;
        !          1720:                default:
        !          1721:                        return SIGBUS;
        !          1722:                }
        !          1723:                break;
        !          1724:        }
        !          1725:
        !          1726:        /* We only handle long but not long long aligned access here */
        !          1727:        if ((addr & 0x07) != 4)
        !          1728:                return SIGBUS;
        !          1729:
        !          1730:        regno = (instr >> 21) & 0x1f;
        !          1731:
        !          1732:        if (store) {
        !          1733:                /*
        !          1734:                 * Two word stores.
        !          1735:                 */
        !          1736:                value = frame->tf_r[regno++];
        !          1737:                if (copyout(&value, (void *)addr, sizeof(u_int32_t)) != 0)
        !          1738:                        return SIGSEGV;
        !          1739:                if (regno == 32)
        !          1740:                        value = 0;
        !          1741:                else
        !          1742:                        value = frame->tf_r[regno];
        !          1743:                if (copyout(&value, (void *)(addr + 4), sizeof(u_int32_t)) != 0)
        !          1744:                        return SIGSEGV;
        !          1745:        } else {
        !          1746:                /*
        !          1747:                 * Two word loads. r0 should be left unaltered, but the
        !          1748:                 * value should still be fetched even if it is discarded.
        !          1749:                 */
        !          1750:                if (copyin((void *)addr, &value, sizeof(u_int32_t)) != 0)
        !          1751:                        return SIGSEGV;
        !          1752:                if (regno != 0)
        !          1753:                        frame->tf_r[regno] = value;
        !          1754:                if (copyin((void *)(addr + 4), &value, sizeof(u_int32_t)) != 0)
        !          1755:                        return SIGSEGV;
        !          1756:                if (regno != 31)
        !          1757:                        frame->tf_r[regno + 1] = value;
        !          1758:        }
        !          1759:
        !          1760:        return 0;
        !          1761: }
        !          1762:
        !          1763: void
        !          1764: cache_flush(struct trapframe *tf)
        !          1765: {
        !          1766:        struct proc *p;
        !          1767:        struct pmap *pmap;
        !          1768:        paddr_t pa;
        !          1769:        vaddr_t va;
        !          1770:        vsize_t len, count;
        !          1771:
        !          1772:        if ((p = curproc) == NULL)
        !          1773:                p = &proc0;
        !          1774:
        !          1775:        p->p_md.md_tf = tf;
        !          1776:
        !          1777:        pmap = vm_map_pmap(&p->p_vmspace->vm_map);
        !          1778:        va = tf->tf_r[2];
        !          1779:        len = tf->tf_r[3];
        !          1780:
        !          1781:        if (/* va < VM_MIN_ADDRESS || */ va >= VM_MAXUSER_ADDRESS ||
        !          1782:            va + len <= va || va + len >= VM_MAXUSER_ADDRESS)
        !          1783:                len = 0;
        !          1784:
        !          1785:        while (len != 0) {
        !          1786:                count = min(len, PAGE_SIZE - (va & PAGE_MASK));
        !          1787:                if (pmap_extract(pmap, va, &pa) != FALSE)
        !          1788:                        dma_cachectl_pa(pa, count, DMA_CACHE_SYNC);
        !          1789:                va += count;
        !          1790:                len -= count;
        !          1791:        }
        !          1792:
        !          1793:        if (CPU_IS88100) {
        !          1794:                tf->tf_snip = tf->tf_snip & ~NIP_E;
        !          1795:                tf->tf_sfip = tf->tf_sfip & ~FIP_E;
        !          1796:        } else {
        !          1797:                /* skip instruction */
        !          1798:                if (tf->tf_exip & 1)
        !          1799:                        tf->tf_exip = tf->tf_enip;
        !          1800:                else
        !          1801:                        tf->tf_exip += 4;
        !          1802:        }
        !          1803:
        !          1804:        userret(p);
        !          1805: }

CVSweb