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

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

1.1     ! nbrk        1: /*     $OpenBSD: trap.c,v 1.12 2007/03/15 10:22:29 art Exp $   */
        !             2: /*     $NetBSD: exception.c,v 1.32 2006/09/04 23:57:52 uwe Exp $       */
        !             3: /*     $NetBSD: syscall.c,v 1.6 2006/03/07 07:21:50 thorpej Exp $      */
        !             4:
        !             5: /*-
        !             6:  * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
        !             7:  * Copyright (c) 1990 The Regents of the University of California.
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * the University of Utah, and William Jolitz.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. Neither the name of the University nor the names of its contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  *     @(#)trap.c      7.4 (Berkeley) 5/13/91
        !            38:  */
        !            39:
        !            40: /*-
        !            41:  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
        !            42:  *
        !            43:  * This code is derived from software contributed to Berkeley by
        !            44:  * the University of Utah, and William Jolitz.
        !            45:  *
        !            46:  * Redistribution and use in source and binary forms, with or without
        !            47:  * modification, are permitted provided that the following conditions
        !            48:  * are met:
        !            49:  * 1. Redistributions of source code must retain the above copyright
        !            50:  *    notice, this list of conditions and the following disclaimer.
        !            51:  * 2. Redistributions in binary form must reproduce the above copyright
        !            52:  *    notice, this list of conditions and the following disclaimer in the
        !            53:  *    documentation and/or other materials provided with the distribution.
        !            54:  * 3. All advertising materials mentioning features or use of this software
        !            55:  *    must display the following acknowledgement:
        !            56:  *     This product includes software developed by the University of
        !            57:  *     California, Berkeley and its contributors.
        !            58:  * 4. Neither the name of the University nor the names of its contributors
        !            59:  *    may be used to endorse or promote products derived from this software
        !            60:  *    without specific prior written permission.
        !            61:  *
        !            62:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            63:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            64:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            65:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            66:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            67:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            68:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            69:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            70:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            71:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            72:  * SUCH DAMAGE.
        !            73:  *
        !            74:  *     @(#)trap.c      7.4 (Berkeley) 5/13/91
        !            75:  */
        !            76:
        !            77: /*
        !            78:  * SH3 Trap and System call handling
        !            79:  *
        !            80:  * T.Horiuchi 1998.06.8
        !            81:  */
        !            82:
        !            83: #include <sys/param.h>
        !            84: #include <sys/systm.h>
        !            85: #include <sys/proc.h>
        !            86: #include <sys/pool.h>
        !            87: #include <sys/user.h>
        !            88: #include <sys/kernel.h>
        !            89: #include <sys/signal.h>
        !            90: #include <sys/syscall.h>
        !            91:
        !            92: #ifdef KTRACE
        !            93: #include <sys/ktrace.h>
        !            94: #endif
        !            95:
        !            96: #include "systrace.h"
        !            97: #if NSYSTRACE > 0
        !            98: #include <dev/systrace.h>
        !            99: #endif
        !           100:
        !           101: #include <uvm/uvm_extern.h>
        !           102:
        !           103: #include <sh/cache.h>
        !           104: #include <sh/cpu.h>
        !           105: #include <sh/mmu.h>
        !           106: #include <sh/trap.h>
        !           107: #include <sh/userret.h>
        !           108: #ifdef SH4
        !           109: #include <sh/fpu.h>
        !           110: #endif
        !           111:
        !           112: #ifdef DDB
        !           113: #include <machine/db_machdep.h>
        !           114: #endif
        !           115:
        !           116: const char * const exp_type[] = {
        !           117:        NULL,                                   /* 000 (reset vector) */
        !           118:        NULL,                                   /* 020 (reset vector) */
        !           119:        "TLB miss/invalid (load)",              /* 040 EXPEVT_TLB_MISS_LD */
        !           120:        "TLB miss/invalid (store)",             /* 060 EXPEVT_TLB_MISS_ST */
        !           121:        "initial page write",                   /* 080 EXPEVT_TLB_MOD */
        !           122:        "TLB protection violation (load)",      /* 0a0 EXPEVT_TLB_PROT_LD */
        !           123:        "TLB protection violation (store)",     /* 0c0 EXPEVT_TLB_PROT_ST */
        !           124:        "address error (load)",                 /* 0e0 EXPEVT_ADDR_ERR_LD */
        !           125:        "address error (store)",                /* 100 EXPEVT_ADDR_ERR_ST */
        !           126:        "FPU",                                  /* 120 EXPEVT_FPU */
        !           127:        NULL,                                   /* 140 (reset vector) */
        !           128:        "unconditional trap (TRAPA)",           /* 160 EXPEVT_TRAPA */
        !           129:        "reserved instruction code exception",  /* 180 EXPEVT_RES_INST */
        !           130:        "illegal slot instruction exception",   /* 1a0 EXPEVT_SLOT_INST */
        !           131:        NULL,                                   /* 1c0 (external interrupt) */
        !           132:        "user break point trap",                /* 1e0 EXPEVT_BREAK */
        !           133:        NULL, NULL, NULL, NULL,                 /* 200-260 */
        !           134:        NULL, NULL, NULL, NULL,                 /* 280-2e0 */
        !           135:        NULL, NULL, NULL, NULL,                 /* 300-360 */
        !           136:        NULL, NULL, NULL, NULL,                 /* 380-3e0 */
        !           137:        NULL, NULL, NULL, NULL,                 /* 400-460 */
        !           138:        NULL, NULL, NULL, NULL,                 /* 480-4e0 */
        !           139:        NULL, NULL, NULL, NULL,                 /* 500-560 */
        !           140:        NULL, NULL, NULL, NULL,                 /* 580-5e0 */
        !           141:        NULL, NULL, NULL, NULL,                 /* 600-660 */
        !           142:        NULL, NULL, NULL, NULL,                 /* 680-6e0 */
        !           143:        NULL, NULL, NULL, NULL,                 /* 700-760 */
        !           144:        NULL, NULL, NULL, NULL,                 /* 780-7e0 */
        !           145:        "FPU disabled",                         /* 800 EXPEVT_FPU_DISABLE */
        !           146:        "slot FPU disabled"                     /* 820 EXPEVT_FPU_SLOT_DISABLE */
        !           147: };
        !           148: const int exp_types = sizeof exp_type / sizeof exp_type[0];
        !           149:
        !           150: void general_exception(struct proc *, struct trapframe *, uint32_t);
        !           151: void tlb_exception(struct proc *, struct trapframe *, uint32_t);
        !           152: void ast(struct proc *, struct trapframe *);
        !           153: void syscall(struct proc *, struct trapframe *);
        !           154: void cachectl(struct proc *, struct trapframe *);
        !           155:
        !           156: /*
        !           157:  * void general_exception(struct proc *p, struct trapframe *tf):
        !           158:  *     p  ... curproc when exception occured.
        !           159:  *     tf ... full user context.
        !           160:  *     va ... fault va for user mode EXPEVT_ADDR_ERR_{LD,ST}
        !           161:  */
        !           162: void
        !           163: general_exception(struct proc *p, struct trapframe *tf, uint32_t va)
        !           164: {
        !           165:        int expevt = tf->tf_expevt;
        !           166:        int tra;
        !           167:        boolean_t usermode = !KERNELMODE(tf->tf_ssr);
        !           168:        union sigval sv;
        !           169:
        !           170:        uvmexp.traps++;
        !           171:
        !           172:        /*
        !           173:         * This function is entered at splhigh. Restore the interrupt
        !           174:         * level to what it was when the trap occured.
        !           175:         */
        !           176:        splx(tf->tf_ssr & PSL_IMASK);
        !           177:
        !           178:        if (usermode) {
        !           179:                if (p == NULL)
        !           180:                        goto do_panic;
        !           181:                KDASSERT(p->p_md.md_regs == tf); /* check exception depth */
        !           182:                expevt |= EXP_USER;
        !           183:        }
        !           184:
        !           185:        switch (expevt) {
        !           186:        case EXPEVT_BREAK:
        !           187:                if (kdb_trap(EXPEVT_BREAK, 0, tf))
        !           188:                        return;
        !           189:                else
        !           190:                        goto do_panic;
        !           191:                break;
        !           192:        case EXPEVT_TRAPA:
        !           193:                /* Check for ddb request */
        !           194:                tra = _reg_read_4(SH_(TRA));
        !           195:                if (tra == (_SH_TRA_BREAK << 2) &&
        !           196:                    kdb_trap(expevt, tra, tf))
        !           197:                        return;
        !           198:                else
        !           199:                        goto do_panic;
        !           200:                break;
        !           201:        case EXPEVT_TRAPA | EXP_USER:
        !           202:                /* Check for debugger break */
        !           203:                tra = _reg_read_4(SH_(TRA));
        !           204:                switch (tra) {
        !           205:                case _SH_TRA_BREAK << 2:
        !           206:                        tf->tf_spc -= 2; /* back to the breakpoint address */
        !           207:                        sv.sival_ptr = (void *)tf->tf_spc;
        !           208:                        trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_BRKPT,
        !           209:                            sv);
        !           210:                        goto out;
        !           211:                case _SH_TRA_SYSCALL << 2:
        !           212:                        syscall(p, tf);
        !           213:                        return;
        !           214:                case _SH_TRA_CACHECTL << 2:
        !           215:                        cachectl(p, tf);
        !           216:                        return;
        !           217:                default:
        !           218:                        sv.sival_ptr = (void *)tf->tf_spc;
        !           219:                        trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLTRP,
        !           220:                            sv);
        !           221:                        goto out;
        !           222:                }
        !           223:                break;
        !           224:
        !           225:        case EXPEVT_ADDR_ERR_LD: /* FALLTHROUGH */
        !           226:        case EXPEVT_ADDR_ERR_ST:
        !           227:                KDASSERT(p && p->p_md.md_pcb->pcb_onfault != NULL);
        !           228:                if (p == NULL || p->p_md.md_pcb->pcb_onfault == 0)
        !           229:                        goto do_panic;
        !           230:                tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
        !           231:                break;
        !           232:
        !           233:        case EXPEVT_ADDR_ERR_LD | EXP_USER: /* FALLTHROUGH */
        !           234:        case EXPEVT_ADDR_ERR_ST | EXP_USER:
        !           235:                sv.sival_ptr = (void *)va;
        !           236:                if (((int)va) < 0)
        !           237:                        trapsignal(p, SIGSEGV, expevt & ~EXP_USER, SEGV_ACCERR,
        !           238:                            sv);
        !           239:                else
        !           240:                        trapsignal(p, SIGBUS, expevt & ~EXP_USER, BUS_ADRALN,
        !           241:                            sv);
        !           242:                goto out;
        !           243:
        !           244:        case EXPEVT_RES_INST | EXP_USER: /* FALLTHROUGH */
        !           245:        case EXPEVT_SLOT_INST | EXP_USER:
        !           246:                sv.sival_ptr = (void *)tf->tf_spc;
        !           247:                trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLOPC, sv);
        !           248:                goto out;
        !           249:
        !           250:        case EXPEVT_BREAK | EXP_USER:
        !           251:                sv.sival_ptr = (void *)tf->tf_spc;
        !           252:                trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_TRACE, sv);
        !           253:                goto out;
        !           254:
        !           255: #ifdef SH4
        !           256:        case EXPEVT_FPU_DISABLE | EXP_USER: /* FALLTHROUGH */
        !           257:        case EXPEVT_FPU_SLOT_DISABLE | EXP_USER:
        !           258:                sv.sival_ptr = (void *)tf->tf_spc;
        !           259:                trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_COPROC, sv);
        !           260:                goto out;
        !           261:
        !           262:        case EXPEVT_FPU | EXP_USER:
        !           263:            {
        !           264:                int fpscr, sigi;
        !           265:
        !           266:                /* XXX worth putting in the trapframe? */
        !           267:                __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr));
        !           268:                fpscr = (fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
        !           269:                if (fpscr & FPEXC_E)
        !           270:                        sigi = FPE_FLTINV;      /* XXX any better value? */
        !           271:                else if (fpscr & FPEXC_V)
        !           272:                        sigi = FPE_FLTINV;
        !           273:                else if (fpscr & FPEXC_Z)
        !           274:                        sigi = FPE_FLTDIV;
        !           275:                else if (fpscr & FPEXC_O)
        !           276:                        sigi = FPE_FLTOVF;
        !           277:                else if (fpscr & FPEXC_U)
        !           278:                        sigi = FPE_FLTUND;
        !           279:                else if (fpscr & FPEXC_I)
        !           280:                        sigi = FPE_FLTRES;
        !           281:                else
        !           282:                        sigi = 0;       /* shouldn't happen */
        !           283:                sv.sival_ptr = (void *)tf->tf_spc;
        !           284:                trapsignal(p, SIGFPE, expevt & ~EXP_USER, sigi, sv);
        !           285:            }
        !           286:                goto out;
        !           287: #endif
        !           288:
        !           289:        default:
        !           290:                goto do_panic;
        !           291:        }
        !           292:
        !           293:        if (!usermode)
        !           294:                return;
        !           295: out:
        !           296:        userret(p);
        !           297:        return;
        !           298:
        !           299: do_panic:
        !           300:        if ((expevt >> 5) < exp_types && exp_type[expevt >> 5] != NULL)
        !           301:                printf("fatal %s", exp_type[expevt >> 5]);
        !           302:        else
        !           303:                printf("EXPEVT 0x%03x", expevt);
        !           304:        printf(" in %s mode\n", expevt & EXP_USER ? "user" : "kernel");
        !           305:        printf("va %p spc %p ssr %p pr %p \n",
        !           306:            va, tf->tf_spc, tf->tf_ssr, tf->tf_pr);
        !           307:
        !           308:        panic("general_exception");
        !           309:        /* NOTREACHED */
        !           310: }
        !           311:
        !           312:
        !           313: /*
        !           314:  * void tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va):
        !           315:  *     p  ... curproc when exception occured.
        !           316:  *     tf ... full user context.
        !           317:  *     va ... fault address.
        !           318:  */
        !           319: void
        !           320: tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va)
        !           321: {
        !           322:        struct vm_map *map;
        !           323:        pmap_t pmap;
        !           324:        union sigval sv;
        !           325:        boolean_t usermode;
        !           326:        int err, track, ftype;
        !           327:        const char *panic_msg;
        !           328:
        !           329: #define TLB_ASSERT(assert, msg)                                \
        !           330:                do {                                    \
        !           331:                        if (!(assert)) {                \
        !           332:                                panic_msg =  msg;       \
        !           333:                                goto tlb_panic;         \
        !           334:                        }                               \
        !           335:                } while(/*CONSTCOND*/0)
        !           336:
        !           337:        /*
        !           338:         * This function is entered at splhigh. Restore the interrupt
        !           339:         * level to what it was when the trap occured.
        !           340:         */
        !           341:        splx(tf->tf_ssr & PSL_IMASK);
        !           342:
        !           343:        usermode = !KERNELMODE(tf->tf_ssr);
        !           344:        if (usermode) {
        !           345:                KDASSERT(p->p_md.md_regs == tf);
        !           346:        } else {
        !           347:                KDASSERT(p == NULL ||           /* idle */
        !           348:                    p == &proc0 ||              /* kthread */
        !           349:                    p->p_md.md_regs != tf);     /* other */
        !           350:        }
        !           351:
        !           352:        switch (tf->tf_expevt) {
        !           353:        case EXPEVT_TLB_MISS_LD:
        !           354:                track = PVH_REFERENCED;
        !           355:                ftype = VM_PROT_READ;
        !           356:                break;
        !           357:        case EXPEVT_TLB_MISS_ST:
        !           358:                track = PVH_REFERENCED;
        !           359:                ftype = VM_PROT_WRITE;
        !           360:                break;
        !           361:        case EXPEVT_TLB_MOD:
        !           362:                track = PVH_REFERENCED | PVH_MODIFIED;
        !           363:                ftype = VM_PROT_WRITE;
        !           364:                break;
        !           365:        case EXPEVT_TLB_PROT_LD:
        !           366:                TLB_ASSERT((int)va > 0,
        !           367:                    "kernel virtual protection fault (load)");
        !           368:                if (usermode) {
        !           369:                        sv.sival_ptr = (void *)va;
        !           370:                        trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_ACCERR, sv);
        !           371:                        goto user_fault;
        !           372:                } else {
        !           373:                        TLB_ASSERT(p->p_md.md_pcb->pcb_onfault != NULL,
        !           374:                            "no copyin/out fault handler (load protection)");
        !           375:                        tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
        !           376:                }
        !           377:                return;
        !           378:
        !           379:        case EXPEVT_TLB_PROT_ST:
        !           380:                track = 0;      /* call uvm_fault first. (COW) */
        !           381:                ftype = VM_PROT_WRITE;
        !           382:                break;
        !           383:
        !           384:        default:
        !           385:                TLB_ASSERT(0, "impossible expevt");
        !           386:        }
        !           387:
        !           388:        /* Select address space */
        !           389:        if (usermode) {
        !           390:                TLB_ASSERT(p != NULL, "no curproc");
        !           391:                map = &p->p_vmspace->vm_map;
        !           392:                pmap = map->pmap;
        !           393:        } else {
        !           394:                if ((int)va < 0) {
        !           395:                        map = kernel_map;
        !           396:                        pmap = pmap_kernel();
        !           397:                } else {
        !           398:                        TLB_ASSERT(p != NULL &&
        !           399:                            p->p_md.md_pcb->pcb_onfault != NULL,
        !           400:                            "invalid user-space access from kernel mode");
        !           401:                        if (va == 0) {
        !           402:                                tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
        !           403:                                return;
        !           404:                        }
        !           405:                        map = &p->p_vmspace->vm_map;
        !           406:                        pmap = map->pmap;
        !           407:                }
        !           408:        }
        !           409:
        !           410:        /* Lookup page table. if entry found, load it. */
        !           411:        if (track && __pmap_pte_load(pmap, va, track)) {
        !           412:                if (usermode)
        !           413:                        userret(p);
        !           414:                return;
        !           415:        }
        !           416:
        !           417:        err = uvm_fault(map, va, 0, ftype);
        !           418:
        !           419:        /* User stack extension */
        !           420:        if (map != kernel_map &&
        !           421:            (va >= (vaddr_t)p->p_vmspace->vm_maxsaddr) &&
        !           422:            (va < USRSTACK)) {
        !           423:                if (err == 0)
        !           424:                        uvm_grow(p, va);
        !           425:                else if (err == EACCES)
        !           426:                        err = EFAULT;
        !           427:        }
        !           428:
        !           429:        /* Page in. load PTE to TLB. */
        !           430:        if (err == 0) {
        !           431:                boolean_t loaded = __pmap_pte_load(pmap, va, track);
        !           432:                TLB_ASSERT(loaded, "page table entry not found");
        !           433:                if (usermode)
        !           434:                        userret(p);
        !           435:                return;
        !           436:        }
        !           437:
        !           438:        /* Page not found. */
        !           439:        if (usermode) {
        !           440:                sv.sival_ptr = (void *)va;
        !           441:                if (err == ENOMEM) {
        !           442:                        printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
        !           443:                            p->p_pid, p->p_comm,
        !           444:                            p->p_cred && p->p_ucred ?
        !           445:                                (int)p->p_ucred->cr_uid : -1);
        !           446:                        trapsignal(p, SIGKILL, tf->tf_expevt, SEGV_MAPERR, sv);
        !           447:                } else
        !           448:                        trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_MAPERR, sv);
        !           449:                goto user_fault;
        !           450:        } else {
        !           451:                TLB_ASSERT(p->p_md.md_pcb->pcb_onfault,
        !           452:                    "no copyin/out fault handler (page not found)");
        !           453:                tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
        !           454:        }
        !           455:        return;
        !           456:
        !           457: user_fault:
        !           458:        userret(p);
        !           459:        ast(p, tf);
        !           460:        return;
        !           461:
        !           462: tlb_panic:
        !           463:        panic("tlb_exception: %s\n"
        !           464:              "expevt=%x va=%08x ssr=%08x spc=%08x proc=%p onfault=%p",
        !           465:              panic_msg, tf->tf_expevt, va, tf->tf_ssr, tf->tf_spc,
        !           466:              p, p ? p->p_md.md_pcb->pcb_onfault : NULL);
        !           467: #undef TLB_ASSERT
        !           468: }
        !           469:
        !           470:
        !           471: /*
        !           472:  * void ast(struct proc *p, struct trapframe *tf):
        !           473:  *     p  ... curproc when exception occured.
        !           474:  *     tf ... full user context.
        !           475:  *     This is called upon exception return. if return from kernel to user,
        !           476:  *     handle asynchronous software traps and context switch if needed.
        !           477:  */
        !           478: void
        !           479: ast(struct proc *p, struct trapframe *tf)
        !           480: {
        !           481:        if (KERNELMODE(tf->tf_ssr))
        !           482:                return;
        !           483:        KDASSERT(p != NULL);
        !           484:        KDASSERT(p->p_md.md_regs == tf);
        !           485:
        !           486:        while (p->p_md.md_astpending) {
        !           487:                uvmexp.softs++;
        !           488:                p->p_md.md_astpending = 0;
        !           489:
        !           490:                if (p->p_flag & P_OWEUPC) {
        !           491:                        ADDUPROF(p);
        !           492:                }
        !           493:
        !           494:                if (want_resched) {
        !           495:                        /* We are being preempted. */
        !           496:                        preempt(NULL);
        !           497:                }
        !           498:
        !           499:                userret(p);
        !           500:        }
        !           501: }
        !           502:
        !           503: void
        !           504: cachectl(struct proc *p, struct trapframe *tf)
        !           505: {
        !           506:        vaddr_t va;
        !           507:        vsize_t len;
        !           508:
        !           509:        if (!SH_HAS_UNIFIED_CACHE) {
        !           510:                va = (vaddr_t)tf->tf_r4;
        !           511:                len = (vsize_t)tf->tf_r5;
        !           512:
        !           513:                if (/* va < VM_MIN_ADDRESS || */ va >= VM_MAXUSER_ADDRESS ||
        !           514:                    va + len <= va || va + len >= VM_MAXUSER_ADDRESS)
        !           515:                        len = 0;
        !           516:
        !           517:                if (len != 0)
        !           518:                        sh_icache_sync_range_index(va, len);
        !           519:        }
        !           520:
        !           521:        userret(p);
        !           522: }
        !           523:
        !           524: void
        !           525: syscall(struct proc *p, struct trapframe *tf)
        !           526: {
        !           527:        caddr_t params;
        !           528:        const struct sysent *callp;
        !           529:        int error, oerror, opc, nsys;
        !           530:        size_t argsize;
        !           531:        register_t code, args[8], rval[2], ocode;
        !           532:
        !           533:        uvmexp.syscalls++;
        !           534:
        !           535:        opc = tf->tf_spc;
        !           536:        ocode = code = tf->tf_r0;
        !           537:
        !           538:        nsys = p->p_emul->e_nsysent;
        !           539:        callp = p->p_emul->e_sysent;
        !           540:
        !           541:        params = (caddr_t)tf->tf_r15;
        !           542:
        !           543:        switch (code) {
        !           544:        case SYS_syscall:
        !           545:                /*
        !           546:                 * Code is first argument, followed by actual args.
        !           547:                 */
        !           548:                code = tf->tf_r4;
        !           549:                break;
        !           550:        case SYS___syscall:
        !           551:                /*
        !           552:                 * Like syscall, but code is a quad, so as to maintain
        !           553:                 * quad alignment for the rest of the arguments.
        !           554:                 */
        !           555:                if (callp != sysent)
        !           556:                        break;
        !           557: #if _BYTE_ORDER == BIG_ENDIAN
        !           558:                code = tf->tf_r5;
        !           559: #else
        !           560:                code = tf->tf_r4;
        !           561: #endif
        !           562:                break;
        !           563:        default:
        !           564:                break;
        !           565:        }
        !           566:        if (code < 0 || code >= nsys)
        !           567:                callp += p->p_emul->e_nosys;            /* illegal */
        !           568:        else
        !           569:                callp += code;
        !           570:        argsize = callp->sy_argsize;
        !           571: #ifdef DIAGNOSTIC
        !           572:        if (argsize > sizeof args) {
        !           573:                callp += p->p_emul->e_nosys - code;
        !           574:                goto bad;
        !           575:        }
        !           576: #endif
        !           577:
        !           578:        switch (ocode) {
        !           579:        case SYS_syscall:
        !           580:                if (argsize) {
        !           581:                        args[0] = tf->tf_r5;
        !           582:                        args[1] = tf->tf_r6;
        !           583:                        args[2] = tf->tf_r7;
        !           584:                        if (argsize > 3 * sizeof(int)) {
        !           585:                                argsize -= 3 * sizeof(int);
        !           586:                                error = copyin(params, (caddr_t)&args[3],
        !           587:                                               argsize);
        !           588:                        } else
        !           589:                                error = 0;
        !           590:                } else
        !           591:                        error = 0;
        !           592:                break;
        !           593:        case SYS___syscall:
        !           594:                if (argsize) {
        !           595:                        args[0] = tf->tf_r6;
        !           596:                        args[1] = tf->tf_r7;
        !           597:                        if (argsize > 2 * sizeof(int)) {
        !           598:                                argsize -= 2 * sizeof(int);
        !           599:                                error = copyin(params, (caddr_t)&args[2],
        !           600:                                               argsize);
        !           601:                        } else
        !           602:                                error = 0;
        !           603:                } else
        !           604:                        error = 0;
        !           605:                break;
        !           606:        default:
        !           607:                if (argsize) {
        !           608:                        args[0] = tf->tf_r4;
        !           609:                        args[1] = tf->tf_r5;
        !           610:                        args[2] = tf->tf_r6;
        !           611:                        args[3] = tf->tf_r7;
        !           612:                        if (argsize > 4 * sizeof(int)) {
        !           613:                                argsize -= 4 * sizeof(int);
        !           614:                                error = copyin(params, (caddr_t)&args[4],
        !           615:                                               argsize);
        !           616:                        } else
        !           617:                                error = 0;
        !           618:                } else
        !           619:                        error = 0;
        !           620:                break;
        !           621:        }
        !           622:
        !           623:        if (error)
        !           624:                goto bad;
        !           625:
        !           626: #ifdef SYSCALL_DEBUG
        !           627:        scdebug_call(p, code, args);
        !           628: #endif
        !           629: #ifdef KTRACE
        !           630:        if (KTRPOINT(p, KTR_SYSCALL))
        !           631:                ktrsyscall(p, code, callp->sy_argsize, args);
        !           632: #endif
        !           633:
        !           634:        rval[0] = 0;
        !           635:        rval[1] = tf->tf_r1;
        !           636: #if NSYSTRACE > 0
        !           637:        if (ISSET(p->p_flag, P_SYSTRACE))
        !           638:                error = systrace_redirect(code, p, args, rval);
        !           639:        else
        !           640: #endif
        !           641:                error = (*callp->sy_call)(p, args, rval);
        !           642:
        !           643:        switch (oerror = error) {
        !           644:        case 0:
        !           645:                tf->tf_r0 = rval[0];
        !           646:                tf->tf_r1 = rval[1];
        !           647:                tf->tf_ssr |= PSL_TBIT; /* T bit */
        !           648:                break;
        !           649:        case ERESTART:
        !           650:                /* 2 = TRAPA instruction size */
        !           651:                tf->tf_spc = opc - 2;
        !           652:                break;
        !           653:        case EJUSTRETURN:
        !           654:                /* nothing to do */
        !           655:                break;
        !           656:        default:
        !           657: bad:
        !           658:                if (p->p_emul->e_errno)
        !           659:                        error = p->p_emul->e_errno[error];
        !           660:                tf->tf_r0 = error;
        !           661:                tf->tf_ssr &= ~PSL_TBIT;        /* T bit */
        !           662:                break;
        !           663:        }
        !           664:
        !           665: #ifdef SYSCALL_DEBUG
        !           666:        scdebug_ret(p, code, oerror, rval);
        !           667: #endif
        !           668:        userret(p);
        !           669: #ifdef KTRACE
        !           670:        if (KTRPOINT(p, KTR_SYSRET))
        !           671:                ktrsysret(p, code, oerror, rval[0]);
        !           672: #endif
        !           673: }
        !           674:
        !           675: /*
        !           676:  * void child_return(void *arg):
        !           677:  *
        !           678:  *     uvm_fork sets this routine to proc_trampoline's service function.
        !           679:  *     when returning from here, jump to userland.
        !           680:  */
        !           681: void
        !           682: child_return(void *arg)
        !           683: {
        !           684:        struct proc *p = arg;
        !           685:        struct trapframe *tf = p->p_md.md_regs;
        !           686:
        !           687:        tf->tf_r0 = 0;
        !           688:        tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */
        !           689:
        !           690:        userret(p);
        !           691:
        !           692: #ifdef KTRACE
        !           693:        if (KTRPOINT(p, KTR_SYSRET))
        !           694:                ktrsysret(p,
        !           695:                    (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
        !           696: #endif
        !           697: }
        !           698:

CVSweb