Annotation of kernel/machdep/ppc/trap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: #include <debug.h>
                     26: #include <cpus.h>
                     27: #include <kern/thread.h>
                     28: #include <mach/exception.h>
                     29: #include <kern/syscall_sw.h>
                     30: #include <machdep/ppc/cpu_data.h>
                     31: #include <mach/thread_status.h>
                     32: #include <vm/vm_fault.h>
                     33: #include <vm/vm_kern.h>        /* For kernel_map */
                     34: #include <mach/vm_param.h>
                     35: #include <machdep/ppc/trap.h>
                     36: #include <machdep/ppc/exception.h>
                     37: #include <machdep/ppc/proc_reg.h>      /* for SR_xxx definitions */
                     38: #include <machdep/ppc/pmap.h>
                     39: #include <machine/label_t.h>
                     40: 
                     41: #include <sys/param.h>
                     42: #include <sys/proc.h>
                     43: #include <sys/resourcevar.h>
                     44: 
                     45: #include <machdep/ppc/ast.h>
                     46: extern void fpu_save(void);
                     47: #define NULL 0
                     48: 
                     49: #if DEBUG
                     50: #define TRAP_ALL               -1
                     51: #define TRAP_ALIGNMENT         0x01
                     52: #define TRAP_DATA              0x02
                     53: #define TRAP_INSTRUCTION       0x04
                     54: #define TRAP_AST               0x08
                     55: #define TRAP_TRACE             0x10
                     56: #define TRAP_PROGRAM           0x20
                     57: #define TRAP_EXCEPTION         0x40
                     58: #define TRAP_UNRESOLVED                0x80
                     59: #define TRAP_SYSCALL           0x100   /* all syscalls */
                     60: #define TRAP_HW                        0x200   /* all in hw_exception.s */
                     61: #define TRAP_MACH_SYSCALL      0x400
                     62: #define TRAP_SERVER_SYSCALL    0x800
                     63: 
                     64: int trapdebug=0;
                     65: 
                     66: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){kprintf A;}}
                     67: #else
                     68: #define TRAP_DEBUG(LEVEL, A)
                     69: #endif
                     70: 
                     71: /*
                     72:  * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied
                     73:  * in either R or RW (note: the pmap module knows this).  This is done for the
                     74:  * benefit of programs that execute out of their data space (ala lisp).
                     75:  * If we didn't do this in that scenerio, the ITLB miss code would call us
                     76:  * and we would call vm_fault() with RX permission.  However, the space was
                     77:  * probably vm_allocate()ed with just RW and vm_fault would fail.  The "right"
                     78:  * solution to me is to have the un*x server always allocate data with RWX for
                     79:  * compatibility with existing binaries.
                     80:  */
                     81: 
                     82: #define        PROT_EXEC       (VM_PROT_READ)
                     83: #define PROT_RO                (VM_PROT_READ)
                     84: #define PROT_RW                (VM_PROT_READ|VM_PROT_WRITE)
                     85: 
                     86: #define IS_KLOADED(pc) ((vm_offset_t)pc > VM_MIN_KERNEL_LOADED_ADDRESS)
                     87: 
                     88: /* A useful macro to update the ppc_exception_state in the PCB
                     89:  * before calling doexception
                     90:  */
                     91: #define UPDATE_PPC_EXCEPTION_STATE {                                         \
                     92:        thread_t th = current_thread();                               \
                     93:        struct ppc_exception_state *es = &th->pcb->es;        \
                     94:        es->dar = dar;                                                        \
                     95:        es->dsisr = dsisr;                                                    \
                     96:        es->exception = trapno / EXC_VECTOR_SIZE;       /* back to powerpc */ \
                     97: }
                     98: 
                     99: static void unresolved_kernel_trap(int trapno,
                    100:                                   struct ppc_saved_state *ssp,
                    101:                                   unsigned int dsisr,
                    102:                                   unsigned int dar,
                    103:                                   char *message);
                    104: 
                    105: struct ppc_saved_state *trap(int trapno,
                    106:                             struct ppc_saved_state *ssp,
                    107:                             unsigned int dsisr,
                    108:                             unsigned int dar)
                    109: {
                    110:        int exception=0;
                    111:        int code;
                    112:        int subcode;
                    113:        vm_map_t map;
                    114:     unsigned int sp;
                    115:        unsigned int space,space2;
                    116:        unsigned int offset;
                    117:        thread_t th = current_thread();
                    118:        int error;
                    119:     struct proc                        *p = th->task->proc;
                    120:     struct timeval             syst;
                    121: 
                    122:        TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n",
                    123:                     trapno/4,ssp->srr0,ssp->srr1));
                    124: 
                    125:        /* Handle kernel traps first */
                    126: 
                    127:        if (!USER_MODE(ssp->srr1)) {
                    128:                /*
                    129:                 * Trap came from system task, ie kernel or collocated server
                    130:                 */
                    131:                switch (trapno) {
                    132:                        /*
                    133:                         * These trap types should never be seen by trap()
                    134:                         * in kernel mode, anyway.
                    135:                         * Some are interrupts that should be seen by
                    136:                         * interrupt() others just don't happen because they
                    137:                         * are handled elsewhere. Some could happen but are
                    138:                         * considered to be fatal in kernel mode.
                    139:                         */
                    140:                case EXC_DECREMENTER:
                    141:                case EXC_INVALID:
                    142:                case EXC_RESET:
                    143:                case EXC_MACHINE_CHECK:
                    144:                case EXC_SYSTEM_MANAGEMENT:
                    145:                case EXC_INTERRUPT:
                    146:                case EXC_FP_UNAVAILABLE:
                    147:                case EXC_IO_ERROR:
                    148:                default:
                    149:                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    150:                        break;
                    151:                        
                    152:                case EXC_TRACE:
                    153: #if DEBUG
                    154:                        enter_debugger(trapno, dsisr, dar, ssp, 0);
                    155: #else
                    156:                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    157: #endif
                    158:                        break;
                    159: 
                    160:                case EXC_RUNMODE_TRACE:
                    161:                case EXC_INSTRUCTION_BKPT:
                    162:                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    163:                        break;
                    164: 
                    165:                case EXC_PROGRAM:
                    166:                        if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
                    167: #if DEBUG
                    168:                                enter_debugger(trapno, dsisr, dar, ssp, 0);
                    169: #else
                    170:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    171: #endif /* DEBUG */
                    172:                        } else {
                    173:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    174:                        }
                    175:                        break;
                    176:                case EXC_ALIGNMENT:
                    177:                        TRAP_DEBUG(TRAP_ALIGNMENT,
                    178:                                   ("NMGS KERNEL ALIGNMENT_ACCESS, "
                    179:                                     "DAR=0x%08x, DSISR = 0x%08X\n",
                    180:                                     dar, dsisr,
                    181:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    182:                        if (alignment(dsisr, dar, ssp)) {
                    183:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    184:                        }
                    185:                        break;
                    186:                case EXC_DATA_ACCESS:
                    187:                        TRAP_DEBUG(TRAP_DATA,
                    188:                                   ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x,"
                    189:                                     "DSISR = 0x%08X\n", dar, dsisr,
                    190:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    191: 
                    192:                        if (dsisr & MASK(DSISR_WATCH)) {
                    193:                                printf("dabr ");
                    194: #if DEBUG
                    195:                                enter_debugger(trapno, dsisr,dar,ssp, 1);
                    196: #else
                    197:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    198: #endif
                    199:                                break;
                    200:                        }
                    201:                        /* simple case : not SR_COPYIN segment, from kernel */
                    202:                        if ((dar >> 28) != SR_COPYIN) {
                    203:                                /* if from kloaded task, use task mapping */
                    204: #if notdef_next  /* NeXT kernloaded modules use the kernel map */
                    205:                                if(IS_KLOADED(ssp->srr0))
                    206:                                        map = th->task->map;
                    207:                                else 
                    208: #endif /* notdef_next */
                    209:                                        map = kernel_map;
                    210: 
                    211:                                offset = dar;
                    212:                                TRAP_DEBUG(TRAP_DATA,
                    213:                                           ("SYSTEM FAULT FROM 0x%08x\n",
                    214:                                            offset));
                    215:                                code = vm_fault(map,
                    216:                                                trunc_page(offset),
                    217:                                                dsisr & MASK(DSISR_WRITE) ?
                    218:                                                        PROT_RW : PROT_RO,
                    219:                                                FALSE,
                    220:                                                &error);
                    221:                                if (code != KERN_SUCCESS) {
                    222: #if DEBUG
                    223:                                        if (th->recover) {
                    224:                                                label_t *l = (label_t *)th->recover;
                    225:                                                th->recover = (vm_offset_t)NULL;
                    226:                                                longjmp(l,1);
                    227:                                        } else {
                    228:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    229:                                        }
                    230: #else
                    231:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    232: #endif
                    233:                                }
                    234:                                break;
                    235:                        }
                    236: 
                    237:                        /* If we get here, the fault was due to a copyin/out */
                    238: 
                    239:                        map = th->task->map;
                    240: 
                    241:                        /* Mask out SR_COPYIN and mask in original segment */
                    242: 
                    243:                        offset = (dar & 0x0fffffff) |
                    244:                                ((mfsrin(dar) & 0xF) << 28);
                    245: 
                    246:                        TRAP_DEBUG(TRAP_DATA,
                    247:                                   ("sr=0x%08x, dar=0x%08x, sp=0x%x\n",
                    248:                                    mfsrin(dar), dar,map->pmap->space));
                    249:                        assert(((mfsrin(dar) & 0x0FFFFFFF) >> 4) ==
                    250:                               map->pmap->space);
                    251:                        TRAP_DEBUG(TRAP_DATA,
                    252:                                   ("KERNEL FAULT FROM 0x%x,0x%08x\n",
                    253:                                    map->pmap->space, offset));
                    254: 
                    255:                        code = vm_fault(map,
                    256:                                        trunc_page(offset),
                    257:                                        dsisr & MASK(DSISR_WRITE) ?
                    258:                                        PROT_RW : PROT_RO,
                    259:                                        FALSE,
                    260:                                        &error);
                    261: 
                    262:                        /* If we failed, there should be a recovery
                    263:                         * spot to rfi to.
                    264:                         */
                    265:                        if (code != KERN_SUCCESS) {
                    266:                                TRAP_DEBUG(TRAP_DATA,
                    267:                                           ("FAULT FAILED- srr0=0x%08x,"
                    268:                                             "pcb-srr0=0x%08x\n",
                    269:                                             ssp->srr0,
                    270:                                             th->pcb->ss.srr0));
                    271: 
                    272:                                if (th->recover) {
                    273:                                        label_t *l = (label_t *)th->recover;
                    274:                                        th->recover = (vm_offset_t)NULL;
                    275:                                        longjmp(l, 1);
                    276:                                } else {
                    277:                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
                    278:                                }
                    279:                        }
                    280:                        break;
                    281:                        
                    282:                case EXC_INSTRUCTION_ACCESS:
                    283:                        /* Colocated tasks aren't necessarily wired and
                    284:                         * may page fault
                    285:                         */
                    286:                        TRAP_DEBUG(TRAP_INSTRUCTION,
                    287:                                   ("NMGS KERNEL INSTRUCTION ACCESS,"
                    288:                                     "DSISR = 0x%B\n", dsisr,
                    289:                             "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    290: 
                    291: #if DEBUG
                    292:                                enter_debugger(trapno, dsisr,dar,ssp, 1);
                    293: #else
                    294:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    295: #endif
                    296: #if 0
                    297:                        /* Make sure it's not the kernel itself faulting */
                    298:                        assert ((ssp->srr0 >= VM_MIN_KERNEL_LOADED_ADDRESS) &&
                    299:                                (ssp->srr0 <  VM_MAX_KERNEL_LOADED_ADDRESS));
                    300: 
                    301:                        /* Same as for data access, except fault type
                    302:                         * is PROT_EXEC and addr comes from srr0
                    303:                         */
                    304:                        map = th->task->map;
                    305:                        space = PPC_SID_KERNEL;
                    306:                        
                    307:                        code = vm_fault(map, trunc_page(ssp->srr0),
                    308:                                        PROT_EXEC, FALSE,
                    309:                                        &error);
                    310:                        if (code != KERN_SUCCESS) {
                    311:                                TRAP_DEBUG(TRAP_INSTRUCTION,
                    312:                                           ("INSTR FAULT FAILED!\n"));
                    313:                                exception = EXC_BAD_ACCESS;
                    314:                                subcode = ssp->srr0;
                    315:                        }
                    316: #endif
                    317:                        break;
                    318: 
                    319:                case EXC_AST:
                    320:                        TRAP_DEBUG(TRAP_AST,
                    321:                                   ("EXC_AST FROM KERNEL MODE\n"));
                    322:                        check_for_ast();
                    323:                        break;
                    324:                }
                    325:        } else {
                    326:                /*
                    327:                 * Trap came from user task
                    328:                 */
                    329: 
                    330:                if (p)
                    331:                        syst = p->p_stats->p_ru.ru_stime;
                    332: 
                    333: 
                    334:                switch (trapno) {
                    335:                        /*
                    336:                         * These trap types should never be seen by trap()
                    337:                         * Some are interrupts that should be seen by
                    338:                         * interrupt() others just don't happen because they
                    339:                         * are handled elsewhere.
                    340:                         */
                    341:                case EXC_DECREMENTER:
                    342:                case EXC_INVALID:
                    343:                case EXC_MACHINE_CHECK:
                    344:                case EXC_INTERRUPT:
                    345:                case EXC_FP_UNAVAILABLE:
                    346:                case EXC_SYSTEM_MANAGEMENT:
                    347:                case EXC_IO_ERROR:
                    348:                        
                    349:                default:
                    350:                        panic("Unexpected exception type, %d 0x%x", trapno, trapno);
                    351:                        break;
                    352: 
                    353:                case EXC_RESET:
                    354:                        powermac_reboot();           /* never returns */
                    355: 
                    356:                case EXC_ALIGNMENT:
                    357:                        TRAP_DEBUG(TRAP_ALIGNMENT,
                    358:                                   ("NMGS USER ALIGNMENT_ACCESS, "
                    359:                                     "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,
                    360:                                     "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    361:                        if (alignment(dsisr, dar, ssp)) {
                    362:                                code = EXC_PPC_UNALIGNED;
                    363:                                exception = EXC_BAD_ACCESS;
                    364:                                subcode = dar;
                    365:                        }
                    366:                        break;
                    367: 
                    368:                case EXC_TRACE:                 /* Real PPC chips */
                    369:                case EXC_INSTRUCTION_BKPT:      /* 603  PPC chips */
                    370:                case EXC_RUNMODE_TRACE:         /* 601  PPC chips */
                    371:                        TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n"));
                    372:                        exception = EXC_BREAKPOINT;
                    373:                        code = EXC_PPC_TRACE;
                    374:                        subcode = ssp->srr0;
                    375:                        break;
                    376: 
                    377:                case EXC_PROGRAM:
                    378:                        TRAP_DEBUG(TRAP_PROGRAM,
                    379:                                   ("NMGS PROGRAM TRAP\n"));
                    380:                        if (ssp->srr1 & MASK(SRR1_PRG_FE)) {
                    381:                                TRAP_DEBUG(TRAP_PROGRAM,
                    382:                                           ("FP EXCEPTION\n"));
                    383:                                fpu_save();
                    384:                                fpu_disable();
                    385:                                UPDATE_PPC_EXCEPTION_STATE;
                    386:                                exception = EXC_ARITHMETIC;
                    387:                                code = EXC_ARITHMETIC;
                    388:                                subcode = per_proc_info[cpu_number()].
                    389:                                        fpu_pcb->fs.fpscr;
                    390:                        } else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) {
                    391:                                TRAP_DEBUG(TRAP_PROGRAM,
                    392:                                           ("ILLEGAL INSTRUCTION\n"));
                    393: 
                    394:                                UPDATE_PPC_EXCEPTION_STATE
                    395:                                exception = EXC_BAD_INSTRUCTION;
                    396:                                code = EXC_PPC_UNIPL_INST;
                    397:                                subcode = ssp->srr0;
                    398:                        } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) {
                    399:                                TRAP_DEBUG(TRAP_PROGRAM,
                    400:                                           ("PRIVILEGED INSTRUCTION\n"));
                    401: 
                    402:                                UPDATE_PPC_EXCEPTION_STATE;
                    403:                                exception = EXC_BAD_INSTRUCTION;
                    404:                                code = EXC_PPC_PRIVINST;
                    405:                                subcode = ssp->srr0;
                    406:                        } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
                    407: #if MACH_KGDB
                    408:                                /* Give kernel debugger a chance to
                    409:                                 * claim the breakpoint before passing
                    410:                                 * it up as an exception
                    411:                                 */
                    412:                                if (kgdb_user_breakpoint(ssp)) {
                    413:                                        call_kgdb_with_ctx(EXC_PROGRAM,
                    414:                                                           0,
                    415:                                                           ssp);
                    416:                                        break;
                    417:                                }
                    418: #endif /* MACH_KGDB */
                    419: 
                    420:                                UPDATE_PPC_EXCEPTION_STATE;
                    421:                                exception = EXC_BREAKPOINT;
                    422:                                code = EXC_PPC_BREAKPOINT;
                    423:                                subcode = ssp->srr0;
                    424:                        }
                    425:                        break;
                    426: 
                    427:                case EXC_DATA_ACCESS:
                    428:                        TRAP_DEBUG(TRAP_DATA,
                    429:                                   ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    430:                        
                    431:                        if (dsisr & MASK(DSISR_WATCH)) {
                    432:                                printf("dabr ");
                    433: #if DEBUG
                    434:                                enter_debugger(trapno, dsisr,dar,ssp, 1);
                    435: #else
                    436:                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                    437: #endif
                    438:                                break;
                    439:                        }
                    440:                        map = th->task->map;
                    441:                        space = map->pmap->space;
                    442:                        assert(space != 0);
                    443: #if DEBUG
                    444:                        mfsr(space2, SR_UNUSED_BY_KERN);
                    445:                        space2 = (space2 >> 4) & 0x00FFFFFF;
                    446: 
                    447:                        /* Do a check that at least SR_UNUSED_BY_KERN
                    448:                         * is in the correct user space.
                    449:                         * TODO NMGS may not be true as ints are on?.
                    450:                         */
                    451:                        assert(space2 == space);
                    452: #if 0
                    453:                        TRAP_DEBUG(TRAP_DATA,("map = 0x%08x, space=0x%08x, addr=0x%08x\n",map, space, trunc_page(dar));
                    454: #endif
                    455: #endif /* DEBUG */
                    456:                        
                    457:                        code = vm_fault(map, trunc_page(dar),
                    458:                                 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
                    459:                                 FALSE,
                    460:                                 &error);
                    461:                        if (code != KERN_SUCCESS) {
                    462:                                TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n"));
                    463:                                UPDATE_PPC_EXCEPTION_STATE;
                    464:                                exception = EXC_BAD_ACCESS;
                    465:                                subcode = dar;
                    466:                        }
                    467:                        break;
                    468:                        
                    469:                case EXC_INSTRUCTION_ACCESS:
                    470:                        TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
                    471: 
                    472:                        /* Same as for data access, except fault type
                    473:                         * is PROT_EXEC and addr comes from srr0
                    474:                         */
                    475:                        map = th->task->map;
                    476:                        space = map->pmap->space;
                    477:                        assert(space != 0);
                    478: #if DEBUG
                    479:                        mfsr(space2, SR_UNUSED_BY_KERN);
                    480:                        space2 = (space2 >> 4) & 0x00FFFFFF;
                    481: 
                    482:                        /* Do a check that at least SR_UNUSED_BY_KERN
                    483:                         * is in the correct user space.
                    484:                         * TODO NMGS is this always true now ints are on?
                    485:                         */
                    486:                        assert(space2 == space);
                    487: #endif /* DEBUG */
                    488:                        
                    489:                        code = vm_fault(map, trunc_page(ssp->srr0),
                    490:                                        PROT_EXEC, FALSE,
                    491:                                        &error);
                    492:                        if (code != KERN_SUCCESS) {
                    493:                                TRAP_DEBUG(TRAP_INSTRUCTION,
                    494:                                           ("INSTR FAULT FAILED!\n"));
                    495:                                UPDATE_PPC_EXCEPTION_STATE;
                    496:                                exception = EXC_BAD_ACCESS;
                    497:                                subcode = ssp->srr0;
                    498:                        }
                    499:                        break;
                    500: 
                    501:                case EXC_AST:
                    502:                        TRAP_DEBUG(TRAP_AST,("EXC_AST FROM USER MODE\n"));
                    503:                        check_for_ast();
                    504:                        break;
                    505:                        
                    506:                }
                    507:        }
                    508: 
                    509:        if (exception) {
                    510:                TRAP_DEBUG(TRAP_EXCEPTION,
                    511:                   ("doexception (0x%x, 0x%x, 0x%x, 0x%x, pc = 0x%x in %s)\n",
                    512:                   exception,code,subcode, th, th->pcb->ss.srr0,
                    513:                   &th->task->proc->p_comm));
                    514:                doexception(exception, code, subcode, th);
                    515:                return ssp;
                    516:        }
                    517: 
                    518:     if (USER_MODE(ssp->srr1)) {
                    519:                if (p && (p->p_flag & P_PROFIL)) {
                    520:                        int             ticks;
                    521:                        struct timeval  *tv = &p->p_stats->p_ru.ru_stime;
                    522:                                        
                    523:                        ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
                    524:                                        (tv->tv_usec - syst.tv_usec) / 1000) /
                    525:                                        (tick / 1000);
                    526:                        if (ticks)
                    527:                                addupc_task(p, ssp->srr0, ticks);
                    528:                }
                    529:        }
                    530:        return ssp;
                    531: }
                    532: 
                    533: #if MACH_ASSERT
                    534: /* This routine is called from assembly before each and every system call
                    535:  * iff MACH_ASSERT is defined. It must preserve r3.
                    536:  */
                    537: 
                    538: extern int syscall_trace(int, struct ppc_saved_state *);
                    539: 
                    540: int syscall_trace(int retval, struct ppc_saved_state *ssp)
                    541: {
                    542:        int i, argc;
                    543: 
                    544:        if (trapdebug & TRAP_SYSCALL)
                    545:                trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL);
                    546: 
                    547:        if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL)))
                    548:                return retval;
                    549:        if (ssp->r0 & 0x80000000) {
                    550:                /* Mach trap */
                    551:                if (!(trapdebug & TRAP_MACH_SYSCALL))
                    552:                        return retval;
                    553: 
                    554:                printf("0x%08x : %30s (",
                    555:                       ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name);
                    556:                argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
                    557:                for (i = 0; i < argc; i++)
                    558:                        printf("%08x ",*(&ssp->r3 + i));
                    559:                printf(")\n");
                    560:        } else {
                    561:                if (!(trapdebug & TRAP_SERVER_SYSCALL))
                    562:                        return retval;
                    563:                printf("0x%08x : RHAPSODY %3d (", ssp->srr0, ssp->r0);
                    564:                argc = 4; /* print 4 of 'em! */
                    565:                for (i = 0; i < argc; i++)
                    566:                        printf("%08x ",*(&ssp->r3 + i));
                    567:                printf(")\n");
                    568:        }
                    569:        return retval;
                    570: }
                    571: #endif /* MACH_ASSERT */
                    572: 
                    573: /*
                    574:  * called from syscall if there is an error
                    575:  */
                    576: 
                    577: int syscall_error(
                    578:        int exception,
                    579:        int code,
                    580:        int subcode,
                    581:        struct ppc_saved_state *ssp)
                    582: {
                    583:        register thread_t thread;
                    584: 
                    585:        thread = current_thread();
                    586: 
                    587:        if (thread == 0)
                    588:            panic("syscall error in boot phase");
                    589: 
                    590:        if (!USER_MODE(ssp->srr1))
                    591:                panic("system call called from kernel");
                    592: 
                    593:        doexception(exception, code, subcode, thread);
                    594: 
                    595:        return 0;
                    596: }
                    597: 
                    598: /* Pass up a server syscall/exception */
                    599: void
                    600: doexception(
                    601:            int exc,
                    602:            int code,
                    603:            int sub,
                    604:            thread_t th)
                    605: {
                    606:        exception(exc, code, sub);
                    607: }
                    608: 
                    609: char *trap_type[] = {
                    610:        "0x0000  INVALID EXCEPTION",
                    611:        "0x0100  System reset",
                    612:        "0x0200  Machine check",
                    613:        "0x0300  Data access",
                    614:        "0x0400  Instruction access",
                    615:        "0x0500  External interrupt",
                    616:        "0x0600  Alignment",
                    617:        "0x0700  Program",
                    618:        "0x0800  Floating point",
                    619:        "0x0900  Decrementer",
                    620:        "0x0A00  I/O controller interface",
                    621:        "0x0B00  INVALID EXCEPTION",
                    622:        "0x0C00  System call exception",
                    623:        "0x0D00  Trace",
                    624:        "0x0E00  FP assist",
                    625:        "0x0F00  Performance monitoring",
                    626:        "0x1000  Instruction PTE miss",
                    627:        "0x1100  Data load PTE miss",
                    628:        "0x1200  Data store PTE miss",
                    629:        "0x1300  Instruction Breakpoint",
                    630:        "0x1400  System Management",
                    631:        "0x1500  INVALID EXCEPTION",
                    632:        "0x1600  INVALID EXCEPTION",
                    633:        "0x1700  INVALID EXCEPTION",
                    634:        "0x1800  INVALID EXCEPTION",
                    635:        "0x1900  INVALID EXCEPTION",
                    636:        "0x1A00  INVALID EXCEPTION",
                    637:        "0x1B00  INVALID EXCEPTION",
                    638:        "0x1C00  INVALID EXCEPTION",
                    639:        "0x1D00  INVALID EXCEPTION",
                    640:        "0x1E00  INVALID EXCEPTION",
                    641:        "0x1F00  INVALID EXCEPTION",
                    642:        "0x2000  Run Mode/Trace"
                    643:        "0x2100  INVALID EXCEPTION",
                    644:        "0x2200  INVALID EXCEPTION",
                    645:        "0x2300  INVALID EXCEPTION",
                    646:        "0x2400  INVALID EXCEPTION",
                    647:        "0x2500  INVALID EXCEPTION",
                    648:        "0x2600  INVALID EXCEPTION",
                    649:        "0x2700  INVALID EXCEPTION",
                    650:        "0x2800  INVALID EXCEPTION",
                    651:        "0x2900  INVALID EXCEPTION",
                    652:        "0x2A00  INVALID EXCEPTION",
                    653:        "0x2B00  INVALID EXCEPTION",
                    654:        "0x2C00  INVALID EXCEPTION",
                    655:        "0x2D00  INVALID EXCEPTION",
                    656:        "0x2E00  INVALID EXCEPTION",
                    657:        "0x2F00  INVALID EXCEPTION",
                    658: };
                    659: 
                    660: void unresolved_kernel_trap(int trapno,
                    661:                            struct ppc_saved_state *ssp,
                    662:                            unsigned int dsisr,
                    663:                            unsigned int dar,
                    664:                            char *message)
                    665: {
                    666:        char *trap_name;
                    667: 
                    668: #if notdef_next
                    669:        if(IS_KLOADED(ssp->srr0)) {
                    670:                int exception;
                    671: 
                    672:                TRAP_DEBUG(TRAP_UNRESOLVED,
                    673:                           ("unresolved trap %d in kernel loaded task %d\n",trapno));
                    674:                TRAP_DEBUG(TRAP_UNRESOLVED,
                    675:                           ("%s: sending exception message\n", message));
                    676:                switch(trapno) {
                    677:                case EXC_INVALID:
                    678:                case EXC_RESET:
                    679:                case EXC_MACHINE_CHECK:
                    680:                case EXC_INTERRUPT:
                    681:                case EXC_DECREMENTER:
                    682:                case EXC_IO_ERROR:
                    683:                case EXC_SYSTEM_CALL:
                    684:                case EXC_RUNMODE_TRACE:
                    685:                default:
                    686:                        exception = EXC_BREAKPOINT;
                    687:                        break;
                    688:                case EXC_ALIGNMENT:
                    689:                case EXC_INSTRUCTION_ACCESS:
                    690:                case EXC_DATA_ACCESS:
                    691:                        exception = EXC_BAD_ACCESS;
                    692:                        break;
                    693:                case EXC_PROGRAM:
                    694:                        exception = EXC_BAD_INSTRUCTION;
                    695:                        break;
                    696:                case EXC_FP_UNAVAILABLE:
                    697:                        /* TODO NMGS - should this generate EXC_ARITHMETIC?*/
                    698:                        exception = EXC_ARITHMETIC;
                    699:                        break;
                    700:                }
                    701:                UPDATE_PPC_EXCEPTION_STATE;
                    702:                doexception(exception, 0, 0, current_thread());
                    703:                return;
                    704:        }
                    705: #if DEBUG
                    706:        regDump(ssp);
                    707: #endif /* DEBUG */
                    708: #endif /* notdef_next */
                    709: 
                    710:        if ((unsigned)trapno <= EXC_MAX)
                    711:                trap_name = trap_type[trapno / EXC_VECTOR_SIZE];
                    712:        else
                    713:                trap_name = "???? unrecognised exception";
                    714:        if (message == NULL)
                    715:                message = trap_name;
                    716: 
                    717:        /* no KGDB so display a backtrace */
                    718:        printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x\n",
                    719:               trap_name, dsisr, dar);
                    720: 
                    721: #ifdef DEBUG
                    722:        enter_debugger(trapno, dsisr, dar, ssp, 1);
                    723: #else
                    724:        {
                    725:        unsigned int* stackptr;
                    726:        int i;
                    727:        printf("generating stack backtrace prior to panic:\n\n");
                    728: 
                    729:        printf("backtrace: 0x%08x ", ssp->srr0);
                    730: 
                    731:        stackptr = (unsigned int *)(ssp->r1);
                    732: 
                    733:        for (i = 0; i < 8; i++) {
                    734: 
                    735:                /* Avoid causing page fault */
                    736:                if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr) == 0)
                    737:                        break;
                    738: 
                    739:                stackptr = (unsigned int*)*stackptr;
                    740:                /*
                    741:                 * TODO NMGS - use FM_LR_SAVE constant, but asm.h defines
                    742:                 * too much (such as r1, used above)
                    743:                 */
                    744: 
                    745:                /* Avoid causing page fault */
                    746:                if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr+2) == 0)
                    747:                        break;
                    748: 
                    749:                printf("0x%08x ",*(stackptr + 2));
                    750:        }
                    751:        printf("\n\n");
                    752:        }
                    753: #endif
                    754: 
                    755:        panic(message);
                    756: }

unix.superglobalmegacorp.com

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