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

Annotation of sys/arch/solbourne/solbourne/trap.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: trap.c,v 1.9 2007/03/15 10:22:29 art Exp $    */
                      2: /*     OpenBSD: trap.c,v 1.42 2004/12/06 20:12:25 miod Exp     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1996
                      6:  *     The President and Fellows of Harvard College. All rights reserved.
                      7:  * Copyright (c) 1992, 1993
                      8:  *     The Regents of the University of California.  All rights reserved.
                      9:  *
                     10:  * This software was developed by the Computer Systems Engineering group
                     11:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     12:  * contributed to Berkeley.
                     13:  *
                     14:  * All advertising materials mentioning features or use of this software
                     15:  * must display the following acknowledgement:
                     16:  *     This product includes software developed by the University of
                     17:  *     California, Lawrence Berkeley Laboratory.
                     18:  *     This product includes software developed by Harvard University.
                     19:  *
                     20:  * Redistribution and use in source and binary forms, with or without
                     21:  * modification, are permitted provided that the following conditions
                     22:  * are met:
                     23:  * 1. Redistributions of source code must retain the above copyright
                     24:  *    notice, this list of conditions and the following disclaimer.
                     25:  * 2. Redistributions in binary form must reproduce the above copyright
                     26:  *    notice, this list of conditions and the following disclaimer in the
                     27:  *    documentation and/or other materials provided with the distribution.
                     28:  * 3. All advertising materials mentioning features or use of this software
                     29:  *    must display the following acknowledgement:
                     30:  *     This product includes software developed by the University of
                     31:  *     California, Berkeley and its contributors.
                     32:  *     This product includes software developed by Harvard University.
                     33:  * 4. Neither the name of the University nor the names of its contributors
                     34:  *    may be used to endorse or promote products derived from this software
                     35:  *    without specific prior written permission.
                     36:  *
                     37:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     38:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     39:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     40:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     41:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     42:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     43:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     44:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     45:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     46:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     47:  * SUCH DAMAGE.
                     48:  *
                     49:  *     @(#)trap.c      8.4 (Berkeley) 9/23/93
                     50:  */
                     51:
                     52: #include <sys/param.h>
                     53: #include <sys/systm.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/signalvar.h>
                     56: #include <sys/user.h>
                     57: #include <sys/kernel.h>
                     58: #include <sys/malloc.h>
                     59: #include <sys/resource.h>
                     60: #include <sys/signal.h>
                     61: #include <sys/wait.h>
                     62: #include <sys/syscall.h>
                     63: #include <sys/syslog.h>
                     64: #ifdef KTRACE
                     65: #include <sys/ktrace.h>
                     66: #endif
                     67:
                     68: #include "systrace.h"
                     69: #include <dev/systrace.h>
                     70:
                     71: #include <uvm/uvm_extern.h>
                     72:
                     73: #include <sparc/sparc/asm.h>
                     74: #include <machine/cpu.h>
                     75: #include <machine/ctlreg.h>
                     76: #include <machine/trap.h>
                     77: #include <machine/instr.h>
                     78: #include <machine/pmap.h>
                     79:
                     80: #include <machine/idt.h>
                     81: #include <machine/kap.h>
                     82:
                     83: #ifdef DDB
                     84: #include <machine/db_machdep.h>
                     85: #else
                     86: #include <machine/frame.h>
                     87: #endif
                     88: #ifdef COMPAT_SVR4
                     89: #include <machine/svr4_machdep.h>
                     90: #endif
                     91:
                     92: #include <sparc/fpu/fpu_extern.h>
                     93: #include <sparc/sparc/memreg.h>
                     94: #include <sparc/sparc/cpuvar.h>
                     95:
                     96: #ifdef DEBUG
                     97: int    rwindow_debug = 0;
                     98: #endif
                     99:
                    100: /*
                    101:  * Initial FPU state is all registers == all 1s, everything else == all 0s.
                    102:  * This makes every floating point register a signalling NaN, with sign bit
                    103:  * set, no matter how it is interpreted.  Appendix N of the Sparc V8 document
                    104:  * seems to imply that we should do this, and it does make sense.
                    105:  */
                    106: struct fpstate initfpstate = {
                    107:        { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0,
                    108:          ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }
                    109: };
                    110:
                    111: /*
                    112:  * There are more than 100 trap types, but most are unused.
                    113:  *
                    114:  * Trap type 0 is taken over as an `Asynchronous System Trap'.
                    115:  * This is left-over Vax emulation crap that should be fixed.
                    116:  *
                    117:  * Note that some of the Sparc v8 traps are actually handled by
                    118:  * the corresponding v7 routine, but listed here for completeness.
                    119:  * The Fujitsu Turbo-Sparc Guide also alludes to several more
                    120:  * unimplemented trap types, but doesn't give the nominal coding.
                    121:  */
                    122: static const char T[] = "trap";
                    123: const char *trap_type[] = {
                    124:        /* non-user vectors */
                    125:        "ast",                  /* 0 */
                    126:        "text fault",           /* 1 */
                    127:        "illegal instruction",  /* 2 */
                    128:        "privileged instruction",/*3 */
                    129:        "fp disabled",          /* 4 */
                    130:        "window overflow",      /* 5 */
                    131:        "window underflow",     /* 6 */
                    132:        "alignment fault",      /* 7 */
                    133:        "fp exception",         /* 8 */
                    134:        "data fault",           /* 9 */
                    135:        "tag overflow",         /* 0a */
                    136:        "watchpoint",           /* 0b */
                    137:        T, T, T, T, T,          /* 0c..10 */
                    138:        "level 1 int",          /* 11 */
                    139:        "level 2 int",          /* 12 */
                    140:        "level 3 int",          /* 13 */
                    141:        "level 4 int",          /* 14 */
                    142:        "level 5 int",          /* 15 */
                    143:        "level 6 int",          /* 16 */
                    144:        "level 7 int",          /* 17 */
                    145:        "level 8 int",          /* 18 */
                    146:        "level 9 int",          /* 19 */
                    147:        "level 10 int",         /* 1a */
                    148:        "level 11 int",         /* 1b */
                    149:        "level 12 int",         /* 1c */
                    150:        "level 13 int",         /* 1d */
                    151:        "level 14 int",         /* 1e */
                    152:        "level 15 int",         /* 1f */
                    153:        "double trap",          /* 20 */
                    154:        "v8 text error",        /* 21 */
                    155:        T, T,                   /* 22..23 */
                    156:        "v8 cp disabled",       /* 24 */
                    157:        "v8 unimp flush",       /* 25 */
                    158:        T, T,                   /* 26..27 */
                    159:        "v8 cp exception",      /* 28 */
                    160:        "v8 data error",        /* 29 */
                    161:        "v8 idiv by zero",      /* 2a */
                    162:        "v8 store error",       /* 2b */
                    163:        "dtlb miss",            /* 2c */
                    164:        T, T, T,                /* 2d..2f */
                    165:        T, T, T, T, T, T, T, T, /* 30..37 */
                    166:        T, T, T, T,             /* 38..3b */
                    167:        "itlb miss",            /* 3c */
                    168:        T, T, T,        /* 3d..3f */
                    169:        T, T, T, T, T, T, T, T, /* 40..48 */
                    170:        T, T, T, T, T, T, T, T, /* 48..4f */
                    171:        T, T, T, T, T, T, T, T, /* 50..57 */
                    172:        T, T, T, T, T, T, T, T, /* 58..5f */
                    173:        T, T, T, T, T, T, T, T, /* 60..67 */
                    174:        T, T, T, T, T, T, T, T, /* 68..6f */
                    175:        T, T, T, T, T, T, T, T, /* 70..77 */
                    176:        T, T, T, T, T, T, T, T, /* 78..7f */
                    177:
                    178:        /* user (software trap) vectors */
                    179:        "syscall",              /* 80 */
                    180:        "breakpoint",           /* 81 */
                    181:        "zero divide",          /* 82 */
                    182:        "flush windows",        /* 83 */
                    183:        "clean windows",        /* 84 */
                    184:        "range check",          /* 85 */
                    185:        "fix align",            /* 86 */
                    186:        "integer overflow",     /* 87 */
                    187:        "svr4 syscall",         /* 88 */
                    188:        "4.4 syscall",          /* 89 */
                    189:        "kgdb exec",            /* 8a */
                    190:        T, T, T, T, T,          /* 8b..8f */
                    191:        T, T, T, T, T, T, T, T, /* 9a..97 */
                    192:        T, T, T, T, T, T, T, T, /* 98..9f */
                    193:        "svr4 getcc",           /* a0 */
                    194:        "svr4 setcc",           /* a1 */
                    195:        "svr4 getpsr",          /* a2 */
                    196:        "svr4 setpsr",          /* a3 */
                    197:        "svr4 gethrtime",       /* a4 */
                    198:        "svr4 gethrvtime",      /* a5 */
                    199:        T,                      /* a6 */
                    200:        "svr4 gethrestime",     /* a7 */
                    201: };
                    202:
                    203: #define        N_TRAP_TYPES    (sizeof trap_type / sizeof *trap_type)
                    204:
                    205: static __inline void userret(struct proc *);
                    206: void trap(unsigned, int, int, struct trapframe *);
                    207: static __inline void share_fpu(struct proc *, struct trapframe *);
                    208: void mem_access_fault(unsigned, int, u_int, int, int, struct trapframe *);
                    209: void ecc_fault(unsigned, int, u_int, int, int, struct trapframe *);
                    210: void syscall(register_t, struct trapframe *, register_t);
                    211:
                    212: int ignore_bogus_traps = 0;
                    213:
                    214: int want_ast = 0;
                    215: /*
                    216:  * Define the code needed before returning to user mode, for
                    217:  * trap, mem_access_fault, and syscall.
                    218:  */
                    219: static __inline void
                    220: userret(struct proc *p)
                    221: {
                    222:        int sig;
                    223:
                    224:        /* take pending signals */
                    225:        while ((sig = CURSIG(p)) != 0)
                    226:                postsig(sig);
                    227:
                    228:        curpriority = p->p_priority = p->p_usrpri;
                    229: }
                    230:
                    231: /*
                    232:  * If someone stole the FPU while we were away, do not enable it
                    233:  * on return.  This is not done in userret() above as it must follow
                    234:  * the ktrsysret() in syscall().  Actually, it is likely that the
                    235:  * ktrsysret should occur before the call to userret.
                    236:  */
                    237: static __inline void share_fpu(p, tf)
                    238:        struct proc *p;
                    239:        struct trapframe *tf;
                    240: {
                    241:        if ((tf->tf_psr & PSR_EF) != 0 && cpuinfo.fpproc != p)
                    242:                tf->tf_psr &= ~PSR_EF;
                    243: }
                    244:
                    245: /*
                    246:  * Called from locore.s trap handling, for non-MMU-related traps.
                    247:  * (MMU-related traps go through mem_access_fault, below.)
                    248:  */
                    249: void
                    250: trap(type, psr, pc, tf)
                    251:        unsigned type;
                    252:        int psr, pc;
                    253:        struct trapframe *tf;
                    254: {
                    255:        struct proc *p;
                    256:        struct pcb *pcb;
                    257:        int n;
                    258:        union sigval sv;
                    259:
                    260:         sv.sival_int = pc; /* XXX fix for parm five of trapsignal() */
                    261:
                    262:        /* This steps the PC over the trap. */
                    263: #define        ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
                    264:
                    265:        uvmexp.traps++;
                    266:        /*
                    267:         * Generally, kernel traps cause a panic.  Any exceptions are
                    268:         * handled early here.
                    269:         */
                    270:        if (psr & PSR_PS) {
                    271: #ifdef DDB
                    272:                if (type == T_BREAKPOINT) {
                    273:                        write_all_windows();
                    274:                        if (kdb_trap(type, tf)) {
                    275:                                return;
                    276:                        }
                    277:                }
                    278: #endif
                    279: #ifdef DIAGNOSTIC
                    280:                /*
                    281:                 * Currently, we allow DIAGNOSTIC kernel code to
                    282:                 * flush the windows to record stack traces.
                    283:                 */
                    284:                if (type == T_FLUSHWIN) {
                    285:                        write_all_windows();
                    286:                        ADVANCE;
                    287:                        return;
                    288:                }
                    289: #endif
                    290:                /*
                    291:                 * Storing %fsr in cpu_attach will cause this trap
                    292:                 * even though the fpu has been enabled, if and only
                    293:                 * if there is no FPU.
                    294:                 */
                    295:                if (type == T_FPDISABLED && cold) {
                    296:                        ADVANCE;
                    297:                        return;
                    298:                }
                    299:        dopanic:
                    300:                printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n",
                    301:                       type, pc, tf->tf_npc, psr, PSR_BITS);
                    302:                if (type == T_RREGERROR)        /* 0x20 double fault */
                    303:                        printf("fcr %b fvar %08x fpar %08x fpsr %08x pdbr %08x\n",
                    304:                            lda(0, ASI_FCR), FCR_BITS, lda(0, ASI_FPAR),
                    305:                            lda(0, ASI_FPSR), lda(0, ASI_PDBR));
                    306:                panic(type < N_TRAP_TYPES ? trap_type[type] : T);
                    307:                /* NOTREACHED */
                    308:        }
                    309:        if ((p = curproc) == NULL)
                    310:                p = &proc0;
                    311:        pcb = &p->p_addr->u_pcb;
                    312:        p->p_md.md_tf = tf;     /* for ptrace/signals */
                    313:
                    314:        switch (type) {
                    315:
                    316:        default:
                    317:                if (type < 0x80) {
                    318:                        if (!ignore_bogus_traps)
                    319:                                goto dopanic;
                    320:                        printf("trap type 0x%x: pc=0x%x npc=0x%x psr=%b\n",
                    321:                               type, pc, tf->tf_npc, psr, PSR_BITS);
                    322:                        trapsignal(p, SIGILL, type, ILL_ILLOPC, sv);
                    323:                        break;
                    324:                }
                    325: #if defined(COMPAT_SVR4)
                    326: badtrap:
                    327: #endif
                    328:                /* the following message is gratuitous */
                    329:                /* ... but leave it in until we find anything */
                    330:                printf("%s[%d]: unimplemented software trap 0x%x\n",
                    331:                        p->p_comm, p->p_pid, type);
                    332:                trapsignal(p, SIGILL, type, ILL_ILLOPC, sv);
                    333:                break;
                    334:
                    335: #ifdef COMPAT_SVR4
                    336:        case T_SVR4_GETCC:
                    337:        case T_SVR4_SETCC:
                    338:        case T_SVR4_GETPSR:
                    339:        case T_SVR4_SETPSR:
                    340:        case T_SVR4_GETHRTIME:
                    341:        case T_SVR4_GETHRVTIME:
                    342:        case T_SVR4_GETHRESTIME:
                    343:                if (!svr4_trap(type, p))
                    344:                        goto badtrap;
                    345:                break;
                    346: #endif
                    347:
                    348:        case T_AST:
                    349:                want_ast = 0;
                    350:                if (p->p_flag & P_OWEUPC) {
                    351:                        ADDUPROF(p);
                    352:                }
                    353:                if (want_resched)
                    354:                        preempt(NULL);
                    355:                break;
                    356:
                    357:        case T_ILLINST:
                    358:                if ((n = emulinstr(pc, tf)) == 0) {
                    359:                        ADVANCE;
                    360:                        break;
                    361:                }
                    362:                trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
                    363:                break;
                    364:
                    365:        case T_PRIVINST:
                    366:                trapsignal(p, SIGILL, 0, ILL_PRVOPC, sv);
                    367:                break;
                    368:
                    369:        case T_FPDISABLED: {
                    370:                struct fpstate *fs = p->p_md.md_fpstate;
                    371:
                    372:                if (fs == NULL) {
                    373:                        fs = malloc(sizeof *fs, M_SUBPROC, M_WAITOK);
                    374:                        *fs = initfpstate;
                    375:                        p->p_md.md_fpstate = fs;
                    376:                }
                    377:                /*
                    378:                 * If we have not found an FPU, we have to emulate it.
                    379:                 */
                    380:                if (!foundfpu) {
                    381: #ifdef notyet
                    382:                        fpu_emulate(p, tf, fs);
                    383:                        break;
                    384: #else
                    385:                        trapsignal(p, SIGFPE, 0, FPE_FLTINV, sv);
                    386:                        break;
                    387: #endif
                    388:                }
                    389:                /*
                    390:                 * We may have more FPEs stored up and/or ops queued.
                    391:                 * If they exist, handle them and get out.  Otherwise,
                    392:                 * resolve the FPU state, turn it on, and try again.
                    393:                 */
                    394:                if (fs->fs_qsize) {
                    395:                        fpu_cleanup(p, fs);
                    396:                        break;
                    397:                }
                    398:                if (cpuinfo.fpproc != p) {      /* we do not have it */
                    399:                        if (cpuinfo.fpproc != NULL) /* someone else had it */
                    400:                                savefpstate(cpuinfo.fpproc->p_md.md_fpstate);
                    401:                        loadfpstate(fs);
                    402:                        cpuinfo.fpproc = p;     /* now we do have it */
                    403:                        uvmexp.fpswtch++;
                    404:                }
                    405:                tf->tf_psr |= PSR_EF;
                    406:                break;
                    407:        }
                    408:
                    409:        case T_WINOF:
                    410:                if (rwindow_save(p))
                    411:                        sigexit(p, SIGILL);
                    412:                break;
                    413:
                    414: #define read_rw(src, dst) \
                    415:        copyin((caddr_t)(src), (caddr_t)(dst), sizeof(struct rwindow))
                    416:
                    417:        case T_RWRET:
                    418:                /*
                    419:                 * T_RWRET is a window load needed in order to rett.
                    420:                 * It simply needs the window to which tf->tf_out[6]
                    421:                 * (%sp) points.  There are no user or saved windows now.
                    422:                 * Copy the one from %sp into pcb->pcb_rw[0] and set
                    423:                 * nsaved to -1.  If we decide to deliver a signal on
                    424:                 * our way out, we will clear nsaved.
                    425:                 */
                    426:                if (pcb->pcb_uw || pcb->pcb_nsaved)
                    427:                        panic("trap T_RWRET 1");
                    428: #ifdef DEBUG
                    429:                if (rwindow_debug)
                    430:                        printf("%s[%d]: rwindow: pcb<-stack: 0x%x\n",
                    431:                                p->p_comm, p->p_pid, tf->tf_out[6]);
                    432: #endif
                    433:                if (read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
                    434:                        sigexit(p, SIGILL);
                    435:                if (pcb->pcb_nsaved)
                    436:                        panic("trap T_RWRET 2");
                    437:                pcb->pcb_nsaved = -1;           /* mark success */
                    438:                break;
                    439:
                    440:        case T_WINUF:
                    441:                /*
                    442:                 * T_WINUF is a real window underflow, from a restore
                    443:                 * instruction.  It needs to have the contents of two
                    444:                 * windows---the one belonging to the restore instruction
                    445:                 * itself, which is at its %sp, and the one belonging to
                    446:                 * the window above, which is at its %fp or %i6---both
                    447:                 * in the pcb.  The restore's window may still be in
                    448:                 * the cpu; we need to force it out to the stack.
                    449:                 */
                    450: #ifdef DEBUG
                    451:                if (rwindow_debug)
                    452:                        printf("%s[%d]: rwindow: T_WINUF 0: pcb<-stack: 0x%x\n",
                    453:                                p->p_comm, p->p_pid, tf->tf_out[6]);
                    454: #endif
                    455:                write_user_windows();
                    456:                if (rwindow_save(p) || read_rw(tf->tf_out[6], &pcb->pcb_rw[0]))
                    457:                        sigexit(p, SIGILL);
                    458: #ifdef DEBUG
                    459:                if (rwindow_debug)
                    460:                        printf("%s[%d]: rwindow: T_WINUF 1: pcb<-stack: 0x%x\n",
                    461:                                p->p_comm, p->p_pid, pcb->pcb_rw[0].rw_in[6]);
                    462: #endif
                    463:                if (read_rw(pcb->pcb_rw[0].rw_in[6], &pcb->pcb_rw[1]))
                    464:                        sigexit(p, SIGILL);
                    465:                if (pcb->pcb_nsaved)
                    466:                        panic("trap T_WINUF");
                    467:                pcb->pcb_nsaved = -1;           /* mark success */
                    468:                break;
                    469:
                    470:        case T_ALIGN:
                    471:                if ((p->p_md.md_flags & MDP_FIXALIGN) != 0 &&
                    472:                    fixalign(p, tf) == 0) {
                    473:                        ADVANCE;
                    474:                        break;
                    475:                }
                    476:                trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv);
                    477:                break;
                    478:
                    479:        case T_FPE:
                    480:                /*
                    481:                 * Clean up after a floating point exception.
                    482:                 * fpu_cleanup can (and usually does) modify the
                    483:                 * state we save here, so we must `give up' the FPU
                    484:                 * chip context.  (The software and hardware states
                    485:                 * will not match once fpu_cleanup does its job, so
                    486:                 * we must not save again later.)
                    487:                 */
                    488:                if (p != cpuinfo.fpproc)
                    489:                        panic("fpe without being the FP user");
                    490:                savefpstate(p->p_md.md_fpstate);
                    491:                cpuinfo.fpproc = NULL;
                    492:                /* tf->tf_psr &= ~PSR_EF; */    /* share_fpu will do this */
                    493:                fpu_cleanup(p, p->p_md.md_fpstate);
                    494:                /* fpu_cleanup posts signals if needed */
                    495: #if 0          /* ??? really never??? */
                    496:                ADVANCE;
                    497: #endif
                    498:                break;
                    499:
                    500:        case T_TAGOF:
                    501:                trapsignal(p, SIGEMT, 0, EMT_TAGOVF, sv);
                    502:                break;
                    503:
                    504:        case T_CPDISABLED:
                    505:                uprintf("coprocessor instruction\n");   /* XXX */
                    506:                trapsignal(p, SIGILL, 0, ILL_COPROC, sv);
                    507:                break;
                    508:
                    509:        case T_BREAKPOINT:
                    510:                trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv);
                    511:                break;
                    512:
                    513:        case T_DIV0:
                    514:        case T_IDIV0:
                    515:                ADVANCE;
                    516:                trapsignal(p, SIGFPE, 0, FPE_INTDIV, sv);
                    517:                break;
                    518:
                    519:        case T_FLUSHWIN:
                    520:                write_user_windows();
                    521: #ifdef probably_slower_since_this_is_usually_false
                    522:                if (pcb->pcb_nsaved && rwindow_save(p))
                    523:                        sigexit(p, SIGILL);
                    524: #endif
                    525:                ADVANCE;
                    526:                break;
                    527:
                    528:        case T_CLEANWIN:
                    529:                uprintf("T_CLEANWIN\n");        /* XXX */
                    530:                ADVANCE;
                    531:                break;
                    532:
                    533:        case T_RANGECHECK:
                    534:                uprintf("T_RANGECHECK\n");      /* XXX */
                    535:                ADVANCE;
                    536:                trapsignal(p, SIGILL, 0, ILL_ILLOPN, sv);
                    537:                break;
                    538:
                    539:        case T_FIXALIGN:
                    540: #ifdef DEBUG_ALIGN
                    541:                uprintf("T_FIXALIGN\n");
                    542: #endif
                    543:                /* User wants us to fix alignment faults */
                    544:                p->p_md.md_flags |= MDP_FIXALIGN;
                    545:                ADVANCE;
                    546:                break;
                    547:
                    548:        case T_INTOF:
                    549:                uprintf("T_INTOF\n");           /* XXX */
                    550:                ADVANCE;
                    551:                trapsignal(p, SIGFPE, FPE_INTOVF_TRAP, FPE_INTOVF, sv);
                    552:                break;
                    553:        }
                    554:        userret(p);
                    555:        share_fpu(p, tf);
                    556: #undef ADVANCE
                    557: }
                    558:
                    559: /*
                    560:  * Save windows from PCB into user stack, and return 0.  This is used on
                    561:  * window overflow pseudo-traps (from locore.s, just before returning to
                    562:  * user mode) and when ptrace or sendsig needs a consistent state.
                    563:  * As a side effect, rwindow_save() always sets pcb_nsaved to 0,
                    564:  * clobbering the `underflow restore' indicator if it was -1.
                    565:  *
                    566:  * If the windows cannot be saved, pcb_nsaved is restored and we return -1.
                    567:  */
                    568: int
                    569: rwindow_save(p)
                    570:        struct proc *p;
                    571: {
                    572:        struct pcb *pcb = &p->p_addr->u_pcb;
                    573:        struct rwindow *rw = &pcb->pcb_rw[0];
                    574:        int i;
                    575:
                    576:        i = pcb->pcb_nsaved;
                    577:        if (i < 0) {
                    578:                pcb->pcb_nsaved = 0;
                    579:                return (0);
                    580:        }
                    581:        if (i == 0)
                    582:                return (0);
                    583: #ifdef DEBUG
                    584:        if (rwindow_debug)
                    585:                printf("%s[%d]: rwindow: pcb->stack:", p->p_comm, p->p_pid);
                    586: #endif
                    587:        do {
                    588: #ifdef DEBUG
                    589:                if (rwindow_debug)
                    590:                        printf(" 0x%x", rw[1].rw_in[6]);
                    591: #endif
                    592:                if (copyout((caddr_t)rw, (caddr_t)rw[1].rw_in[6],
                    593:                    sizeof *rw))
                    594:                        return (-1);
                    595:                rw++;
                    596:        } while (--i > 0);
                    597: #ifdef DEBUG
                    598:        if (rwindow_debug)
                    599:                printf("\n");
                    600: #endif
                    601:        pcb->pcb_nsaved = 0;
                    602:        return (0);
                    603: }
                    604:
                    605: /*
                    606:  * Kill user windows (before exec) by writing back to stack or pcb
                    607:  * and then erasing any pcb tracks.  Otherwise we might try to write
                    608:  * the registers into the new process after the exec.
                    609:  */
                    610: void
                    611: pmap_unuse_final(p)
                    612:        struct proc *p;
                    613: {
                    614:
                    615:        write_user_windows();
                    616:        p->p_addr->u_pcb.pcb_nsaved = 0;
                    617: }
                    618:
                    619: /*
                    620:  * Called from locore.s trap handling, for synchronous memory faults.
                    621:  *
                    622:  * This duplicates a lot of logic in trap() and perhaps should be
                    623:  * moved there; but the bus-error-register parameters are unique to
                    624:  * this routine.
                    625:  *
                    626:  * Since synchronous errors accumulate during prefetch, we can have
                    627:  * more than one `cause'.  But we do not care what the cause, here;
                    628:  * we just want to page in the page and try again.
                    629:  */
                    630: void
                    631: mem_access_fault(type, ser, v, pc, psr, tf)
                    632:        unsigned type;
                    633:        int ser;
                    634:        u_int v;
                    635:        int pc, psr;
                    636:        struct trapframe *tf;
                    637: {
                    638:        struct proc *p;
                    639:        struct vmspace *vm;
                    640:        vaddr_t va;
                    641:        int rv;
                    642:        vm_prot_t ftype;
                    643:        int onfault;
                    644:        union sigval sv;
                    645:        u_int isr;
                    646:
                    647:        uvmexp.traps++;
                    648:        if ((p = curproc) == NULL)      /* safety check */
                    649:                p = &proc0;
                    650:
                    651:        if (type == T_DATAFAULT && (ser & FCR_EXTERNAL) != 0) {
                    652:                /*
                    653:                 * For external faults, check the iCU status.
                    654:                 */
                    655:
                    656:                isr = lda(ICU_ISR, ASI_PHYS_IO);
                    657:
                    658:                /*
                    659:                 * Sometimes the interrupt register is empty... and I have
                    660:                 * no idea what we are supposed to do in such situations.
                    661:                 */
                    662:                if (isr == 0) {
                    663: #ifdef DEBUG
                    664:                        printf("external data fault, fcr %b pc %08x fvar %08x fpar %08x fpsr %08x pdbr %08x\n",
                    665:                            ser, FCR_BITS, pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR), lda(0, ASI_PDBR));
                    666: #ifdef DDB
                    667:                        Debugger();
                    668: #endif
                    669: #endif
                    670:                        ser &= ~FCR_EXTERNAL;
                    671:                        if (ser == 0)
                    672:                                goto out;
                    673:                } else {
                    674:                        /*
                    675:                         * This is either an unrecoverable DMA or ECC error,
                    676:                         * or a bus timeout.
                    677:                         * XXX should restart the operation if retry timeout.
                    678:                         */
                    679:                        panic("data fault: fcr %b isr %b pc %08x addr %08x fpar %08x fpsr %08x",
                    680:                            ser, FCR_BITS, isr, ISR_BITS,
                    681:                            pc, v, lda(0, ASI_FPAR), lda(0, ASI_FPSR));
                    682:                }
                    683:        }
                    684:
                    685:        /*
                    686:         * Figure out what to pass the VM code, and ignore the sva register
                    687:         * value in v on text faults (text faults are always at pc).
                    688:         * Kernel faults are somewhat different: text faults are always
                    689:         * illegal, and data faults are extra complex.  User faults must
                    690:         * set p->p_md.md_tf, in case we decide to deliver a signal.  Check
                    691:         * for illegal virtual addresses early since those can induce more
                    692:         * faults.
                    693:         */
                    694:        if (type == T_TEXTFAULT)
                    695:                v = pc;
                    696:        ftype = ser & FCR_RO ? VM_PROT_WRITE : VM_PROT_READ;
                    697:        va = trunc_page(v);
                    698:        if (psr & PSR_PS) {
                    699:                extern char Lfsbail[];
                    700:                if (type == T_TEXTFAULT) {
                    701:                        /*
                    702:                         * If we are trying to figure on which processor mask
                    703:                         * we run, we might trigger a text fault with
                    704:                         * pcb_onfault set.
                    705:                         * This is normal; don't panic there.
                    706:                         */
                    707:                        if (cold && p->p_addr->u_pcb.pcb_onfault != NULL)
                    708:                                goto kfault;
                    709:                        (void) splhigh();
                    710:                        printf("text fault: pc=0x%x fcr=%b\n", pc,
                    711:                               ser, FCR_BITS);
                    712:                        panic("kernel fault");
                    713:                        /* NOTREACHED */
                    714:                }
                    715:                /*
                    716:                 * If this was an access that we shouldn't try to page in,
                    717:                 * resume at the fault handler without any action.
                    718:                 */
                    719:                if (p->p_addr && p->p_addr->u_pcb.pcb_onfault == Lfsbail)
                    720:                        goto kfault;
                    721:
                    722:                /*
                    723:                 * During autoconfiguration, faults are never OK unless
                    724:                 * pcb_onfault is set.  Once running normally we must allow
                    725:                 * exec() to cause copy-on-write faults to kernel addresses.
                    726:                 */
                    727:                if (cold)
                    728:                        goto kfault;
                    729:                if (va >= VM_MIN_KERNEL_ADDRESS) {
                    730:                        if (uvm_fault(kernel_map, va, 0, ftype) == 0)
                    731:                                return;
                    732:                        goto kfault;
                    733:                }
                    734:        } else
                    735:                p->p_md.md_tf = tf;
                    736:
                    737:        vm = p->p_vmspace;
                    738:        rv = uvm_fault(&vm->vm_map, (vaddr_t)va, 0, ftype);
                    739:
                    740:        /*
                    741:         * If this was a stack access we keep track of the maximum
                    742:         * accessed stack size.  Also, if vm_fault gets a protection
                    743:         * failure it is due to accessing the stack region outside
                    744:         * the current limit and we need to reflect that as an access
                    745:         * error.
                    746:         */
                    747:        if ((caddr_t)va >= vm->vm_maxsaddr) {
                    748:                if (rv == 0)
                    749:                        uvm_grow(p, va);
                    750:                else if (rv == EACCES)
                    751:                        rv = EFAULT;
                    752:        }
                    753:        if (rv != 0) {
                    754:                /*
                    755:                 * If doing copyin/out, return to onfault address.  Any
                    756:                 * other page fault in kernel, die; if user fault, deliver
                    757:                 * SIGSEGV.
                    758:                 */
                    759:                if (psr & PSR_PS) {
                    760: kfault:
                    761:                        onfault = p->p_addr ?
                    762:                            (int)p->p_addr->u_pcb.pcb_onfault : 0;
                    763:                        if (!onfault) {
                    764:                                (void) splhigh();
                    765:                                printf("data fault: pc=0x%x addr=0x%x fcr=%b\n",
                    766:                                       pc, v, ser, FCR_BITS);
                    767:                                panic("kernel fault");
                    768:                                /* NOTREACHED */
                    769:                        }
                    770:                        tf->tf_pc = onfault;
                    771:                        tf->tf_npc = onfault + 4;
                    772:                        return;
                    773:                }
                    774:
                    775:                sv.sival_int = v;
                    776:                trapsignal(p, SIGSEGV, (ser & FCR_RO) ? VM_PROT_WRITE :
                    777:                    VM_PROT_READ, SEGV_MAPERR, sv);
                    778:        }
                    779: out:
                    780:        if ((psr & PSR_PS) == 0) {
                    781:                userret(p);
                    782:                share_fpu(p, tf);
                    783:        }
                    784: }
                    785:
                    786: void
                    787: ecc_fault(type, ser, v, pc, psr, tf)
                    788:        unsigned type;
                    789:        int ser;
                    790:        u_int v;
                    791:        int pc, psr;
                    792:        struct trapframe *tf;
                    793: {
                    794:        /* XXX */
                    795:        panic("ecc_fault");
                    796: }
                    797:
                    798: /*
                    799:  * System calls.  `pc' is just a copy of tf->tf_pc.
                    800:  *
                    801:  * Note that the things labelled `out' registers in the trapframe were the
                    802:  * `in' registers within the syscall trap code (because of the automatic
                    803:  * `save' effect of each trap).  They are, however, the %o registers of the
                    804:  * thing that made the system call, and are named that way here.
                    805:  */
                    806: void
                    807: syscall(code, tf, pc)
                    808:        register_t code;
                    809:        struct trapframe *tf;
                    810:        register_t pc;
                    811: {
                    812:        int i, nsys, *ap, nap;
                    813:        struct sysent *callp;
                    814:        struct proc *p;
                    815:        int error, new;
                    816:        struct args {
                    817:                register_t i[8];
                    818:        } args;
                    819:        register_t rval[2];
                    820: #ifdef DIAGNOSTIC
                    821:        extern struct pcb *cpcb;
                    822: #endif
                    823:
                    824:        uvmexp.syscalls++;
                    825:        p = curproc;
                    826: #ifdef DIAGNOSTIC
                    827:        if (tf->tf_psr & PSR_PS)
                    828:                panic("syscall");
                    829:        if (cpcb != &p->p_addr->u_pcb)
                    830:                panic("syscall cpcb/ppcb");
                    831:        if (tf != (struct trapframe *)((caddr_t)cpcb + USPACE) - 1)
                    832:                panic("syscall trapframe");
                    833: #endif
                    834:        p->p_md.md_tf = tf;
                    835:        new = code & (SYSCALL_G7RFLAG | SYSCALL_G2RFLAG);
                    836:        code &= ~(SYSCALL_G7RFLAG | SYSCALL_G2RFLAG);
                    837:
                    838:        callp = p->p_emul->e_sysent;
                    839:        nsys = p->p_emul->e_nsysent;
                    840:
                    841:        /*
                    842:         * The first six system call arguments are in the six %o registers.
                    843:         * Any arguments beyond that are in the `argument extension' area
                    844:         * of the user's stack frame (see <machine/frame.h>).
                    845:         *
                    846:         * Check for ``special'' codes that alter this, namely syscall and
                    847:         * __syscall.  The latter takes a quad syscall number, so that other
                    848:         * arguments are at their natural alignments.  Adjust the number
                    849:         * of ``easy'' arguments as appropriate; we will copy the hard
                    850:         * ones later as needed.
                    851:         */
                    852:        ap = &tf->tf_out[0];
                    853:        nap = 6;
                    854:
                    855:        switch (code) {
                    856:        case SYS_syscall:
                    857:                code = *ap++;
                    858:                nap--;
                    859:                break;
                    860:        case SYS___syscall:
                    861:                if (callp != sysent)
                    862:                        break;
                    863:                code = ap[_QUAD_LOWWORD];
                    864:                ap += 2;
                    865:                nap -= 2;
                    866:                break;
                    867:        }
                    868:
                    869:        if (code < 0 || code >= nsys)
                    870:                callp += p->p_emul->e_nosys;
                    871:        else {
                    872:                callp += code;
                    873:                i = callp->sy_argsize / sizeof(register_t);
                    874:                if (i > nap) {  /* usually false */
                    875:                        if (i > 8)
                    876:                                panic("syscall nargs");
                    877:                        error = copyin((caddr_t)tf->tf_out[6] +
                    878:                            offsetof(struct frame, fr_argx),
                    879:                            (caddr_t)&args.i[nap], (i - nap) * sizeof(register_t));
                    880:                        if (error) {
                    881: #ifdef KTRACE
                    882:                                if (KTRPOINT(p, KTR_SYSCALL))
                    883:                                        ktrsyscall(p, code,
                    884:                                            callp->sy_argsize, args.i);
                    885: #endif
                    886:                                goto bad;
                    887:                        }
                    888:                        i = nap;
                    889:                }
                    890:                copywords(ap, args.i, i * sizeof(register_t));
                    891:        }
                    892: #ifdef KTRACE
                    893:        if (KTRPOINT(p, KTR_SYSCALL))
                    894:                ktrsyscall(p, code, callp->sy_argsize, args.i);
                    895: #endif
                    896:        rval[0] = 0;
                    897:        rval[1] = tf->tf_out[1];
                    898: #if NSYSTRACE > 0
                    899:        if (ISSET(p->p_flag, P_SYSTRACE))
                    900:                error = systrace_redirect(code, p, &args, rval);
                    901:        else
                    902: #endif
                    903:                error = (*callp->sy_call)(p, &args, rval);
                    904:
                    905:        switch (error) {
                    906:        case 0:
                    907:                /* Note: fork() does not return here in the child */
                    908:                tf->tf_out[0] = rval[0];
                    909:                tf->tf_out[1] = rval[1];
                    910:                if (new) {
                    911:                        /* jmp %g2 (or %g7, deprecated) on success */
                    912:                        i = tf->tf_global[new & SYSCALL_G2RFLAG ? 2 : 7];
                    913:                        if (i & 3) {
                    914:                                error = EINVAL;
                    915:                                goto bad;
                    916:                        }
                    917:                } else {
                    918:                        /* old system call convention: clear C on success */
                    919:                        tf->tf_psr &= ~PSR_C;   /* success */
                    920:                        i = tf->tf_npc;
                    921:                }
                    922:                tf->tf_pc = i;
                    923:                tf->tf_npc = i + 4;
                    924:                break;
                    925:
                    926:        case ERESTART:
                    927:        case EJUSTRETURN:
                    928:                /* nothing to do */
                    929:                break;
                    930:
                    931:        default:
                    932:        bad:
                    933:                if (p->p_emul->e_errno)
                    934:                        error = p->p_emul->e_errno[error];
                    935:                tf->tf_out[0] = error;
                    936:                tf->tf_psr |= PSR_C;    /* fail */
                    937:                i = tf->tf_npc;
                    938:                tf->tf_pc = i;
                    939:                tf->tf_npc = i + 4;
                    940:                break;
                    941:        }
                    942:
                    943:        userret(p);
                    944: #ifdef KTRACE
                    945:        if (KTRPOINT(p, KTR_SYSRET))
                    946:                ktrsysret(p, code, error, rval[0]);
                    947: #endif
                    948:        share_fpu(p, tf);
                    949: }
                    950:
                    951: /*
                    952:  * Process the tail end of a fork() for the child.
                    953:  */
                    954: void
                    955: child_return(arg)
                    956:        void *arg;
                    957: {
                    958:        struct proc *p = arg;
                    959:        struct trapframe *tf = p->p_md.md_tf;
                    960:
                    961:        /*
                    962:         * Return values in the frame set by cpu_fork().
                    963:         */
                    964:        tf->tf_out[0] = 0;
                    965:        tf->tf_out[1] = 0;
                    966:        tf->tf_psr &= ~PSR_C;
                    967:
                    968:        userret(p);
                    969: #ifdef KTRACE
                    970:        if (KTRPOINT(p, KTR_SYSRET))
                    971:                ktrsysret(p,
                    972:                    (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
                    973: #endif
                    974: }

CVSweb