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

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

1.1     ! nbrk        1: /*     $OpenBSD: trap.c,v 1.78 2007/04/26 21:36:32 kettenis Exp $      */
        !             2: /*     $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
        !             6:  * Copyright (C) 1995, 1996 TooLs GmbH.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *     This product includes software developed by TooLs GmbH.
        !            20:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            26:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            27:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            28:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            29:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            30:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            31:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            32:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  */
        !            34: #include <sys/param.h>
        !            35: #include <sys/proc.h>
        !            36: #include <sys/signalvar.h>
        !            37: #include <sys/reboot.h>
        !            38: #include <sys/syscall.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/user.h>
        !            41: #include <sys/ktrace.h>
        !            42: #include <sys/pool.h>
        !            43:
        !            44: #include <dev/cons.h>
        !            45:
        !            46: #include <machine/cpu.h>
        !            47: #include <machine/fpu.h>
        !            48: #include <machine/frame.h>
        !            49: #include <machine/pcb.h>
        !            50: #include <machine/pmap.h>
        !            51: #include <machine/psl.h>
        !            52: #include <machine/trap.h>
        !            53: #include <machine/db_machdep.h>
        !            54:
        !            55: #include "systrace.h"
        !            56: #include <dev/systrace.h>
        !            57:
        !            58: #include <uvm/uvm_extern.h>
        !            59:
        !            60: #include <ddb/db_extern.h>
        !            61: #include <ddb/db_sym.h>
        !            62: #include <ddb/db_output.h>
        !            63:
        !            64: static int fix_unaligned(struct proc *p, struct trapframe *frame);
        !            65: int badaddr(char *addr, u_int32_t len);
        !            66: static __inline void userret(struct proc *);
        !            67: void trap(struct trapframe *frame);
        !            68:
        !            69: /* These definitions should probably be somewhere else                         XXX */
        !            70: #define        FIRSTARG        3               /* first argument is in reg 3 */
        !            71: #define        NARGREG         8               /* 8 args are in registers */
        !            72: #define        MOREARGS(sp)    ((caddr_t)((int)(sp) + 8)) /* more args go here */
        !            73:
        !            74: #ifdef DDB
        !            75: void ppc_dumpbt(struct trapframe *frame);
        !            76:
        !            77: void
        !            78: ppc_dumpbt(struct trapframe *frame)
        !            79: {
        !            80:        u_int32_t addr;
        !            81:        /* dumpframe is defined in db_trace.c */
        !            82:        addr=frame->fixreg[1];
        !            83:        while (addr != 0)
        !            84:                addr = db_dumpframe(addr, db_printf);
        !            85:        return;
        !            86: }
        !            87: #endif
        !            88:
        !            89: #ifdef ALTIVEC
        !            90: /*
        !            91:  * Save state of the vector processor, This is done lazily in the hope
        !            92:  * that few processes in the system will be using the vector unit
        !            93:  * and that the exception time taken to switch them will be less than
        !            94:  * the necessary time to save the vector on every context switch.
        !            95:  *
        !            96:  * Also note that in this version, the VRSAVE register is saved with
        !            97:  * the state of the current process holding the vector processor,
        !            98:  * and the contents of that register are not used to optimize the save.
        !            99:  *
        !           100:  * This can lead to VRSAVE corruption, data passing between processes,
        !           101:  * because this register is accessable without the MSR[VEC] bit set.
        !           102:  * To store/restore this cleanly a processor identifier bit would need
        !           103:  * to be saved and this register saved on every context switch.
        !           104:  * Since we do not use the information, we may be able to get by
        !           105:  * with not saving it rigorously.
        !           106:  */
        !           107: void
        !           108: save_vec(struct proc *p)
        !           109: {
        !           110:        struct pcb *pcb = &p->p_addr->u_pcb;
        !           111:        struct vreg *pcb_vr = pcb->pcb_vr;
        !           112:        u_int32_t oldmsr, msr;
        !           113:
        !           114:        if (p == NULL)
        !           115:                return;
        !           116:
        !           117:        /* first we enable vector so that we dont throw an exception
        !           118:         * in kernel mode
        !           119:         */
        !           120:        oldmsr = ppc_mfmsr();
        !           121:        msr = oldmsr | PSL_VEC;
        !           122:        ppc_mtmsr(msr);
        !           123:        __asm__ volatile ("sync;isync");
        !           124:
        !           125:        pcb->pcb_vr->vrsave = ppc_mfvrsave();
        !           126:
        !           127: #define STR(x) #x
        !           128: #define SAVE_VEC_REG(reg, addr)   \
        !           129:        __asm__ volatile ("stvxl %0, 0, %1" :: "n"(reg),"r" (addr));
        !           130:
        !           131:        SAVE_VEC_REG(0,&pcb_vr->vreg[0]);
        !           132:        SAVE_VEC_REG(1,&pcb_vr->vreg[1]);
        !           133:        SAVE_VEC_REG(2,&pcb_vr->vreg[2]);
        !           134:        SAVE_VEC_REG(3,&pcb_vr->vreg[3]);
        !           135:        SAVE_VEC_REG(4,&pcb_vr->vreg[4]);
        !           136:        SAVE_VEC_REG(5,&pcb_vr->vreg[5]);
        !           137:        SAVE_VEC_REG(6,&pcb_vr->vreg[6]);
        !           138:        SAVE_VEC_REG(7,&pcb_vr->vreg[7]);
        !           139:        SAVE_VEC_REG(8,&pcb_vr->vreg[8]);
        !           140:        SAVE_VEC_REG(9,&pcb_vr->vreg[9]);
        !           141:        SAVE_VEC_REG(10,&pcb_vr->vreg[10]);
        !           142:        SAVE_VEC_REG(11,&pcb_vr->vreg[11]);
        !           143:        SAVE_VEC_REG(12,&pcb_vr->vreg[12]);
        !           144:        SAVE_VEC_REG(13,&pcb_vr->vreg[13]);
        !           145:        SAVE_VEC_REG(14,&pcb_vr->vreg[14]);
        !           146:        SAVE_VEC_REG(15,&pcb_vr->vreg[15]);
        !           147:        SAVE_VEC_REG(16,&pcb_vr->vreg[16]);
        !           148:        SAVE_VEC_REG(17,&pcb_vr->vreg[17]);
        !           149:        SAVE_VEC_REG(18,&pcb_vr->vreg[18]);
        !           150:        SAVE_VEC_REG(19,&pcb_vr->vreg[19]);
        !           151:        SAVE_VEC_REG(20,&pcb_vr->vreg[20]);
        !           152:        SAVE_VEC_REG(21,&pcb_vr->vreg[21]);
        !           153:        SAVE_VEC_REG(22,&pcb_vr->vreg[22]);
        !           154:        SAVE_VEC_REG(23,&pcb_vr->vreg[23]);
        !           155:        SAVE_VEC_REG(24,&pcb_vr->vreg[24]);
        !           156:        SAVE_VEC_REG(25,&pcb_vr->vreg[25]);
        !           157:        SAVE_VEC_REG(26,&pcb_vr->vreg[26]);
        !           158:        SAVE_VEC_REG(27,&pcb_vr->vreg[27]);
        !           159:        SAVE_VEC_REG(28,&pcb_vr->vreg[28]);
        !           160:        SAVE_VEC_REG(29,&pcb_vr->vreg[29]);
        !           161:        SAVE_VEC_REG(30,&pcb_vr->vreg[30]);
        !           162:        SAVE_VEC_REG(31,&pcb_vr->vreg[31]);
        !           163:        __asm__ volatile ("mfvscr 0");
        !           164:        SAVE_VEC_REG(0,&pcb_vr->vscr);
        !           165:
        !           166:        /* fix kernel msr back */
        !           167:        ppc_mtmsr(oldmsr);
        !           168: }
        !           169:
        !           170: /*
        !           171:  * Copy the context of a given process into the vector registers.
        !           172:  */
        !           173: void
        !           174: enable_vec(struct proc *p)
        !           175: {
        !           176:        struct pcb *pcb = &p->p_addr->u_pcb;
        !           177:        struct vreg *pcb_vr = pcb->pcb_vr;
        !           178:        u_int32_t oldmsr, msr;
        !           179:
        !           180:        /* If this is the very first altivec instruction executed
        !           181:         * by this process, create a context.
        !           182:         */
        !           183:        if (pcb->pcb_vr == NULL) {
        !           184:                pcb->pcb_vr = pool_get(&ppc_vecpl, PR_WAITOK);
        !           185:                bzero(pcb->pcb_vr, sizeof *(pcb->pcb_vr));
        !           186:        }
        !           187:
        !           188:        /* first we enable vector so that we dont throw an exception
        !           189:         * in kernel mode
        !           190:         */
        !           191:        oldmsr = ppc_mfmsr();
        !           192:        msr = oldmsr | PSL_VEC;
        !           193:        ppc_mtmsr(msr);
        !           194:        __asm__ volatile ("sync;isync");
        !           195:
        !           196: #define LOAD_VEC_REG(reg, addr)   \
        !           197:        __asm__ volatile ("lvxl %0, 0, %1" :: "n"(reg), "r" (addr));
        !           198:
        !           199:        LOAD_VEC_REG(0, &pcb_vr->vscr);
        !           200:        __asm__ volatile ("mtvscr 0");
        !           201:        ppc_mtvrsave(pcb_vr->vrsave);
        !           202:
        !           203:        LOAD_VEC_REG(0, &pcb_vr->vreg[0]);
        !           204:        LOAD_VEC_REG(1, &pcb_vr->vreg[1]);
        !           205:        LOAD_VEC_REG(2, &pcb_vr->vreg[2]);
        !           206:        LOAD_VEC_REG(3, &pcb_vr->vreg[3]);
        !           207:        LOAD_VEC_REG(4, &pcb_vr->vreg[4]);
        !           208:        LOAD_VEC_REG(5, &pcb_vr->vreg[5]);
        !           209:        LOAD_VEC_REG(6, &pcb_vr->vreg[6]);
        !           210:        LOAD_VEC_REG(7, &pcb_vr->vreg[7]);
        !           211:        LOAD_VEC_REG(8, &pcb_vr->vreg[8]);
        !           212:        LOAD_VEC_REG(9, &pcb_vr->vreg[9]);
        !           213:        LOAD_VEC_REG(10, &pcb_vr->vreg[10]);
        !           214:        LOAD_VEC_REG(11, &pcb_vr->vreg[11]);
        !           215:        LOAD_VEC_REG(12, &pcb_vr->vreg[12]);
        !           216:        LOAD_VEC_REG(13, &pcb_vr->vreg[13]);
        !           217:        LOAD_VEC_REG(14, &pcb_vr->vreg[14]);
        !           218:        LOAD_VEC_REG(15, &pcb_vr->vreg[15]);
        !           219:        LOAD_VEC_REG(16, &pcb_vr->vreg[16]);
        !           220:        LOAD_VEC_REG(17, &pcb_vr->vreg[17]);
        !           221:        LOAD_VEC_REG(18, &pcb_vr->vreg[18]);
        !           222:        LOAD_VEC_REG(19, &pcb_vr->vreg[19]);
        !           223:        LOAD_VEC_REG(20, &pcb_vr->vreg[20]);
        !           224:        LOAD_VEC_REG(21, &pcb_vr->vreg[21]);
        !           225:        LOAD_VEC_REG(22, &pcb_vr->vreg[22]);
        !           226:        LOAD_VEC_REG(23, &pcb_vr->vreg[23]);
        !           227:        LOAD_VEC_REG(24, &pcb_vr->vreg[24]);
        !           228:        LOAD_VEC_REG(25, &pcb_vr->vreg[25]);
        !           229:        LOAD_VEC_REG(26, &pcb_vr->vreg[26]);
        !           230:        LOAD_VEC_REG(27, &pcb_vr->vreg[27]);
        !           231:        LOAD_VEC_REG(28, &pcb_vr->vreg[28]);
        !           232:        LOAD_VEC_REG(29, &pcb_vr->vreg[29]);
        !           233:        LOAD_VEC_REG(30, &pcb_vr->vreg[30]);
        !           234:        LOAD_VEC_REG(31, &pcb_vr->vreg[31]);
        !           235:
        !           236:        /* fix kernel msr back */
        !           237:        ppc_mtmsr(oldmsr);
        !           238: }
        !           239: #endif /* ALTIVEC */
        !           240:
        !           241: static __inline void
        !           242: userret(struct proc *p)
        !           243: {
        !           244:        int sig;
        !           245:
        !           246:        /* take pending signals */
        !           247:        while ((sig = CURSIG(p)) != 0)
        !           248:                postsig(sig);
        !           249:        curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
        !           250: }
        !           251:
        !           252: void
        !           253: trap(struct trapframe *frame)
        !           254: {
        !           255:        struct cpu_info *ci = curcpu();
        !           256:        struct proc *p = curproc;
        !           257:        int type = frame->exc;
        !           258:        union sigval sv;
        !           259:        char *name;
        !           260:        db_expr_t offset;
        !           261:
        !           262:        if (frame->srr1 & PSL_PR) {
        !           263:                type |= EXC_USER;
        !           264:        }
        !           265:
        !           266:        switch (type) {
        !           267:        case EXC_TRC|EXC_USER:
        !           268:                {
        !           269:                        sv.sival_int = frame->srr0;
        !           270:                        KERNEL_PROC_LOCK(p);
        !           271:                        trapsignal(p, SIGTRAP, type, TRAP_TRACE, sv);
        !           272:                        KERNEL_PROC_UNLOCK(p);
        !           273:                }
        !           274:                break;
        !           275:
        !           276:        case EXC_MCHK:
        !           277:                {
        !           278:                        faultbuf *fb;
        !           279:
        !           280:                        if ((fb = p->p_addr->u_pcb.pcb_onfault)) {
        !           281:                                p->p_addr->u_pcb.pcb_onfault = 0;
        !           282:                                frame->srr0 = fb->pc;           /* PC */
        !           283:                                frame->srr1 = fb->sr;           /* SR */
        !           284:                                frame->fixreg[1] = fb->sp;      /* SP */
        !           285:                                frame->fixreg[3] = 1;           /* != 0 */
        !           286:                                frame->cr = fb->cr;
        !           287:                                bcopy(&fb->regs[0], &frame->fixreg[13], 19*4);
        !           288:                                return;
        !           289:                        }
        !           290:                }
        !           291:                goto brain_damage;
        !           292:
        !           293:        case EXC_DSI:
        !           294:                {
        !           295:                        struct vm_map *map;
        !           296:                        vaddr_t va;
        !           297:                        int ftype;
        !           298:                        faultbuf *fb;
        !           299:
        !           300:                        map = kernel_map;
        !           301:                        va = frame->dar;
        !           302:                        if ((va >> ADDR_SR_SHIFT) == PPC_USER_SR) {
        !           303:                                sr_t user_sr;
        !           304:
        !           305:                                asm ("mfsr %0, %1"
        !           306:                                     : "=r"(user_sr) : "K"(PPC_USER_SR));
        !           307:                                va &= ADDR_PIDX | ADDR_POFF;
        !           308:                                va |= user_sr << ADDR_SR_SHIFT;
        !           309:                                map = &p->p_vmspace->vm_map;
        !           310:                                if (pte_spill_v(map->pmap, va, frame->dsisr, 0))
        !           311:                                        return;
        !           312:                        }
        !           313:                        if (frame->dsisr & DSISR_STORE)
        !           314:                                ftype = VM_PROT_READ | VM_PROT_WRITE;
        !           315:                        else
        !           316:                                ftype = VM_PROT_READ;
        !           317:                        if (uvm_fault(map, trunc_page(va), 0, ftype) == 0)
        !           318:                                return;
        !           319:
        !           320:                        if ((fb = p->p_addr->u_pcb.pcb_onfault)) {
        !           321:                                p->p_addr->u_pcb.pcb_onfault = 0;
        !           322:                                frame->srr0 = fb->pc;           /* PC */
        !           323:                                frame->fixreg[1] = fb->sp;      /* SP */
        !           324:                                frame->fixreg[3] = 1;           /* != 0 */
        !           325:                                frame->cr = fb->cr;
        !           326:                                bcopy(&fb->regs[0], &frame->fixreg[13], 19*4);
        !           327:                                return;
        !           328:                        }
        !           329:                        map = kernel_map;
        !           330:                }
        !           331: printf("kern dsi on addr %x iar %x\n", frame->dar, frame->srr0);
        !           332:                goto brain_damage;
        !           333:        case EXC_DSI|EXC_USER:
        !           334:                {
        !           335:                        int ftype, vftype;
        !           336:
        !           337:                        /* Try spill handler first */
        !           338:                        if (pte_spill_v(p->p_vmspace->vm_map.pmap,
        !           339:                            frame->dar, frame->dsisr, 0))
        !           340:                                break;
        !           341:
        !           342:                        KERNEL_PROC_LOCK(p);
        !           343:                        if (frame->dsisr & DSISR_STORE) {
        !           344:                                ftype = VM_PROT_READ | VM_PROT_WRITE;
        !           345:                                vftype = VM_PROT_WRITE;
        !           346:                        } else
        !           347:                                vftype = ftype = VM_PROT_READ;
        !           348:                        if (uvm_fault(&p->p_vmspace->vm_map,
        !           349:                                     trunc_page(frame->dar), 0, ftype) == 0) {
        !           350:                                uvm_grow(p, trunc_page(frame->dar));
        !           351:                                KERNEL_PROC_UNLOCK(p);
        !           352:                                break;
        !           353:                        }
        !           354:
        !           355: #if 0
        !           356: printf("dsi on addr %x iar %x lr %x\n", frame->dar, frame->srr0,frame->lr);
        !           357: #endif
        !           358: /*
        !           359:  * keep this for later in case we want it later.
        !           360: */
        !           361:                        sv.sival_int = frame->dar;
        !           362:                        trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv);
        !           363:                        KERNEL_PROC_UNLOCK(p);
        !           364:                }
        !           365:                break;
        !           366:        case EXC_ISI|EXC_USER:
        !           367:                {
        !           368:                        int ftype;
        !           369:
        !           370:                        /* Try spill handler */
        !           371:                        if (pte_spill_v(p->p_vmspace->vm_map.pmap,
        !           372:                            frame->srr0, 0, 1))
        !           373:                                break;
        !           374:
        !           375:                        KERNEL_PROC_LOCK(p);
        !           376:                        ftype = VM_PROT_READ | VM_PROT_EXECUTE;
        !           377:                        if (uvm_fault(&p->p_vmspace->vm_map,
        !           378:                            trunc_page(frame->srr0), 0, ftype) == 0) {
        !           379:                                uvm_grow(p, trunc_page(frame->srr0));
        !           380:                                KERNEL_PROC_UNLOCK(p);
        !           381:                                break;
        !           382:                        }
        !           383:                        KERNEL_PROC_UNLOCK(p);
        !           384:                }
        !           385: #if 0
        !           386: printf("isi iar %x lr %x\n", frame->srr0, frame->lr);
        !           387: #endif
        !           388:                /* FALLTHROUGH */
        !           389:        case EXC_MCHK|EXC_USER:
        !           390: /* XXX Likely that returning from this trap is bogus... */
        !           391: /* XXX Have to make sure that sigreturn does the right thing. */
        !           392:                sv.sival_int = frame->srr0;
        !           393:                KERNEL_PROC_LOCK(p);
        !           394:                trapsignal(p, SIGSEGV, VM_PROT_EXECUTE, SEGV_MAPERR, sv);
        !           395:                KERNEL_PROC_UNLOCK(p);
        !           396:                break;
        !           397:        case EXC_SC|EXC_USER:
        !           398:                {
        !           399:                        struct sysent *callp;
        !           400:                        size_t argsize;
        !           401:                        register_t code, error;
        !           402:                        register_t *params, rval[2];
        !           403:                        int nsys, n;
        !           404:                        register_t args[10];
        !           405:
        !           406:                        uvmexp.syscalls++;
        !           407:
        !           408:                        nsys = p->p_emul->e_nsysent;
        !           409:                        callp = p->p_emul->e_sysent;
        !           410:
        !           411:                        code = frame->fixreg[0];
        !           412:                        params = frame->fixreg + FIRSTARG;
        !           413:
        !           414:                        switch (code) {
        !           415:                        case SYS_syscall:
        !           416:                                /*
        !           417:                                 * code is first argument,
        !           418:                                 * followed by actual args.
        !           419:                                 */
        !           420:                                code = *params++;
        !           421:                                break;
        !           422:                        case SYS___syscall:
        !           423:                                /*
        !           424:                                 * Like syscall, but code is a quad,
        !           425:                                 * so as to maintain quad alignment
        !           426:                                 * for the rest of the args.
        !           427:                                 */
        !           428:                                if (callp != sysent)
        !           429:                                        break;
        !           430:                                params++;
        !           431:                                code = *params++;
        !           432:                                break;
        !           433:                        default:
        !           434:                                break;
        !           435:                        }
        !           436:                        if (code < 0 || code >= nsys)
        !           437:                                callp += p->p_emul->e_nosys;
        !           438:                        else
        !           439:                                callp += code;
        !           440:                        argsize = callp->sy_argsize;
        !           441:                        n = NARGREG - (params - (frame->fixreg + FIRSTARG));
        !           442:                        if (argsize > n * sizeof(register_t)) {
        !           443:                                bcopy(params, args, n * sizeof(register_t));
        !           444:
        !           445:                                error = copyin(MOREARGS(frame->fixreg[1]),
        !           446:                                   args + n, argsize - n * sizeof(register_t));
        !           447:                                if (error) {
        !           448: #ifdef KTRACE
        !           449:                                        /* Can't get all the arguments! */
        !           450:                                        if (KTRPOINT(p, KTR_SYSCALL))
        !           451:                                                ktrsyscall(p, code,
        !           452:                                                           argsize, args);
        !           453: #endif
        !           454:                                        goto syscall_bad;
        !           455:                                }
        !           456:                                params = args;
        !           457:                        }
        !           458:
        !           459:                        KERNEL_PROC_LOCK(p);
        !           460: #ifdef KTRACE
        !           461:                        if (KTRPOINT(p, KTR_SYSCALL))
        !           462:                                ktrsyscall(p, code, argsize, params);
        !           463: #endif
        !           464:                        rval[0] = 0;
        !           465:                        rval[1] = frame->fixreg[FIRSTARG + 1];
        !           466:
        !           467: #ifdef SYSCALL_DEBUG
        !           468:                        scdebug_call(p, code, params);
        !           469: #endif
        !           470:
        !           471:
        !           472: #if NSYSTRACE > 0
        !           473:                        if (ISSET(p->p_flag, P_SYSTRACE))
        !           474:                                error = systrace_redirect(code, p, params,
        !           475:                                    rval);
        !           476:                        else
        !           477: #endif
        !           478:                                error = (*callp->sy_call)(p, params, rval);
        !           479:                        KERNEL_PROC_UNLOCK(p);
        !           480:                        switch (error) {
        !           481:                        case 0:
        !           482:                                frame->fixreg[0] = error;
        !           483:                                frame->fixreg[FIRSTARG] = rval[0];
        !           484:                                frame->fixreg[FIRSTARG + 1] = rval[1];
        !           485:                                frame->cr &= ~0x10000000;
        !           486:                                break;
        !           487:                        case ERESTART:
        !           488:                                /*
        !           489:                                 * Set user's pc back to redo the system call.
        !           490:                                 */
        !           491:                                frame->srr0 -= 4;
        !           492:                                break;
        !           493:                        case EJUSTRETURN:
        !           494:                                /* nothing to do */
        !           495:                                break;
        !           496:                        default:
        !           497: syscall_bad:
        !           498:                                if (p->p_emul->e_errno)
        !           499:                                        error = p->p_emul->e_errno[error];
        !           500:                                frame->fixreg[0] = error;
        !           501:                                frame->fixreg[FIRSTARG] = error;
        !           502:                                frame->fixreg[FIRSTARG + 1] = rval[1];
        !           503:                                frame->cr |= 0x10000000;
        !           504:                                break;
        !           505:                        }
        !           506: #ifdef SYSCALL_DEBUG
        !           507:                        KERNEL_PROC_LOCK(p);
        !           508:                        scdebug_ret(p, code, error, rval);
        !           509:                        KERNEL_PROC_UNLOCK(p);
        !           510: #endif
        !           511: #ifdef KTRACE
        !           512:                        if (KTRPOINT(p, KTR_SYSRET)) {
        !           513:                                KERNEL_PROC_LOCK(p);
        !           514:                                ktrsysret(p, code, error, rval[0]);
        !           515:                                KERNEL_PROC_UNLOCK(p);
        !           516:                        }
        !           517: #endif
        !           518:                }
        !           519:                break;
        !           520:
        !           521:        case EXC_FPU|EXC_USER:
        !           522:                if (ci->ci_fpuproc)
        !           523:                        save_fpu();
        !           524:                uvmexp.fpswtch++;
        !           525:                enable_fpu(p);
        !           526:                break;
        !           527:
        !           528:        case EXC_ALI|EXC_USER:
        !           529:                /* alignment exception
        !           530:                 * we check to see if this can be fixed up
        !           531:                 * by the code that fixes the typical gcc misaligned code
        !           532:                 * then kill the process if not.
        !           533:                 */
        !           534:                if (fix_unaligned(p, frame) == 0)
        !           535:                        frame->srr0 += 4;
        !           536:                else {
        !           537:                        sv.sival_int = frame->srr0;
        !           538:                        KERNEL_PROC_LOCK(p);
        !           539:                        trapsignal(p, SIGSEGV, VM_PROT_EXECUTE, SEGV_MAPERR,
        !           540:                                sv);
        !           541:                        KERNEL_PROC_UNLOCK(p);
        !           542:                }
        !           543:                break;
        !           544:
        !           545:        default:
        !           546:
        !           547: brain_damage:
        !           548: /*
        !           549: mpc_print_pci_stat();
        !           550: */
        !           551:
        !           552: #ifdef DDB
        !           553:                /* set up registers */
        !           554:                db_save_regs(frame);
        !           555:                db_find_sym_and_offset(frame->srr0, &name, &offset);
        !           556: #else
        !           557:                name = NULL;
        !           558: #endif
        !           559:                if (!name) {
        !           560:                        name = "0";
        !           561:                        offset = frame->srr0;
        !           562:                }
        !           563:                panic ("trap type %x at %x (%s+0x%lx) lr %x",
        !           564:                        type, frame->srr0, name, offset, frame->lr);
        !           565:
        !           566:
        !           567:        case EXC_PGM|EXC_USER:
        !           568:        {
        !           569: #if 0
        !           570:                char *errstr[8];
        !           571:                int errnum = 0;
        !           572:
        !           573:                if (frame->srr1 & (1<<(31-11))) {
        !           574:                        /* floating point enabled program exception */
        !           575:                        errstr[errnum] = "floating point";
        !           576:                        errnum++;
        !           577:                }
        !           578:                if (frame->srr1 & (1<<(31-12))) {
        !           579:                        /* illegal instruction program exception */
        !           580:                        errstr[errnum] = "illegal instruction";
        !           581:                        errnum++;
        !           582:                }
        !           583:                if (frame->srr1 & (1<<(31-13))) {
        !           584:                        /* privileged instruction exception */
        !           585:                        errstr[errnum] = "privileged instr";
        !           586:                        errnum++;
        !           587:                }
        !           588: #endif
        !           589:                if (frame->srr1 & (1<<(31-14))) {
        !           590: #if 0
        !           591:                        errstr[errnum] = "trap instr";
        !           592:                        errnum++;
        !           593: #endif
        !           594:                        sv.sival_int = frame->srr0;
        !           595:                        KERNEL_PROC_LOCK(p);
        !           596:                        trapsignal(p, SIGTRAP, type, TRAP_BRKPT, sv);
        !           597:                        KERNEL_PROC_UNLOCK(p);
        !           598:                        break;
        !           599:                }
        !           600: #if 0
        !           601:                if (frame->srr1 & (1<<(31-15))) {
        !           602:                        errstr[errnum] = "previous address";
        !           603:                        errnum++;
        !           604:                }
        !           605: #endif
        !           606: #if 0
        !           607: printf("pgm iar %x srr1 %x\n", frame->srr0, frame->srr1);
        !           608: {
        !           609: int i;
        !           610: for (i = 0; i < errnum; i++) {
        !           611:        printf("\t[%s]\n", errstr[i]);
        !           612: }
        !           613: }
        !           614: #endif
        !           615:                sv.sival_int = frame->srr0;
        !           616:                KERNEL_PROC_LOCK(p);
        !           617:                trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
        !           618:                KERNEL_PROC_UNLOCK(p);
        !           619:                break;
        !           620:        }
        !           621:        case EXC_PGM:
        !           622:                /* should check for correct byte here or panic */
        !           623: #ifdef DDB
        !           624:                db_save_regs(frame);
        !           625:                cnpollc(TRUE);
        !           626:                db_trap(T_BREAKPOINT, 0);
        !           627:                cnpollc(FALSE);
        !           628: #else
        !           629:                panic("trap EXC_PGM");
        !           630: #endif
        !           631:                break;
        !           632:
        !           633:        /* This is not really a perf exception, but is an ALTIVEC unavail
        !           634:         * if we do not handle it, kill the process with illegal instruction.
        !           635:         */
        !           636:        case EXC_PERF|EXC_USER:
        !           637: #ifdef ALTIVEC
        !           638:        case EXC_VEC|EXC_USER:
        !           639:                if (ci->ci_vecproc)
        !           640:                        save_vec(ci->ci_vecproc);
        !           641:
        !           642:                ci->ci_vecproc = p;
        !           643:                enable_vec(p);
        !           644:                break;
        !           645: #else  /* ALTIVEC */
        !           646:                sv.sival_int = frame->srr0;
        !           647:                KERNEL_PROC_LOCK(p);
        !           648:                trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
        !           649:                KERNEL_PROC_UNLOCK(p);
        !           650:                break;
        !           651: #endif
        !           652:
        !           653:        case EXC_VECAST|EXC_USER:
        !           654:                KERNEL_PROC_LOCK(p);
        !           655:                trapsignal(p, SIGFPE, 0, FPE_FLTRES, sv);
        !           656:                KERNEL_PROC_UNLOCK(p);
        !           657:                break;
        !           658:
        !           659:        case EXC_AST|EXC_USER:
        !           660:                uvmexp.softs++;
        !           661:                ci->ci_astpending = 0;          /* we are about to do it */
        !           662:                if (p->p_flag & P_OWEUPC) {
        !           663:                        KERNEL_PROC_LOCK(p);
        !           664:                        ADDUPROF(p);
        !           665:                        KERNEL_PROC_UNLOCK(p);
        !           666:                }
        !           667:                if (ci->ci_want_resched)
        !           668:                        preempt(NULL);
        !           669:                break;
        !           670:        }
        !           671:
        !           672:        userret(p);
        !           673:
        !           674:        /*
        !           675:         * If someone stole the fpu while we were away, disable it
        !           676:         */
        !           677:        if (p != ci->ci_fpuproc)
        !           678:                frame->srr1 &= ~PSL_FP;
        !           679:        else if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
        !           680:                frame->srr1 |= PSL_FP;
        !           681:
        !           682: #ifdef ALTIVEC
        !           683:        /*
        !           684:         * If someone stole the vector unit while we were away, disable it
        !           685:         */
        !           686:        if (p == ci->ci_vecproc)
        !           687:                frame->srr1 |= PSL_VEC;
        !           688:        else
        !           689:                frame->srr1 &= ~PSL_VEC;
        !           690: #endif /* ALTIVEC */
        !           691: }
        !           692:
        !           693: void
        !           694: child_return(void *arg)
        !           695: {
        !           696:        struct proc *p = (struct proc *)arg;
        !           697:        struct trapframe *tf = trapframe(p);
        !           698:
        !           699:        tf->fixreg[0] = 0;
        !           700:        tf->fixreg[FIRSTARG] = 0;
        !           701:        tf->fixreg[FIRSTARG + 1] = 1;
        !           702:        tf->cr &= ~0x10000000;
        !           703:        /* Disable FPU, VECT, as we can't be fpuproc */
        !           704:        tf->srr1 &= ~(PSL_FP|PSL_VEC);
        !           705:
        !           706:        KERNEL_PROC_UNLOCK(p);
        !           707:
        !           708:        userret(p);
        !           709:
        !           710: #ifdef KTRACE
        !           711:        if (KTRPOINT(p, KTR_SYSRET)) {
        !           712:                KERNEL_PROC_LOCK(p);
        !           713:                ktrsysret(p,
        !           714:                    (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
        !           715:                KERNEL_PROC_UNLOCK(p);
        !           716:        }
        !           717: #endif
        !           718: }
        !           719:
        !           720: int
        !           721: badaddr(char *addr, u_int32_t len)
        !           722: {
        !           723:        faultbuf env;
        !           724:        u_int32_t v;
        !           725:        void *oldh = curpcb->pcb_onfault;
        !           726:
        !           727:        if (setfault(&env)) {
        !           728:                curpcb->pcb_onfault = oldh;
        !           729:                return EFAULT;
        !           730:        }
        !           731:        switch(len) {
        !           732:        case 4:
        !           733:                v = *((volatile u_int32_t *)addr);
        !           734:                break;
        !           735:        case 2:
        !           736:                v = *((volatile u_int16_t *)addr);
        !           737:                break;
        !           738:        default:
        !           739:                v = *((volatile u_int8_t *)addr);
        !           740:                break;
        !           741:        }
        !           742:        /* Make sure all loads retire before turning off fault handling!! */
        !           743:        __asm__ volatile ("sync");
        !           744:        curpcb->pcb_onfault = oldh;
        !           745:        return(0);
        !           746: }
        !           747:
        !           748:
        !           749: /*
        !           750:  * For now, this only deals with the particular unaligned access case
        !           751:  * that gcc tends to generate.  Eventually it should handle all of the
        !           752:  * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
        !           753:  */
        !           754:
        !           755: static int
        !           756: fix_unaligned(struct proc *p, struct trapframe *frame)
        !           757: {
        !           758:        int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
        !           759:        struct cpu_info *ci = curcpu();
        !           760:
        !           761:        switch (indicator) {
        !           762:        case EXC_ALI_LFD:
        !           763:        case EXC_ALI_STFD:
        !           764:                {
        !           765:                        int reg = EXC_ALI_RST(frame->dsisr);
        !           766:                        double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg];
        !           767:
        !           768:                        /* Juggle the FPU to ensure that we've initialized
        !           769:                         * the FPRs, and that their current state is in
        !           770:                         * the PCB.
        !           771:                         */
        !           772:                        if (ci->ci_fpuproc != p) {
        !           773:                                if (ci->ci_fpuproc)
        !           774:                                        save_fpu();
        !           775:                                enable_fpu(p);
        !           776:                        }
        !           777:                        save_fpu();
        !           778:
        !           779:                        if (indicator == EXC_ALI_LFD) {
        !           780:                                if (copyin((void *)frame->dar, fpr,
        !           781:                                    sizeof(double)) != 0)
        !           782:                                        return -1;
        !           783:                        } else {
        !           784:                                if (copyout(fpr, (void *)frame->dar,
        !           785:                                    sizeof(double)) != 0)
        !           786:                                        return -1;
        !           787:                        }
        !           788:                        enable_fpu(p);
        !           789:                        return 0;
        !           790:                }
        !           791:                break;
        !           792:        }
        !           793:        return -1;
        !           794: }

CVSweb