Annotation of XNU/osfmk/ppc/trap.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: 
        !            26: #include <mach_kdb.h>
        !            27: #include <mach_kdp.h>
        !            28: #include <debug.h>
        !            29: #include <cpus.h>
        !            30: #include <kern/thread.h>
        !            31: #include <kern/exception.h>
        !            32: #include <kern/syscall_sw.h>
        !            33: #include <kern/cpu_data.h>
        !            34: #include <kern/debug.h>
        !            35: #include <mach/thread_status.h>
        !            36: #include <vm/vm_fault.h>
        !            37: #include <vm/vm_kern.h>        /* For kernel_map */
        !            38: #include <ppc/misc_protos.h>
        !            39: #include <ppc/trap.h>
        !            40: #include <ppc/exception.h>
        !            41: #include <ppc/proc_reg.h>      /* for SR_xxx definitions */
        !            42: #include <ppc/pmap.h>
        !            43: #include <ppc/mem.h>
        !            44: #include <ppc/fpu_protos.h>
        !            45: 
        !            46: #include <sys/kdebug.h>
        !            47: 
        !            48: #if    MACH_KDB
        !            49: #include <ddb/db_watch.h>
        !            50: #include <ddb/db_run.h>
        !            51: #include <ddb/db_break.h>
        !            52: #include <ddb/db_trap.h>
        !            53: 
        !            54: boolean_t let_ddb_vm_fault = FALSE;
        !            55: boolean_t      debug_all_traps_with_kdb = FALSE;
        !            56: extern struct db_watchpoint *db_watchpoint_list;
        !            57: extern boolean_t db_watchpoints_inserted;
        !            58: extern boolean_t db_breakpoints_inserted;
        !            59: 
        !            60: 
        !            61: #endif /* MACH_KDB */
        !            62: 
        !            63: extern int debugger_active[NCPUS];
        !            64: 
        !            65: #if DEBUG || MACH_ASSERT
        !            66: #define TRAP_ALL               -1
        !            67: #define TRAP_ALIGNMENT         0x01
        !            68: #define TRAP_DATA              0x02
        !            69: #define TRAP_INSTRUCTION       0x04
        !            70: #define TRAP_AST               0x08
        !            71: #define TRAP_TRACE             0x10
        !            72: #define TRAP_PROGRAM           0x20
        !            73: #define TRAP_EXCEPTION         0x40
        !            74: #define TRAP_UNRESOLVED                0x80
        !            75: #define TRAP_SYSCALL           0x100   /* all syscalls */
        !            76: #define TRAP_HW                        0x200   /* all in hw_exception.s */
        !            77: #define TRAP_MACH_SYSCALL      0x400
        !            78: #define TRAP_SERVER_SYSCALL    0x800
        !            79: 
        !            80: int trapdebug=0; /* TRAP_SERVER_SYSCALL;*/
        !            81: 
        !            82: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){printf A;}}
        !            83: #else
        !            84: #define TRAP_DEBUG(LEVEL, A)
        !            85: #endif
        !            86: 
        !            87: /*
        !            88:  * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied
        !            89:  * in either R or RW (note: the pmap module knows this).  This is done for the
        !            90:  * benefit of programs that execute out of their data space (ala lisp).
        !            91:  * If we didn't do this in that scenerio, the ITLB miss code would call us
        !            92:  * and we would call vm_fault() with RX permission.  However, the space was
        !            93:  * probably vm_allocate()ed with just RW and vm_fault would fail.  The "right"
        !            94:  * solution to me is to have the un*x server always allocate data with RWX for
        !            95:  * compatibility with existing binaries.
        !            96:  */
        !            97: 
        !            98: #define        PROT_EXEC       (VM_PROT_READ)
        !            99: #define PROT_RO                (VM_PROT_READ)
        !           100: #define PROT_RW                (VM_PROT_READ|VM_PROT_WRITE)
        !           101: 
        !           102: /* A useful macro to update the ppc_exception_state in the PCB
        !           103:  * before calling doexception
        !           104:  */
        !           105: #define UPDATE_PPC_EXCEPTION_STATE {                                         \
        !           106:        thread_act_t thr_act = current_act();                                 \
        !           107:        struct ppc_exception_state *es = &thr_act->mact.pcb->es;              \
        !           108:        es->dar = dar;                                                        \
        !           109:        es->dsisr = dsisr;                                                    \
        !           110:        es->exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \
        !           111: }
        !           112: 
        !           113: static void unresolved_kernel_trap(int trapno,
        !           114:                                   struct ppc_saved_state *ssp,
        !           115:                                   unsigned int dsisr,
        !           116:                                   unsigned int dar,
        !           117:                                   char *message);
        !           118: 
        !           119: struct ppc_saved_state *trap(int trapno,
        !           120:                             struct ppc_saved_state *ssp,
        !           121:                             unsigned int dsisr,
        !           122:                             unsigned int dar)
        !           123: {
        !           124:        int exception=0;
        !           125:        int code;
        !           126:        int subcode;
        !           127:        vm_map_t map;
        !           128:         unsigned int sp;
        !           129:        unsigned int space,space2;
        !           130:        unsigned int offset;
        !           131:        thread_act_t thr_act = current_act();
        !           132: #ifdef MACH_BSD
        !           133:        time_value_t tv;
        !           134: #endif /* MACH_BSD */
        !           135: 
        !           136: 
        !           137:        TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n",
        !           138:                     trapno/4,ssp->srr0,ssp->srr1));
        !           139: 
        !           140: #if DEBUG
        !           141:        {
        !           142:                /* make sure we're not near to overflowing kernel stack */
        !           143:                int sp;
        !           144:                mp_disable_preemption();                                                /* Make sure we don't preempt */
        !           145: #ifdef __ELF__
        !           146:                __asm__ volatile("mr    %0, 1" : "=r" (sp));
        !           147: #else
        !           148:                __asm__ volatile("mr    %0, r1" : "=r" (sp));
        !           149: #endif
        !           150:                if (sp < 
        !           151:                    (cpu_data[cpu_number()].active_thread->kernel_stack +
        !           152:                     sizeof(struct ppc_saved_state)+256)) {
        !           153:                        printf("TRAP - LOW ON KERNEL STACK!\n");
        !           154:                }       
        !           155:        mp_enable_preemption();                                                         /* Preemption is cool now */
        !           156:        }
        !           157: #endif /* DEBUG */
        !           158:        /* Handle kernel traps first */
        !           159: 
        !           160:        if (!USER_MODE(ssp->srr1)) {
        !           161:                /*
        !           162:                 * Trap came from system task, ie kernel or collocated server
        !           163:                 */
        !           164:                switch (trapno) {
        !           165: 
        !           166:                case T_PREEMPT:                                                         /* Handle a preempt trap */
        !           167:                        mp_disable_preemption();                                        /* since preemption is not enabled */
        !           168:                        ast_off(AST_URGENT);                                            /* clear urgent and let it sched */
        !           169:                        mp_enable_preemption();                                         /* normally... */
        !           170:                        break;                                                          /* Do nothing, just check... */
        !           171: 
        !           172:                        /*
        !           173:                         * These trap types should never be seen by trap()
        !           174:                         * in kernel mode, anyway.
        !           175:                         * Some are interrupts that should be seen by
        !           176:                         * interrupt() others just don't happen because they
        !           177:                         * are handled elsewhere. Some could happen but are
        !           178:                         * considered to be fatal in kernel mode.
        !           179:                         */
        !           180:                case T_DECREMENTER:
        !           181:                case T_IN_VAIN:                                                         /* Shouldn't ever see this, lowmem_vectors eats it */
        !           182:                case T_RESET:
        !           183:                case T_MACHINE_CHECK:
        !           184:                case T_SYSTEM_MANAGEMENT:
        !           185:                case T_ALTIVEC_ASSIST:
        !           186:                case T_INTERRUPT:
        !           187:                case T_FP_UNAVAILABLE:
        !           188:                case T_IO_ERROR:
        !           189:                case T_RESERVED:
        !           190:                default:
        !           191:                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           192:                        break;
        !           193:                        
        !           194:                case T_TRACE:
        !           195:                case T_RUNMODE_TRACE:
        !           196:                case T_INSTRUCTION_BKPT:
        !           197: #if    MACH_KDP || MACH_KDB
        !           198:                        if (!Call_Debugger(trapno, ssp))
        !           199: #endif                   
        !           200:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           201:                        break;
        !           202: 
        !           203:                case T_PROGRAM:
        !           204:                        if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
        !           205: #if MACH_KDP || MACH_KDB
        !           206:                                if (!Call_Debugger(trapno, ssp))
        !           207: #endif 
        !           208:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           209:                        } else {
        !           210:                                unresolved_kernel_trap(trapno, ssp, 
        !           211:                                                        dsisr, dar, NULL);
        !           212:                        }
        !           213:                        break;
        !           214:                case T_ALIGNMENT:
        !           215:                        TRAP_DEBUG(TRAP_ALIGNMENT,
        !           216:                                   ("NMGS KERNEL ALIGNMENT_ACCESS, "
        !           217:                                     "DAR=0x%08x, DSISR = 0x%B\n",
        !           218:                                     dar, dsisr,
        !           219:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           220:                        if (alignment(dsisr, dar, ssp)) {
        !           221:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           222:                        }
        !           223:                        break;
        !           224:                case T_DATA_ACCESS:
        !           225:                        TRAP_DEBUG(TRAP_DATA,
        !           226:                                   ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x,"
        !           227:                                     "DSISR = 0x%B\n", dar, dsisr,
        !           228:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           229: 
        !           230: #if    MACH_KDB
        !           231:                        mp_disable_preemption();
        !           232:                        if (debug_mode
        !           233: #if    NCPUS > 1
        !           234:                            && debugger_active[cpu_number()]
        !           235: #endif /* NCPUS > 1 */
        !           236:                            && !let_ddb_vm_fault) {
        !           237:                                /*
        !           238:                                 * Force kdb to handle this one.
        !           239:                                 */
        !           240:                                kdb_trap(trapno, ssp);
        !           241:                        }
        !           242:                        mp_enable_preemption();
        !           243: #endif /* MACH_KDB */
        !           244: 
        !           245:                        /* simple case : not SR_COPYIN segment, from kernel */
        !           246:                        if ((dar >> 28) != SR_COPYIN_NUM) {
        !           247:                                map = kernel_map;
        !           248: 
        !           249:                                offset = dar;
        !           250:                                
        !           251: 
        !           252: /*
        !           253:  *     Note: Some ROM device drivers will access page 0 when they start.  The IOKit will 
        !           254:  *     set a flag to tell us to ignore any access fault on page 0.  After the driver is
        !           255:  *     opened, it will clear the flag.
        !           256:  */
        !           257:                                if((0 == (dar & -PAGE_SIZE)) &&         /* Check for access of page 0 and */
        !           258:                                  ((thr_act->mact.specFlags) & ignoreZeroFault)) {
        !           259:                                                                        /* special case of ignoring page zero faults */
        !           260:                                        ssp->srr0 += 4;                 /* Point to next instruction */
        !           261:                                        break;
        !           262:                                }
        !           263: 
        !           264:                                TRAP_DEBUG(TRAP_DATA,
        !           265:                                           ("SYSTEM FAULT FROM 0x%08x\n",
        !           266:                                            offset));
        !           267: 
        !           268:                                code = vm_fault(map,
        !           269:                                                trunc_page(offset),
        !           270:                                                dsisr & MASK(DSISR_WRITE) ?
        !           271:                                                        PROT_RW : PROT_RO,
        !           272:                                                FALSE);
        !           273:                                if (code != KERN_SUCCESS) {
        !           274:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           275:                                }
        !           276:                                else { 
        !           277:                                        ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
        !           278:                                        ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
        !           279:                                }
        !           280:                                break;
        !           281:                        }
        !           282: 
        !           283:                        /* If we get here, the fault was due to a copyin/out */
        !           284: 
        !           285:                        map = thr_act->map;
        !           286: 
        !           287:                        /* Mask out SR_COPYIN and mask in original segment */
        !           288: 
        !           289:                        offset = (dar & 0x0fffffff) |
        !           290:                                ((mfsrin(dar)<<8) & 0xF0000000);
        !           291: 
        !           292:                        TRAP_DEBUG(TRAP_DATA,
        !           293:                                   ("sr=0x%08x, dar=0x%08x, sp=0x%x\n",
        !           294:                                    mfsrin(dar), dar,map->pmap->space));
        !           295:                        assert((mfsrin(dar) & 0x000FFFFF) ==
        !           296:                               map->pmap->space);
        !           297:                        TRAP_DEBUG(TRAP_DATA,
        !           298:                                   ("KERNEL FAULT FROM 0x%x,0x%08x\n",
        !           299:                                    map->pmap->space, offset));
        !           300: 
        !           301:                        code = vm_fault(map,
        !           302:                                        trunc_page(offset),
        !           303:                                        dsisr & MASK(DSISR_WRITE) ?
        !           304:                                        PROT_RW : PROT_RO,
        !           305:                                        FALSE);
        !           306: 
        !           307:                        /* If we failed, there should be a recovery
        !           308:                         * spot to rfi to.
        !           309:                         */
        !           310:                        if (code != KERN_SUCCESS) {
        !           311:                                TRAP_DEBUG(TRAP_DATA,
        !           312:                                           ("FAULT FAILED- srr0=0x%08x,"
        !           313:                                             "pcb-srr0=0x%08x\n",
        !           314:                                             ssp->srr0,
        !           315:                                             thr_act->mact.pcb->ss.srr0));
        !           316: 
        !           317:                                if (thr_act->thread->recover) {
        !           318:                                
        !           319: #if 0
        !           320:                                        __asm__ volatile("tweq r1,r1"); /* (TEST/DEBUG) */
        !           321: #endif
        !           322: 
        !           323:                                        act_lock_thread(thr_act);
        !           324:                                        ssp->srr0 = thr_act->thread->recover;
        !           325:                                        thr_act->thread->recover =
        !           326:                                                        (vm_offset_t)NULL;
        !           327:                                        act_unlock_thread(thr_act);
        !           328:                                } else {
        !           329:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
        !           330:                                }
        !           331:                        }
        !           332:                        else { 
        !           333:                                ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
        !           334:                                ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
        !           335:                        }
        !           336:                        
        !           337:                        break;
        !           338:                        
        !           339:                case T_INSTRUCTION_ACCESS:
        !           340: 
        !           341:                        TRAP_DEBUG(TRAP_INSTRUCTION,
        !           342:                                   ("NMGS KERNEL INSTRUCTION ACCESS,"
        !           343:                                     "DSISR = 0x%B\n", dsisr,
        !           344:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           345: 
        !           346: #if    MACH_KDB
        !           347:                        if (debug_mode
        !           348: #if    NCPUS > 1
        !           349:                            && debugger_active[cpu_number()]
        !           350: #endif /* NCPUS > 1 */
        !           351:                            && !let_ddb_vm_fault) {
        !           352:                                /*
        !           353:                                 * Force kdb to handle this one.
        !           354:                                 */
        !           355:                                kdb_trap(trapno, ssp);
        !           356:                        }
        !           357: #endif /* MACH_KDB */
        !           358: 
        !           359:                        /* Same as for data access, except fault type
        !           360:                         * is PROT_EXEC and addr comes from srr0
        !           361:                         */
        !           362:                        map = thr_act->map;
        !           363:                        
        !           364:                        code = vm_fault(map, trunc_page(ssp->srr0),
        !           365:                                        PROT_EXEC, FALSE);
        !           366:                        if (code != KERN_SUCCESS) {
        !           367:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           368:                        }
        !           369:                        else { 
        !           370:                                ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
        !           371:                                ssp->srr1 |= MASK(DSISR_HASH);                                  /* Make sure this is marked as a miss */
        !           372:                        }
        !           373:                        break;
        !           374: 
        !           375:                /* Usually shandler handles all the system calls, but the
        !           376:                 * atomic thread switcher may throwup (via thandler) and
        !           377:                 * have to pass it up to the exception handler.
        !           378:                 */
        !           379: 
        !           380:                case T_SYSTEM_CALL:
        !           381:                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
        !           382:                        break;
        !           383: 
        !           384:                case T_AST:
        !           385:                        TRAP_DEBUG(TRAP_AST,
        !           386:                                   ("T_AST FROM KERNEL MODE\n"));
        !           387:                        ast_taken(FALSE, AST_ALL, 0);
        !           388:                        break;
        !           389:                }
        !           390:        } else {
        !           391: #ifdef MACH_BSD
        !           392:                {
        !           393:                void get_procrustime(time_value_t *);
        !           394: 
        !           395:                        get_procrustime(&tv);
        !           396:                }
        !           397: #endif /* MACH_BSD */
        !           398: 
        !           399:        
        !           400:                /*
        !           401:                 * Trap came from user task
        !           402:                 */
        !           403: 
        !           404:                switch (trapno) {
        !           405:                case T_PREEMPT:                                                                 /* Handle a preempt trap */
        !           406:                        break;                                                                          /* Do nothing, just check... */
        !           407: 
        !           408:                        /*
        !           409:                         * These trap types should never be seen by trap()
        !           410:                         * Some are interrupts that should be seen by
        !           411:                         * interrupt() others just don't happen because they
        !           412:                         * are handled elsewhere.
        !           413:                         */
        !           414:                case T_DECREMENTER:
        !           415:                case T_IN_VAIN:                                                         /* Shouldn't ever see this, lowmem_vectors eats it */
        !           416:                case T_MACHINE_CHECK:
        !           417:                case T_INTERRUPT:
        !           418:                case T_FP_UNAVAILABLE:
        !           419:                case T_SYSTEM_MANAGEMENT:
        !           420:                case T_RESERVED:
        !           421:                case T_IO_ERROR:
        !           422:                        
        !           423:                default:
        !           424:                        panic("Unexpected exception type");
        !           425:                        break;
        !           426: 
        !           427:                case T_RESET:
        !           428:                        halt_all_cpus(TRUE);         /* never returns */
        !           429: 
        !           430:                case T_ALIGNMENT:
        !           431:                        TRAP_DEBUG(TRAP_ALIGNMENT,
        !           432:                                   ("NMGS USER ALIGNMENT_ACCESS, "
        !           433:                                     "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,
        !           434:                                     "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           435:                        if (alignment(dsisr, dar, ssp)) {
        !           436:                                code = EXC_PPC_UNALIGNED;
        !           437:                                exception = EXC_BAD_ACCESS;
        !           438:                                subcode = dar;
        !           439:                        }
        !           440:                        break;
        !           441: 
        !           442:                case T_TRACE:                   /* Real PPC chips */
        !           443:                case T_INSTRUCTION_BKPT:        /* 603  PPC chips */
        !           444:                case T_RUNMODE_TRACE:           /* 601  PPC chips */
        !           445:                        TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n"));
        !           446: 
        !           447:                        exception = EXC_BREAKPOINT;
        !           448:                        code = EXC_PPC_TRACE;
        !           449:                        subcode = ssp->srr0;
        !           450:                        break;
        !           451: 
        !           452:                case T_PROGRAM:
        !           453:                        TRAP_DEBUG(TRAP_PROGRAM,
        !           454:                                   ("NMGS PROGRAM TRAP\n"));
        !           455:                        if (ssp->srr1 & MASK(SRR1_PRG_FE)) {
        !           456:                                TRAP_DEBUG(TRAP_PROGRAM,
        !           457:                                           ("FP EXCEPTION\n"));
        !           458:                                fpu_save();
        !           459:                                UPDATE_PPC_EXCEPTION_STATE;
        !           460:                                exception = EXC_ARITHMETIC;
        !           461:                                code = EXC_ARITHMETIC;
        !           462:                        
        !           463:                                mp_disable_preemption();
        !           464:                                subcode = current_act()->mact.FPU_pcb->fs.fpscr;
        !           465:                                mp_enable_preemption();
        !           466:                        }       
        !           467:                        else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) {
        !           468:                                
        !           469:                                TRAP_DEBUG(TRAP_PROGRAM,
        !           470:                                           ("ILLEGAL INSTRUCTION\n"));
        !           471: 
        !           472:                                UPDATE_PPC_EXCEPTION_STATE
        !           473:                                exception = EXC_BAD_INSTRUCTION;
        !           474:                                code = EXC_PPC_UNIPL_INST;
        !           475:                                subcode = ssp->srr0;
        !           476:                        } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) {
        !           477:                                TRAP_DEBUG(TRAP_PROGRAM,
        !           478:                                           ("PRIVILEGED INSTRUCTION\n"));
        !           479: 
        !           480:                                UPDATE_PPC_EXCEPTION_STATE;
        !           481:                                exception = EXC_BAD_INSTRUCTION;
        !           482:                                code = EXC_PPC_PRIVINST;
        !           483:                                subcode = ssp->srr0;
        !           484:                        } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
        !           485:                                unsigned int inst;
        !           486: 
        !           487:                                if (copyin((char *) ssp->srr0, (char *) &inst, 4 ))
        !           488:                                        panic("copyin failed\n");
        !           489:                                UPDATE_PPC_EXCEPTION_STATE;
        !           490:                                if (inst == 0x7FE00008) {
        !           491:                                        exception = EXC_BREAKPOINT;
        !           492:                                        code = EXC_PPC_BREAKPOINT;
        !           493:                                } else {
        !           494:                                        exception = EXC_SOFTWARE;
        !           495:                                        code = EXC_PPC_TRAP;
        !           496:                                }
        !           497:                                subcode = ssp->srr0;
        !           498:                        }
        !           499:                        break;
        !           500:                        
        !           501:                case T_ALTIVEC_ASSIST:
        !           502:                        UPDATE_PPC_EXCEPTION_STATE;
        !           503:                        exception = EXC_ARITHMETIC;
        !           504:                        code = EXC_PPC_ALTIVECASSIST;
        !           505:                        subcode = ssp->srr0;
        !           506:                        break;
        !           507: 
        !           508:                case T_DATA_ACCESS:
        !           509:                        TRAP_DEBUG(TRAP_DATA,
        !           510:                                   ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           511:                        
        !           512:                        map = thr_act->map;
        !           513:                        
        !           514:                        code = vm_fault(map, trunc_page(dar),
        !           515:                                 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
        !           516:                                 FALSE);
        !           517:                        if (code != KERN_SUCCESS) {
        !           518:                                
        !           519:                                TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n"));
        !           520:                                UPDATE_PPC_EXCEPTION_STATE;
        !           521:                                exception = EXC_BAD_ACCESS;
        !           522:                                subcode = dar;
        !           523:                        }
        !           524:                        else { 
        !           525:                                ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
        !           526:                                ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
        !           527:                        }
        !           528:                        break;
        !           529:                        
        !           530:                case T_INSTRUCTION_ACCESS:
        !           531:                        TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
        !           532: 
        !           533:                        /* Same as for data access, except fault type
        !           534:                         * is PROT_EXEC and addr comes from srr0
        !           535:                         */
        !           536:                        map = thr_act->map;
        !           537:                        
        !           538:                        code = vm_fault(map, trunc_page(ssp->srr0),
        !           539:                                        PROT_EXEC, FALSE);
        !           540:                        if (code != KERN_SUCCESS) {
        !           541:                                
        !           542: 
        !           543:                                TRAP_DEBUG(TRAP_INSTRUCTION,
        !           544:                                           ("INSTR FAULT FAILED!\n"));
        !           545:                                UPDATE_PPC_EXCEPTION_STATE;
        !           546:                                exception = EXC_BAD_ACCESS;
        !           547:                                subcode = ssp->srr0;
        !           548:                        }
        !           549:                        else { 
        !           550:                                ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
        !           551:                                ssp->srr1 |= MASK(DSISR_HASH);                                  /* Make sure this is marked as a miss */
        !           552:                        }
        !           553:                        break;
        !           554: 
        !           555:                case T_AST:
        !           556:                        TRAP_DEBUG(TRAP_AST,("T_AST FROM USER MODE\n"));
        !           557:                        ast_taken(FALSE, AST_ALL, 0);
        !           558:                        break;
        !           559:                        
        !           560:                }
        !           561: #ifdef MACH_BSD
        !           562:                {
        !           563:                void bsd_uprofil(time_value_t *, unsigned int);
        !           564: 
        !           565:                bsd_uprofil(&tv, ssp->srr0);
        !           566:                }
        !           567: #endif /* MACH_BSD */
        !           568:        }
        !           569: 
        !           570:        if (exception) {
        !           571:                TRAP_DEBUG(TRAP_EXCEPTION,
        !           572:                           ("doexception (0x%x, 0x%x, 0x%x\n",
        !           573:                            exception,code,subcode));
        !           574:                                
        !           575: #if 0
        !           576:                __asm__ volatile("tweq r1,r1");                 /* (TEST/DEBUG) */
        !           577: #endif         
        !           578:                                
        !           579:                doexception(exception, code, subcode);
        !           580:                return ssp;
        !           581:        }
        !           582:        /* AST delivery
        !           583:         * Check to see if we need an AST, if so take care of it here
        !           584:         */
        !           585: 
        !           586:        mp_disable_preemption();                                                        /* We can't preempt here */
        !           587:        while (ast_needed(cpu_number()) && USER_MODE(ssp->srr1))        {
        !           588:                mp_enable_preemption();                                                 /* ast_taken doesn't expect preemption disabled */
        !           589:                ast_taken(FALSE, AST_ALL, 0);
        !           590:                mp_disable_preemption();                                                /* Disable pretemption for check */
        !           591:        }
        !           592:        mp_enable_preemption();                                                         /* Preemption be cool again */
        !           593: 
        !           594:        return ssp;
        !           595: }
        !           596: 
        !           597: /* This routine is called from assembly before each and every system call.
        !           598:  * It must preserve r3.
        !           599:  */
        !           600: 
        !           601: extern int syscall_trace(int, struct ppc_saved_state *);
        !           602: 
        !           603: 
        !           604: extern int pmdebug;
        !           605: 
        !           606: int syscall_trace(int retval, struct ppc_saved_state *ssp)
        !           607: {
        !           608:        int i, argc;
        !           609: 
        !           610:        int kdarg[3];
        !           611:        /* Always prepare to trace mach system calls */
        !           612:        if (kdebug_enable && (ssp->r0 & 0x80000000)) {
        !           613:          /* Mach trap */
        !           614:          kdarg[0]=0;
        !           615:          kdarg[1]=0;
        !           616:          kdarg[2]=0;
        !           617:          argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
        !           618:          if (argc > 3)
        !           619:            argc = 3;
        !           620:          for (i=0; i < argc; i++)
        !           621:            kdarg[i] = (int)*(&ssp->r3 + i);
        !           622:          KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->r0))) | DBG_FUNC_START,
        !           623:                       kdarg[0], kdarg[1], kdarg[2], 0, 0);
        !           624:        }           
        !           625: 
        !           626: #if MACH_ASSERT
        !           627:        if (trapdebug & TRAP_SYSCALL)
        !           628:                trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL);
        !           629: 
        !           630:        if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL)))
        !           631:                return retval;
        !           632:        if (ssp->r0 & 0x80000000) {
        !           633:                /* Mach trap */
        !           634:                if (!(trapdebug & TRAP_MACH_SYSCALL))
        !           635:                        return retval;
        !           636: 
        !           637:                printf("0x%08x : %30s (",
        !           638:                       ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name);
        !           639:                argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
        !           640:                for (i = 0; i < argc; i++)
        !           641:                        printf("%08x ",*(&ssp->r3 + i));
        !           642:                printf(")\n");
        !           643:        } else {
        !           644:                if (!(trapdebug & TRAP_SERVER_SYSCALL))
        !           645:                        return retval;
        !           646:                printf("0x%08x : UNIX %3d (", ssp->srr0, ssp->r0);
        !           647:                argc = 4; /* print 4 of 'em! */
        !           648:                for (i = 0; i < argc; i++)
        !           649:                        printf("%08x ",*(&ssp->r3 + i));
        !           650:                printf(")\n");
        !           651:        }
        !           652: #endif /* MACH_ASSERT */
        !           653:        return retval;
        !           654: }
        !           655: 
        !           656: /* This routine is called from assembly after each mach system call
        !           657:  * It must preserve r3.
        !           658:  */
        !           659: 
        !           660: extern int syscall_trace_end(int, struct ppc_saved_state *);
        !           661: 
        !           662: int syscall_trace_end(int retval, struct ppc_saved_state *ssp)
        !           663: {
        !           664:        if (kdebug_enable && (ssp->r0 & 0x80000000)) {
        !           665:          /* Mach trap */
        !           666:          KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(ssp->r0))) | DBG_FUNC_END,
        !           667:                       retval, 0, 0, 0, 0);
        !           668:        }           
        !           669:        return retval;
        !           670: }
        !           671: 
        !           672: /*
        !           673:  * called from syscall if there is an error
        !           674:  */
        !           675: 
        !           676: int syscall_error(
        !           677:        int exception,
        !           678:        int code,
        !           679:        int subcode,
        !           680:        struct ppc_saved_state *ssp)
        !           681: {
        !           682:        register thread_t thread;
        !           683: 
        !           684:        thread = current_thread();
        !           685: 
        !           686:        if (thread == 0)
        !           687:            panic("syscall error in boot phase");
        !           688: 
        !           689:        if (!USER_MODE(ssp->srr1))
        !           690:                panic("system call called from kernel");
        !           691: 
        !           692:        doexception(exception, code, subcode);
        !           693: 
        !           694:        return 0;
        !           695: }
        !           696: 
        !           697: /* Pass up a server syscall/exception */
        !           698: void
        !           699: doexception(
        !           700:            int exc,
        !           701:            int code,
        !           702:            int sub)
        !           703: {
        !           704:        exception_data_type_t   codes[EXCEPTION_CODE_MAX];
        !           705: 
        !           706:        codes[0] = code;        
        !           707:        codes[1] = sub;
        !           708:        exception(exc, codes, 2);
        !           709: }
        !           710: 
        !           711: char *trap_type[] = {
        !           712:        "0x000   Interrupt in vain",
        !           713:        "0x100   System reset",
        !           714:        "0x200   Machine check",
        !           715:        "0x300   Data access",
        !           716:        "0x400   Instruction access",
        !           717:        "0x500   External interrupt",
        !           718:        "0x600   Alignment",
        !           719:        "0x700   Program",
        !           720:        "0x800   Floating point",
        !           721:        "0x900   Decrementer",
        !           722:        "0xA00   I/O controller interface",
        !           723:        "0xB00   INVALID EXCEPTION",
        !           724:        "0xC00   System call exception",
        !           725:        "0xD00   Trace",
        !           726:        "0xE00   FP assist",
        !           727:        "0xF20   VMX",
        !           728:        "0xF00   INVALID EXCEPTION",
        !           729:        "0x1000  Instruction PTE miss",
        !           730:        "0x1100  Data load PTE miss",
        !           731:        "0x1200  Data store PTE miss",
        !           732:        "0x1300  Instruction Breakpoint",
        !           733:        "0x1400  System Management",
        !           734:        "0x1500  INVALID EXCEPTION",
        !           735:        "0x1600  Altivec Assist",
        !           736:        "0x1700  INVALID EXCEPTION",
        !           737:        "0x1800  INVALID EXCEPTION",
        !           738:        "0x1900  INVALID EXCEPTION",
        !           739:        "0x1A00  INVALID EXCEPTION",
        !           740:        "0x1B00  INVALID EXCEPTION",
        !           741:        "0x1C00  INVALID EXCEPTION",
        !           742:        "0x1D00  INVALID EXCEPTION",
        !           743:        "0x1E00  INVALID EXCEPTION",
        !           744:        "0x1F00  INVALID EXCEPTION",
        !           745:        "0x2000  Run Mode/Trace"
        !           746: };
        !           747: int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
        !           748: 
        !           749: void unresolved_kernel_trap(int trapno,
        !           750:                            struct ppc_saved_state *ssp,
        !           751:                            unsigned int dsisr,
        !           752:                            unsigned int dar,
        !           753:                            char *message)
        !           754: {
        !           755:        unsigned int* stackptr;
        !           756:        char *trap_name;
        !           757:        int i, lr;
        !           758:        extern void print_backtrace(struct ppc_saved_state *);
        !           759:        extern unsigned int debug_mode, disableDebugOuput;
        !           760: 
        !           761:        disableDebugOuput = FALSE;
        !           762:        debug_mode++;
        !           763:        if ((unsigned)trapno <= T_MAX)
        !           764:                trap_name = trap_type[trapno / T_VECTOR_SIZE];
        !           765:        else
        !           766:                trap_name = "???? unrecognized exception";
        !           767:        if (message == NULL)
        !           768:                message = trap_name;
        !           769: 
        !           770:        printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x PC=0x%08x\n"
        !           771:               "generating stack backtrace prior to panic:\n\n",
        !           772:               trap_name, dsisr, dar, ssp->srr0);
        !           773: 
        !           774:        printf("backtrace: %08x ", ssp->srr0);
        !           775: 
        !           776:        stackptr = (unsigned int *)(ssp->r1);
        !           777: 
        !           778: #ifdef __ELF__
        !           779:        lr = 1;
        !           780: #else
        !           781:        lr = 2;
        !           782: #endif
        !           783: 
        !           784:        print_backtrace(ssp);
        !           785: 
        !           786: #if    MACH_KDB || MACH_KDP
        !           787:        (void *)Call_Debugger(trapno, ssp);
        !           788: #endif
        !           789:        panic(message);
        !           790: }
        !           791: 
        !           792: #if    MACH_KDB
        !           793: void
        !           794: thread_kdb_return(void)
        !           795: {
        !           796:        register thread_act_t   thr_act = current_act();
        !           797:        register thread_t       cur_thr = current_thread();
        !           798:        register struct ppc_saved_state *regs = USER_REGS(thr_act);
        !           799: 
        !           800:        Call_Debugger(thr_act->mact.pcb->es.exception, regs);
        !           801: #if            MACH_LDEBUG
        !           802:        assert(cur_thr->mutex_count == 0); 
        !           803: #endif         /* MACH_LDEBUG */
        !           804:        check_simple_locks();
        !           805:        thread_exception_return();
        !           806:        /*NOTREACHED*/
        !           807: }
        !           808: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.