Annotation of XNU/osfmk/ppc/trap.c, revision 1.1.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.