Annotation of kernel/machdep/ppc/hw_exception.s, 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: /* Low level routines dealing with exception entry and exit.
                     26:  * There are various types of exception:
                     27:  *
                     28:  *    Interrupt, trap, system call and debugger entry. Each has it's own
                     29:  *    handler since the state save routine is different for each. The
                     30:  *    code is very similar (a lot of cut and paste).
                     31:  *
                     32:  *    The code for the FPU disabled handler (lazy fpu) is in cswtch.s
                     33:  */
                     34: 
                     35: #include <debug.h>
                     36: #include <mach_assert.h>
                     37: 
                     38: #include <mach/exception.h>
                     39: #include <mach/ppc/vm_param.h>
                     40: 
                     41: #include <assym.h>
                     42: 
                     43: #include <machdep/ppc/asm.h>
                     44: #include <machdep/ppc/proc_reg.h>
                     45: #include <machdep/ppc/trap.h>
                     46: #include <machdep/ppc/exception.h>
                     47: #include <kernserv/ppc/spl.h>
                     48: #include <machdep/ppc/machspl.h>
                     49: #include <kern/ast.h>
                     50:        
                     51: /*
                     52:  * thandler(type)
                     53:  *
                     54:  * Entry:      VM switched ON
                     55:  *             Interrupts  OFF
                     56:  *              original r1-3 saved in sprg1-3
                     57:  *              original srr0 and srr1 saved in per_proc_info structure
                     58:  *              original cr            saved in per_proc_info structure
                     59:  *              exception type         saved in per_proc_info structure
                     60:  *              r1 = scratch
                     61:  *              r2 = virt addr of per_proc_info 
                     62:  *             r3 = exception type (one of EXC_...)
                     63:  */
                     64: 
                     65: /*
                     66:  * If pcb.ksp == 0 then the kernel stack is already busy,
                     67:  *                 we save ppc_saved state below the current stack pointer,
                     68:  *                leaving enough space for the `red zone' in case the
                     69:  *                trapped thread was in the middle of saving state below
                     70:  *                its stack pointer.
                     71:  *
                     72:  * otherwise       we save a ppc_saved_state in the pcb, and switch to
                     73:  *                the kernel stack (setting pcb.ksp to 0)
                     74:  *
                     75:  * on return, we do the reverse, the last state is popped from the pcb
                     76:  * and pcb.ksp is set to the top of stack below the kernel state + frame
                     77:  * TODO NMGS - is this frame used? I don't think so
                     78:  *
                     79:  *                    Diagram of a thread's kernel stack
                     80:  *
                     81:  *               ---------------       TOP OF STACK
                     82:  *              |kernel_state   |
                     83:  *              |---------------|
                     84:  *              |backpointer FM |
                     85:  *              |---------------|                                      
                     86:  *              |... C usage ...|                                      
                     87:  *              |               |                                      
                     88:  *              |---------------|                       TRAP IN KERNEL CODE
                     89:  *              |ppc_saved_state|                       STATE SAVED HERE   
                     90:  *              |---------------|                                      
                     91:  *              |backpointer FM |                                       
                     92:  *              |---------------|                         
                     93:  *              |... C usage ...|                         
                     94:  *              |               |                         
                     95:  *              |               |                         
                     96:  *              |               |                         
                     97:  *              |               |                         
                     98:  */
                     99: 
                    100: 
                    101: #if DEBUG
                    102: 
                    103: /* TRAP_SPACE_NEEDED is the space assumed free on the kernel stack when
                    104:  * another trap is taken. We need at least enough space for a saved state
                    105:  * structure plus two small backpointer frames, and we add a few
                    106:  * hundred bytes for the space needed by the C (which may be less but
                    107:  * may be much more). We're trying to catch kernel stack overflows :-)
                    108:  */
                    109: 
                    110: #define TRAP_SPACE_NEEDED      FM_REDZONE+SS_SIZE+(2*FM_SIZE)+256
                    111: 
                    112: #endif /* DEBUG */
                    113: 
                    114:        .text
                    115: 
                    116: ENTRY(thandler, TAG_NO_FRAME_USED)     /* What tag should this have?! */
                    117: 
                    118:                /* If we're on the gdb stack, there has probably been
                    119:                 * a fault reading user memory or something like that,
                    120:                 * so we should pass this to the gdb handler. NOTE
                    121:                 * we may have entered gdb through an interrupt handler
                    122:                 * (keyboard or serial line, for example), so interrupt
                    123:                 * stack may be busy too.
                    124:                 */
                    125:        addis   r1,     0,      ha16(EXT(gdbstackptr))
                    126:        addi    r1,     r1,     lo16(EXT(gdbstackptr))  /* TODO assumes 1 CPU */
                    127:        lwz     r1,     0(r1)
                    128:        cmpwi   CR0,    r1,     0
                    129:        beq-    CR0,    EXT(gdbhandler)
                    130:        
                    131: #if DEBUG
                    132:                /* Make sure we're not on the interrupt stack */
                    133:        addis   r1,     0,      ha16(EXT(istackptr))
                    134:        addi    r1,     r1,     lo16(EXT(istackptr))
                    135:        lwz     r1,     0(r1)
                    136:        cmpwi   CR0,    r1,     0
                    137: 
                    138:        /* If we are on the interrupt stack, treat as an interrupt,
                    139:         * the interrupt handler will panic with useful info.
                    140:         */
                    141: 
                    142:        beq-    CR0,    EXT(ihandler)
                    143:        
                    144: #endif /* DEBUG */
                    145: 
                    146:        lwz     r3,     PP_CPU_DATA(r2)
                    147: 
                    148:        lwz     r3,     CPU_ACTIVE_THREAD(r3)
                    149:        lwz     r3,     THREAD_PCB(r3)
                    150:        lwz     r1,     PCB_KSP(r3)
                    151: 
                    152:        cmpwi   CR1,    r1,     0       /* zero implies already on kstack */
                    153:        bne     CR1,    .L_kstackfree   /* This test is also used below */
                    154: 
                    155:        mfsprg  r1,     1               /* recover previous stack ptr */
                    156: 
                    157:        /* On kernel stack, allocate stack frame and check for overflow */
                    158: 
                    159:        /* Move stack pointer below redzone + reserve a saved_state */
                    160: 
                    161:        subi    r1,     r1,     FM_REDZONE+SS_SIZE 
                    162: 
                    163:        b       .L_kstack_save_state
                    164: 
                    165: .L_kstackfree:
                    166:        mr      r1,     r3              /* r1 points to save area of pcb */
                    167: 
                    168: .L_kstack_save_state:  
                    169: 
                    170:        /* Once we reach here, r1 contains the place
                    171:          * where we can store a ppc_saved_state structure. This may
                    172:         * or may not be part of a pcb, we test that again once
                    173:         * we've saved state. (CR1 still holds test done on ksp)
                    174:         */
                    175: 
                    176:        stw     r0,     SS_R0(r1)
                    177: 
                    178:        mfsprg  r0,     1
                    179:        stw     r0,     SS_R1(r1)
                    180: 
                    181:        mfsprg  r0,     2
                    182:        stw     r0,     SS_R2(r1)
                    183: 
                    184:        mfsprg  r0,     3
                    185:        stw     r0,     SS_R3(r1)
                    186: 
                    187:        stw     r4,     SS_R4(r1)
                    188:        stw     r5,     SS_R5(r1)
                    189:        stw     r6,     SS_R6(r1)
                    190:        stw     r7,     SS_R7(r1)
                    191:        stw     r8,     SS_R8(r1)
                    192:        stw     r9,     SS_R9(r1)
                    193:        stw     r10,    SS_R10(r1)
                    194:        stw     r11,    SS_R11(r1)
                    195:        stw     r12,    SS_R12(r1)
                    196:        stw     r13,    SS_R13(r1)
                    197:        stw     r14,    SS_R14(r1)
                    198:        stw     r15,    SS_R15(r1)
                    199:        stw     r16,    SS_R16(r1)
                    200:        stw     r17,    SS_R17(r1)
                    201:        stw     r18,    SS_R18(r1)
                    202:        stw     r19,    SS_R19(r1)
                    203:        stw     r20,    SS_R20(r1)
                    204:        stw     r21,    SS_R21(r1)
                    205:        stw     r22,    SS_R22(r1)
                    206:        stw     r23,    SS_R23(r1)
                    207:        stw     r24,    SS_R24(r1)
                    208:        stw     r25,    SS_R25(r1)
                    209:        stw     r26,    SS_R26(r1)
                    210:        stw     r27,    SS_R27(r1)
                    211:        stw     r28,    SS_R28(r1)
                    212:        stw     r29,    SS_R29(r1)
                    213:        stw     r30,    SS_R30(r1)
                    214:        stw     r31,    SS_R31(r1)
                    215: 
                    216:        /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
                    217:         * some of this comes back out from the per-processor structure
                    218:         * pointed to by r2
                    219:         */
                    220: 
                    221:        lwz     r0,     PP_SAVE_CR(r2)
                    222:        stw     r0,     SS_CR(r1)
                    223:        
                    224:        lwz     r0,     PP_SAVE_SRR0(r2)
                    225:        stw     r0,     SS_SRR0(r1)
                    226: 
                    227:        /* WARNING - r0 from the following instruction is used
                    228:         * further below
                    229:         */
                    230: 
                    231:        lwz     r0,     PP_SAVE_SRR1(r2)
                    232:        stw     r0,     SS_SRR1(r1)
                    233: 
                    234: 
                    235:        /* WARNING! These two instructions assume that we didn't take
                    236:         * any type of exception whilst saving state, it's a bit late
                    237:         * for that!
                    238:         * TODO NMGS move these up the code somehow, put in PROC_REG?
                    239:         */
                    240: 
                    241:        mfdsisr ARG2                    /* r4   */
                    242:        mfdar   ARG3                    /* r5   */
                    243: 
                    244:        /* work out if we will reenable interrupts or not depending
                    245:         * upon the state which we came from, store as tmp in ARG5
                    246:         */
                    247:        li      ARG5,   MSR_SUPERVISOR_INT_OFF
                    248:        rlwimi  ARG5,   r0,     0,      MSR_EE_BIT,     MSR_EE_BIT
                    249: 
                    250:        mfxer   r0
                    251:        stw     r0,     SS_XER(r1)
                    252: 
                    253:        mflr    r0
                    254:        stw     r0,     SS_LR(r1)
                    255: 
                    256:        mfctr   r0
                    257:        stw     r0,     SS_CTR(r1)
                    258: 
                    259:        /* Don't save MQ, we don't bother for now */
                    260:        
                    261:        /* Free the reservation whilst saving SR_COPYIN */
                    262: 
                    263:        mfsr    r0,     SR_COPYIN_NAME
                    264:        li      ARG7,   SS_SR_COPYIN
                    265:        sync                            /* bug fix for 3.2 processors */
                    266:        stwcx.  r0,     ARG7,   r1
                    267:        stw     r0,     SS_SR_COPYIN(r1)
                    268:        
                    269:        /* r3 still holds our pcb, CR1 still holds test to see if we're
                    270:         * in the pcb or have saved state on the kernel stack */
                    271: 
                    272:        mr      ARG1,   r1              /* Preserve saved_state ptr in ARG1 */
                    273: 
                    274:        beq     CR1,    .L_state_on_kstack/* using above test for pcb/stack */
                    275: 
                    276:        /* We saved state in the pcb, recover the stack pointer */
                    277:        lwz     r1,     PCB_KSP(r3)
                    278: 
                    279:        /* Mark that we're occupying the kernel stack for sure now */   
                    280:        li      r0,     0
                    281:        stw     r0,     PCB_KSP(r3)
                    282: 
                    283: .L_state_on_kstack:    
                    284:                
                    285:        /* Phew!
                    286:         *
                    287:         * To summarise, when we reach here, we have filled out
                    288:         * a ppc_saved_state structure either in the pcb or on
                    289:         * the kernel stack, and the stack is marked as busy.
                    290:         * r4 holds a pointer to this state, r1 is now the stack
                    291:         * pointer no matter where the state was savd.
                    292:         * We now generate a small stack frame with backpointers
                    293:         * to follow the calling
                    294:         * conventions. We set up the backpointers to the trapped
                    295:         * routine allowing us to backtrace.
                    296:         */
                    297: 
                    298: /* WARNING!! Using mfsprg below assumes interrupts are still off here */
                    299:        
                    300:        subi    r1,     r1,     FM_SIZE
                    301:        mfsprg  r0,     1
                    302:        stw     r0,     FM_BACKPTR(r1)  /* point back to previous stackptr */
                    303: 
                    304: #if    DEBUG
                    305:        /* If debugging, we need two frames, the first being a dummy
                    306:         * which links back to the trapped routine. The second is
                    307:         * that which the C routine below will need
                    308:         */
                    309:        lwz     r0,     SS_SRR0(r1)
                    310:        stw     r0,     FM_LR_SAVE(r1)  /* save old instr ptr as LR value */
                    311: 
                    312:        //stwu  r1,     -FM_SIZE(r1)    /* and make new frame */
                    313:        stw     r1,     -FM_SIZE(r1)    /* and make new frame */
                    314:        subi    r1,     r1,     FM_SIZE
                    315: #endif /* DEBUG */
                    316: 
                    317: 
                    318:        /* call trap handler proper, with
                    319:         *   ARG0 = type                (not yet, holds pcb ptr)
                    320:         *   ARG1 = saved_state ptr     (already there)
                    321:         *   ARG2 = dsisr               (already there)
                    322:         *   ARG3 = dar                 (already there)
                    323:         */
                    324: 
                    325:        /* This assumes that no (non-tlb) exception/interrupt has occured
                    326:         * since PP_SAVE_* get clobbered by an exception...
                    327:         */
                    328:        lwz     ARG0,   PP_SAVE_EXCEPTION_TYPE(r2)
                    329: 
                    330:        /* Reenable interrupts if they were enabled before we came here */
                    331:        mtmsr   ARG5
                    332:        isync
                    333: 
                    334:        /* syscall exception might warp here if there's nothing left
                    335:         * to do except generate a trap
                    336:         */
                    337: .L_call_trap:  
                    338:        bl      EXT(trap)
                    339: 
                    340:        /*
                    341:         * Ok, return from C function
                    342:         *
                    343:         * This is also the point where new threads come when they are created.
                    344:         * The new thread is setup to look like a thread that took an 
                    345:         * interrupt and went immediatly into trap.
                    346:         *
                    347:         * r3 must hold the pointer to the saved state, either on the
                    348:         * stack or in the pcb.
                    349:         */
                    350: 
                    351: thread_return:
                    352:        /* Reload the saved state */
                    353: 
                    354:        /* r0-3 will be restored last, use as temp for now */
                    355: 
                    356:        lwz     r4,     SS_R4(r3)
                    357:        lwz     r5,     SS_R5(r3)
                    358:        lwz     r6,     SS_R6(r3)
                    359:        lwz     r7,     SS_R7(r3)
                    360:        lwz     r8,     SS_R8(r3)
                    361:        lwz     r9,     SS_R9(r3)
                    362:        lwz     r10,    SS_R10(r3)
                    363:        lwz     r11,    SS_R11(r3)
                    364:        lwz     r12,    SS_R12(r3)
                    365:        lwz     r13,    SS_R13(r3)
                    366:        lwz     r14,    SS_R14(r3)
                    367:        lwz     r15,    SS_R15(r3)
                    368:        lwz     r16,    SS_R16(r3)
                    369:        lwz     r17,    SS_R17(r3)
                    370:        lwz     r18,    SS_R18(r3)
                    371:        lwz     r19,    SS_R19(r3)
                    372:        lwz     r20,    SS_R20(r3)
                    373:        lwz     r21,    SS_R21(r3)
                    374:        lwz     r22,    SS_R22(r3)
                    375:        lwz     r23,    SS_R23(r3)
                    376:        lwz     r24,    SS_R24(r3)
                    377:        lwz     r25,    SS_R25(r3)
                    378:        lwz     r26,    SS_R26(r3)
                    379:        lwz     r27,    SS_R27(r3)
                    380:        lwz     r28,    SS_R28(r3)
                    381:        lwz     r29,    SS_R29(r3)
                    382:        lwz     r30,    SS_R30(r3)
                    383:        lwz     r31,    SS_R31(r3)
                    384: 
                    385:        lwz     r0,     SS_XER(r3)
                    386:        mtxer   r0
                    387:        lwz     r0,     SS_LR(r3)
                    388:        mtlr    r0
                    389:        lwz     r0,     SS_CTR(r3)
                    390:        mtctr   r0
                    391:        lwz     r0,     SS_SR_COPYIN(r3)
                    392:        isync
                    393:        mtsr    SR_COPYIN_NAME, r0
                    394:        isync
                    395:        
                    396: 
                    397:        /* TODO NMGS don't restore mq since we're not 601-specific enough */
                    398: 
                    399:        /* Disable interrupts */
                    400:        li      r0, MSR_SUPERVISOR_INT_OFF
                    401:        mtmsr   r0
                    402: 
                    403: 
                    404:        /* Is this the last saved state, found in the pcb? */
                    405:        /* TODO NMGS optimise this by spreading it through the code above? */
                    406: 
                    407:        /* After this we no longer to keep &per_proc_info in r2 */
                    408:        
                    409:        lwz     r1,     PP_CPU_DATA(r2)
                    410:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                    411:        lwz     r0,     THREAD_PCB(r1)
                    412: 
                    413:        cmp     CR0,0,  r0,     r3
                    414:        bne     CR0,    .L_notthelast_trap
                    415: 
                    416:        /* our saved state is actually part of the thread's pcb so
                    417:         * we need to mark that we're leaving the kernel stack and
                    418:         * jump into user space
                    419:         */
                    420: 
                    421:        /* Mark the kernel stack as free */
                    422: 
                    423:        /* There may be a critical region here for traps(interrupts?)
                    424:         * once the stack is marked as free, PCB_SR0 may be trampled on
                    425:         * so interrupts should be switched off
                    426:         */
                    427:        /* Release any processor reservation we may have had too */
                    428: 
                    429:        lwz     r2,     THREAD_KERNEL_STACK(r1)
                    430:        addi    r0,     r2,     KSTK_SIZE-KS_SIZE-FM_SIZE
                    431:        li      r2,     PCB_KSP
                    432: /* we have to use an indirect store to clear reservation */
                    433:        sync                            /* bug fix for 3.2 processors */
                    434:        stwcx.  r0,     r2,     r3              /* clear reservation */
                    435:        stw     r0,     PCB_KSP(r3)             /* mark stack as free */
                    436:        
                    437:        /* We may be returning to something in the kernel space.
                    438:         * If we are, we can skip the trampoline and just rfi,
                    439:         * since we don't want to restore the user's space regs
                    440:         */
                    441:        lwz     r0,     SS_SRR1(r3)
                    442:        andi.   r0,     r0,     MASK(MSR_PR)
                    443:        beq-    .L_trap_ret_to_kspace
                    444:        
                    445:        /* If jumping into user space, we should restore the user's
                    446:         * segment register 0. We jump via a trampoline in physical mode
                    447:         */
                    448:                
                    449:        lwz     r0,     SS_CR(r3)
                    450:        mtcrf   0xFF,r0
                    451: 
                    452:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                    453:         * as arguments */
                    454:        lwz     r0,     SS_R1(r3)
                    455:        mtsprg  1,      r0
                    456:        lwz     r0,     SS_R2(r3)
                    457:        mtsprg  2,      r0
                    458:        lwz     r0,     SS_R3(r3)
                    459:        mtsprg  3,      r0
                    460: 
                    461:        lwz     r0,     SS_R0(r3)
                    462: 
                    463:        /* Prepare to rfi to the exception exit routine, which is
                    464:         * in physical address space */
                    465:        addis   r1,     0,      ha16(EXT(exception_exit))
                    466:        addi    r1,     r1,     lo16(EXT(exception_exit))
                    467:        lwz     r1,     0(r1)
                    468:        mtsrr0  r1
                    469:        li      r1,     MSR_VM_OFF
                    470:        mtsrr1  r1
                    471: 
                    472:        
                    473:        lwz     r1,     PCB_SR0(r3)     /* For trampoline */
                    474:        lwz     r2,     SS_SRR0(r3)     /* For trampoline */
                    475:        
                    476:        lwz     r3,     SS_SRR1(r3)     /* load the last register... */
                    477: 
                    478:        rfi
                    479: 
                    480: .L_trap_ret_to_kspace: 
                    481: .L_notthelast_trap:
                    482:        /* If we're not the last trap on the kernel stack life is easier,
                    483:         * we don't need to switch back into the user's segment. we can
                    484:         * simply restore the last registers and rfi
                    485:         */
                    486: 
                    487:        lwz     r0,     SS_CR(r3)
                    488:        mtcrf   0xFF,r0
                    489:        lwz     r0,     SS_SRR0(r3)
                    490:        mtsrr0  r0
                    491:        lwz     r0,     SS_SRR1(r3)
                    492:        mtsrr1  r0
                    493: 
                    494:        lwz     r0,     SS_R0(r3)
                    495:        lwz     r1,     SS_R1(r3)
                    496:        /* critical region for traps(interrupt?) since r1 no longer points
                    497:         * to bottom of stack. Could be fixed. But interrupts are off (?).
                    498:         */
                    499:        lwz     r2,     SS_R2(r3)       /* r2 is a constant (&per_proc_info) */
                    500:        /* r3 restored last */
                    501:        lwz     r4,     SS_R4(r3)
                    502:        lwz     r5,     SS_R5(r3)
                    503:        /* and lastly... */
                    504:        lwz     r3,     SS_R3(r3)
                    505: 
                    506:        rfi                             /* return to calling context */
                    507: 
                    508: 
                    509: 
                    510: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
                    511:  * void                        CallPseudoKernel        ( void )
                    512:  *
                    513:  * This op provides a means of invoking the BlueBox PseudoKernel from a
                    514:  * system (68k) or native (PPC) context while changing BlueBox interruption
                    515:  * state atomically. As an added bonus, this op clobbers only r0 while leaving
                    516:  * the rest of PPC user state registers intact.
                    517:  *
                    518:  * This op is invoked as follows:
                    519:  *     li r0, kCallPseudoKernelNumber  // load this op's firmware call number
                    520:  *     sc                              // invoke CallPseudoKernel
                    521:  *     dc.l    CallPseudoKernelDescriptorPtr   // static pointer to CallPseudoKernelDescriptor
                    522:  *
                    523:  * NOTE: The CallPseudoKernelDescriptor and the word pointed to by
                    524:  * intControlAddr must be locked, else this op will crash the kernel.
                    525:  *
                    526:  * Entry:      VM switched ON
                    527:  *             Interrupts  OFF
                    528:  *              original r1-3 saved in sprg1-3
                    529:  *              original srr0 and srr1 saved in per_proc_info structure
                    530:  *              original cr            saved in per_proc_info structure
                    531:  *              exception type         saved in per_proc_info structure
                    532:  *              r1 = scratch
                    533:  *              r2 = virt addr of per_proc_info
                    534:  *             r3 = exception type (one of EXC_...)
                    535:  *
                    536: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
                    537:        .align  5
                    538:                                        
                    539: __fcCallPseudoKernel:
                    540: 
                    541:        // Needed to save some state so this code matches NuKernel Support
                    542:        lwz     r1,     PP_CPU_DATA(r2)
                    543:        lwz     r3,     CPU_ACTIVE_THREAD(r1)
                    544:        lwz     r1,     THREAD_PCB(r3)
                    545: 
                    546:        stw     r0,     SS_R0(r1)
                    547: 
                    548:        lwz     r0,     PP_SAVE_SRR0(r2)
                    549:        stw     r0,     SS_SRR0(r1)
                    550: 
                    551:        lwz     r0,     PP_SAVE_SRR1(r2)
                    552:        stw     r0,     SS_SRR1(r1)
                    553: 
                    554:        lwz     r0,     PP_SAVE_CR(r2)
                    555:        stw     r0,     SS_CR(r1)
                    556: 
                    557:        mfsprg  r0,     1
                    558:        stw     r0,     SS_R1(r1)
                    559: 
                    560:        mfsprg  r0,     2
                    561:        stw     r0,     SS_R2(r1)
                    562: 
                    563:        mfsprg  r0,     3
                    564:        stw     r0,     SS_R3(r1)
                    565: 
                    566:        stw     r4,     SS_R4(r1)
                    567:        stw     r5,     SS_R5(r1)
                    568:        stw     r6,     SS_R6(r1)
                    569:        stw     r7,     SS_R7(r1)
                    570:        stw     r8,     SS_R8(r1)
                    571:        stw     r9,     SS_R9(r1)
                    572:        stw     r10,    SS_R10(r1)
                    573:        stw     r11,    SS_R11(r1)
                    574:        stw     r12,    SS_R12(r1)
                    575: 
                    576:        // word following the sc is the descriptor's address
                    577:        lwz     r3,     SS_SRR0(r1)
                    578: 
                    579:        lwz     r10,    SS_CR(r1)       // setup r10 with CR
                    580: 
                    581:        lwz     r3,     0(r3)           // get descriptor's address
                    582: 
                    583:        lwz     r11,    CPKD_INTCONTROLADDR(r3)
                    584:        lwz     r4,     CPKD_PC(r3)
                    585:        lwz     r6,     CPKD_NEWSTATE(r3)
                    586:        lwz     r7,     CPKD_INTSTATEMASK(r3)
                    587:        lwz     r8,     0(r11)          // get current interruption control word
                    588:        lwz     r5,     CPKD_GPR0(r3)
                    589:        lwz     r12,    CPKD_SYSCONTEXTSTATE(r3)
                    590:        andc    r9, r8, r7              // remove current state
                    591:        and     r8, r8, r7              // extract current state
                    592:        cmplw   r8, r12                 // test for entry from system context
                    593:        or      r9, r9, r6              // insert new state
                    594:        bne     CallFromAlternateContext                
                    595: 
                    596: CallFromSystemContext:
                    597:        lwz     r6,     CPKD_INTCR2SHIFT(r3)
                    598:        lwz     r7,     CPKD_INTCR2MASK(r3)
                    599:        srw     r10, r10, r6            // position live CR2 from cr register as required
                    600:        andc    r9, r9, r7              // remove old backup CR2
                    601:        and     r10, r10, r7            // mask live CR2
                    602:        or      r9, r9, r10             // insert CR2 into backup CR2
                    603:        b       CallContinue
                    604: 
                    605: CallFromAlternateContext:
                    606: CallContinue:
                    607:        stw     r9,     0(r11)  // update interruption control word 
                    608: 
                    609:        // introduce new pc and gr0 contents
                    610:        lwz     r6,     SS_SRR1(r1)
                    611:        stw     r4,     SS_SRR0(r1)
                    612:        stw     r5,     SS_R0(r1)
                    613: 
                    614:        // insert updated fe0, fe1, se, and be bits into user msr
                    615:        rlwimi  r6, r6, 0, MSR_FE1_BIT, MSR_FE0_BIT
                    616:        /* Turn off FPU */
                    617:        rlwinm  r6,     r6,     0,      MSR_FP_BIT+1,   MSR_FP_BIT-1
                    618: 
                    619:        // zero single step and branch step control in user msr
                    620:        stw     r6,     SS_SRR1(r1) // update user msr
                    621: 
                    622:        /*
                    623:        ** Restore state for exit
                    624:        */
                    625:        lwz     r0,     SS_CR(r1)
                    626:        mtcrf   0xFF,   r0
                    627: 
                    628:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                    629:         * as arguments */
                    630:        lwz     r0,     SS_R1(r1)
                    631:        mtsprg  1,      r0
                    632: 
                    633:        lwz     r0,     SS_R2(r1)
                    634:        mtsprg  2,      r0
                    635: 
                    636:        lwz     r0,     SS_R3(r1)
                    637:        mtsprg  3,      r0
                    638: 
                    639:        lwz     r0,     SS_R0(r1)
                    640: 
                    641:        lwz     r4,     SS_R4(r1)
                    642:        lwz     r5,     SS_R5(r1)
                    643:        lwz     r6,     SS_R6(r1)
                    644:        lwz     r7,     SS_R7(r1)
                    645:        lwz     r8,     SS_R8(r1)
                    646:        lwz     r9,     SS_R9(r1)
                    647:        lwz     r10,    SS_R10(r1)
                    648:        lwz     r11,    SS_R11(r1)
                    649:        lwz     r12,    SS_R12(r1)
                    650: 
                    651:        /* Prepare to rfi to the exception exit routine, which is
                    652:         * in physical address space */
                    653:        addis   r3,     0,      ha16(EXT(exception_exit))
                    654:        addi    r3,     r3,     lo16(EXT(exception_exit))
                    655:        lwz     r3,     0(r3)
                    656:        mtsrr0  r3
                    657:        li      r3,     MSR_VM_OFF
                    658:        mtsrr1  r3
                    659: 
                    660:        lwz     r2,     SS_SRR0(r1)     /* For trampoline */
                    661:        lwz     r3,     SS_SRR1(r1)     /* For trampoline */
                    662:        lwz     r1,     PCB_SR0(r1)     /* load the last register... */
                    663: 
                    664:        rfi
                    665: 
                    666: 
                    667: 
                    668: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
                    669:  * void ExitPseudoKernel ( ExitPseudoKernelDescriptorPtr exitDescriptor )
                    670:  *
                    671:  * This op provides a means of exiting from the BlueBox PseudoKernel to a
                    672:  * user context while changing the BlueBox interruption state atomically.
                    673:  * It also allows all of the user state PPC registers to be loaded.
                    674:  *
                    675:  * This op is invoked as follows:
                    676:  *     lwz r3, ExitPseudoKernelDescriptorPtr
                    677:  *     li r0, kCallPseudoKernelNumber  // load this op's firmware call number
                    678:  *     sc                              // invoke CallPseudoKernel
                    679:  *
                    680:  * Entry:      VM switched ON
                    681:  *             Interrupts  OFF
                    682:  *              original r1-3 saved in sprg1-3
                    683:  *              original srr0 and srr1 saved in per_proc_info structure
                    684:  *              original cr            saved in per_proc_info structure
                    685:  *              exception type         saved in per_proc_info structure
                    686:  *              r1 = scratch
                    687:  *              r2 = virt addr of per_proc_info
                    688:  *             r3 = exception type (one of EXC_...)
                    689:  *
                    690: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
                    691:        .align  5
                    692: __fcExitPseudoKernel:
                    693:        // Needed to save some state so this code matches NuKernel Support
                    694:        lwz     r1,     PP_CPU_DATA(r2)
                    695:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                    696:        lwz     r1,     THREAD_PCB(r1)
                    697: 
                    698:        stw     r0,     SS_R0(r1)
                    699: 
                    700:        lwz     r0,     PP_SAVE_SRR0(r2)
                    701:        stw     r0,     SS_SRR0(r1)
                    702: 
                    703:        lwz     r0,     PP_SAVE_SRR1(r2)
                    704:        stw     r0,     SS_SRR1(r1)
                    705: 
                    706:        lwz     r0,     PP_SAVE_CR(r2)
                    707:        stw     r0,     SS_CR(r1)
                    708: 
                    709:        mfsprg  r0,     1
                    710:        stw     r0,     SS_R1(r1)
                    711: 
                    712:        mfsprg  r0,     2
                    713:        stw     r0,     SS_R2(r1)
                    714: 
                    715:        mfsprg  r0,     3
                    716:        stw     r0,     SS_R3(r1)
                    717: 
                    718:        stw     r4,     SS_R4(r1)
                    719:        stw     r5,     SS_R5(r1)
                    720:        stw     r6,     SS_R6(r1)
                    721:        stw     r7,     SS_R7(r1)
                    722:        stw     r8,     SS_R8(r1)
                    723:        stw     r9,     SS_R9(r1)
                    724:        stw     r10,    SS_R10(r1)
                    725:        stw     r11,    SS_R11(r1)
                    726:        stw     r12,    SS_R12(r1)
                    727: 
                    728:        /* start of actual routine */
                    729: 
                    730:        lwz     r9, SS_SRR1(r1)
                    731: 
                    732:        lwz     r3, SS_R3(r1)           // restore r3, it is exitdescptr
                    733: 
                    734:        lwz     r8, EPKD_CR(r3)
                    735: 
                    736:        lwz     r11, EPKD_INTCONTROLADDR(r3)
                    737:        lwz     r4, EPKD_PC(r3)
                    738:        lwz     r7, EPKD_NEWSTATE(r3)
                    739:        lwz     r10, EPKD_INTSTATEMASK(r3)
                    740:        lwz     r5, 0(r11)      // get current interruption control word
                    741:        lwz     r0, EPKD_SYSCONTEXTSTATE(r3)
                    742:        andc    r12, r5, r10            // remove current state
                    743:        cmplw   r7, r0                  // test for exit to system context
                    744:        or      r12, r12, r7            // insert new state
                    745:        lwz     r0, EPKD_MSRUPDATE(r3)
                    746:        beq     ExitToSystemContext
                    747: 
                    748: ExitToAlternateContext:
                    749:        lwz     r5, EPKD_INTPENDINGMASK(r3)
                    750:        lwz     r6, EPKD_INTPENDINGPC(r3)
                    751:        and.    r7, r12, r5             // test for pending 'rupt in backup cr2
                    752:        beq     ExitUpdateRuptControlWord       //   and enter alternate context if none pending
                    753:        mr      r4, r6                  // otherwise, introduce entry abort pc
                    754:        b       ExitNoUpdateRuptControlWord     //   and prepare to reenter pseudokernel
                    755: 
                    756: ExitToSystemContext:
                    757:        lwz     r5, EPKD_INTCR2SHIFT(r3)
                    758:        lwz     r6, EPKD_INTCR2MASK(r3)         
                    759:        slw     r7, r12, r5             // position backup cr2
                    760:        and     r7, r7, r6              //   and mask it
                    761:        or      r8, r8, r7              //   then or it into the live cr2
                    762:                                                                                        // ...fall through into system context
                    763: 
                    764: ExitUpdateRuptControlWord:
                    765:        // insert updated fe0, fe1, se, and be bits into user msr
                    766:        rlwimi  r9, r0, 0, MSR_FE0_BIT, MSR_FE1_BIT
                    767:        /* Turn off FPU */
                    768:        rlwinm  r9,     r9,     0,      MSR_FP_BIT+1,   MSR_FP_BIT-1
                    769:        stw     r12, 0(r11)             // update interruption control word 
                    770: ExitNoUpdateRuptControlWord:
                    771:        lwz     r5, EPKD_GPR0(r3)
                    772:        lwz     r6, EPKD_SP(r3)
                    773:        lwz     r7, EPKD_GPR3(r3)
                    774:                                                                                        // load caller's new register contents
                    775: 
                    776:        stw     r4, SS_SRR0(r1)
                    777:        stw     r5, SS_R0(r1)
                    778:        stw     r6, SS_R1(r1)
                    779:        stw     r7, SS_R3(r1)
                    780:        stw     r8, SS_CR(r1)
                    781:        stw     r9, SS_SRR1(r1)
                    782: 
                    783: 
                    784:        lwz     r0,     SS_CR(r1)
                    785:        mtcrf   0xFF,r0                 /* update cr, it is live */
                    786: 
                    787:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                    788:         * as arguments */
                    789:        lwz     r0,     SS_R1(r1)
                    790:        mtsprg  1,      r0
                    791:        lwz     r0,     SS_R2(r1)
                    792:        mtsprg  2,      r0
                    793:        lwz     r0,     SS_R3(r1)
                    794:        mtsprg  3,      r0
                    795: 
                    796:        lwz     r0,     SS_R0(r1)
                    797: 
                    798:        lwz     r4,     SS_R4(r1)
                    799:        lwz     r5,     SS_R5(r1)
                    800:        lwz     r6,     SS_R6(r1)
                    801:        lwz     r7,     SS_R7(r1)
                    802:        lwz     r8,     SS_R8(r1)
                    803:        lwz     r9,     SS_R9(r1)
                    804:        lwz     r10,    SS_R10(r1)
                    805:        lwz     r11,    SS_R11(r1)
                    806:        lwz     r12,    SS_R12(r1)
                    807: 
                    808:        /* Prepare to rfi to the exception exit routine, which is
                    809:         * in physical address space */
                    810:        addis   r3,     0,      ha16(EXT(exception_exit))
                    811:        addi    r3,     r3,     lo16(EXT(exception_exit))
                    812:        lwz     r3,     0(r3)
                    813:        mtsrr0  r3
                    814:        li      r3,     MSR_VM_OFF
                    815:        mtsrr1  r3
                    816: 
                    817:        lwz     r2,     SS_SRR0(r1)     /* For trampoline */
                    818:        lwz     r3,     SS_SRR1(r1)     /* load the last register... */
                    819:        lwz     r1,     PCB_SR0(r1)     /* For trampoline... */
                    820: 
                    821:        rfi
                    822: 
                    823: 
                    824: /*
                    825:  * void cthread_set_self(cproc_t p)
                    826:  *
                    827:  * set's thread state "user_value"
                    828:  *
                    829:  * This op is invoked as follows:
                    830:  *     li r0, CthreadSetSelfNumber     // load the fast-trap number
                    831:  *     sc                              // invoke fast-trap
                    832:  *     blr
                    833:  *
                    834:  * Entry:      VM switched ON
                    835:  *             Interrupts  OFF
                    836:  *              original r1-3 saved in sprg1-3
                    837:  *              original srr0 and srr1 saved in per_proc_info structure
                    838:  *              original cr            saved in per_proc_info structure
                    839:  *              exception type         saved in per_proc_info structure
                    840:  *              r1 = scratch
                    841:  *              r2 = virt addr of per_proc_info
                    842:  *             r3 = exception type (one of EXC_...)
                    843:  *
                    844:  */
                    845:        .text
                    846:        .align  5
                    847: __fcCthreadSetSelfNumber:
                    848:        lwz     r1,     PP_CPU_DATA(r2)
                    849:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                    850:        lwz     r1,     THREAD_PCB(r1)
                    851: 
                    852:        mfsprg  r3,     3
                    853:        stw     r3,     CTHREAD_SELF(r1)
                    854: 
                    855:        /* Prepare to rfi to the exception exit routine, which is
                    856:         * in physical address space */
                    857:        addis   r3,     0,      ha16(EXT(exception_exit))
                    858:        addi    r3,     r3,     lo16(EXT(exception_exit))
                    859:        lwz     r3,     0(r3)
                    860:        mtsrr0  r3
                    861:        li      r3,     MSR_VM_OFF
                    862:        mtsrr1  r3
                    863: 
                    864:        lwz     r3,     PP_SAVE_SRR1(r2)        /* load the last register... */
                    865:        lwz     r2,     PP_SAVE_SRR0(r2)        /* For trampoline */
                    866:        lwz     r1,     PCB_SR0(r1)             /* For trampoline... */
                    867: 
                    868:        rfi
                    869: 
                    870: 
                    871: /*
                    872:  * ur_cthread_t ur_cthread_self(void)
                    873:  *
                    874:  * return thread state "user_value"
                    875:  *
                    876:  * This op is invoked as follows:
                    877:  *     li r0, UrCthreadSelfNumber      // load the fast-trap number
                    878:  *     sc                              // invoke fast-trap
                    879:  *     blr
                    880:  *
                    881:  * Entry:      VM switched ON
                    882:  *             Interrupts  OFF
                    883:  *              original r1-3 saved in sprg1-3
                    884:  *              original srr0 and srr1 saved in per_proc_info structure
                    885:  *              original cr            saved in per_proc_info structure
                    886:  *              exception type         saved in per_proc_info structure
                    887:  *              r1 = scratch
                    888:  *              r2 = virt addr of per_proc_info
                    889:  *             r3 = exception type (one of EXC_...)
                    890:  *
                    891:  */
                    892:        .text
                    893:        .align  5
                    894: __fcUrCthreadSelfNumber:
                    895:        lwz     r1,     PP_CPU_DATA(r2)
                    896:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                    897:        lwz     r1,     THREAD_PCB(r1)
                    898: 
                    899:        lwz     r3,     CTHREAD_SELF(r1)
                    900:        mtsprg  3,      r3
                    901: 
                    902: 
                    903:        /* Prepare to rfi to the exception exit routine, which is
                    904:         * in physical address space */
                    905:        addis   r3,     0,      ha16(EXT(exception_exit))
                    906:        addi    r3,     r3,     lo16(EXT(exception_exit))
                    907:        lwz     r3,     0(r3)
                    908:        mtsrr0  r3
                    909:        li      r3,     MSR_VM_OFF
                    910:        mtsrr1  r3
                    911: 
                    912:        lwz     r3,     PP_SAVE_SRR1(r2)        /* load the last register... */
                    913:        lwz     r2,     PP_SAVE_SRR0(r2)        /* For trampoline */
                    914:        lwz     r1,     PCB_SR0(r1)             /* For trampoline... */
                    915: 
                    916:        rfi
                    917: 
                    918: 
                    919: 
                    920: /*
                    921:  * shandler(type)
                    922:  *
                    923:  * Entry:      VM switched ON
                    924:  *             Interrupts  OFF
                    925:  *              original r1-3 saved in sprg1-3
                    926:  *              original srr0 and srr1 saved in per_proc_info structure
                    927:  *              original cr            saved in per_proc_info structure
                    928:  *              exception type         saved in per_proc_info structure
                    929:  *              r1 = scratch
                    930:  *              r2 = virt addr of per_proc_info
                    931:  *             r3 = exception type (one of EXC_...)
                    932:  */
                    933: 
                    934: /*
                    935:  * If pcb.ksp == 0 then the kernel stack is already busy,
                    936:  *                 this is an error - jump to the debugger entry
                    937:  * 
                    938:  * otherwise       we save a (partial - TODO ) ppc_saved_state
                    939:  *                 in the pcb, and, depending upon the type of
                    940:  *                 syscall, look it up in the kernel table
                    941:  *                or pass it to the server.
                    942:  *
                    943:  * on return, we do the reverse, the state is popped from the pcb
                    944:  * and pcb.ksp is set to the top of stack.
                    945:  */
                    946: 
                    947: ENTRY(shandler, TAG_NO_FRAME_USED)     /* What tag should this have?! */
                    948: 
                    949: #if DEBUG
                    950:                /* Make sure we're not on the interrupt stack */
                    951:        addis   r1,     0,      ha16(EXT(istackptr))
                    952:        addi    r1,     r1,     lo16(EXT(istackptr))
                    953:        lwz     r1,     0(r1)
                    954:        cmpwi   CR0,    r1,     0
                    955: 
                    956:        /* If we are on the interrupt stack, treat as an interrupt,
                    957:         * the interrupt handler will panic with useful info.
                    958:         */
                    959:        beq     EXT(ihandler)
                    960:        
                    961: #endif /* DEBUG */
                    962: 
                    963:        /*
                    964:        **      check for special BlueBox calls
                    965:        */
                    966:        addis   r1,     0,      ha16(EXT(nsysent))
                    967:        addi    r1,     r1,     lo16(EXT(nsysent))
                    968:        lwz     r3,     0(r1)
                    969:        cmpw    CR0,    r0,     r3
                    970:        ble     L_shandler_syscall
                    971: 
                    972:        cmpwi   CR0,    r0,     0x7FFC
                    973:        beq-    __fcCallPseudoKernel
                    974: 
                    975:        cmpwi   CR0,    r0,     0x7FFE
                    976:        beq-    __fcExitPseudoKernel
                    977: 
                    978:        cmpwi   CR0,    r0,     0x7FF1  ;CthreadSetSelfNumber
                    979:        beq-    __fcCthreadSetSelfNumber
                    980: 
                    981:        cmpwi   CR0,    r0,     0x7FF2  ;UrCthreadSelfNumber
                    982:        beq-    __fcUrCthreadSelfNumber
                    983: 
                    984: L_shandler_syscall:
                    985:        lwz     r3,     PP_CPU_DATA(r2)
                    986:        lwz     r3,     CPU_ACTIVE_THREAD(r3)
                    987:        lwz     r1,     THREAD_PCB(r3)
                    988: #if DEBUG
                    989:                /* Check that we're not on kernel stack already */
                    990:        lwz     r1,     PCB_KSP(r1)
                    991: 
                    992:        /* If we are on a kernel stack, treat as a interrupt
                    993:         * the interrupt handler will panic with useful info.
                    994:         */
                    995:        cmpwi   CR1,    r1,     0
                    996:        /* tell the handler that we performed a syscall from this loc */
                    997:        li      r3,     EXC_SYSTEM_CALL
                    998:        beq     CR1,    EXT(ihandler)
                    999: 
                   1000: /* Reload active thread into r3 and PCB into r1 as before */
                   1001:        lwz     r3,     PP_CPU_DATA(r2)
                   1002:        lwz     r3,     CPU_ACTIVE_THREAD(r3)
                   1003:        lwz     r1,     THREAD_PCB(r3)
                   1004: #endif /* DEBUG */
                   1005: 
                   1006:        /* Once we reach here, r1 contains the pcb
                   1007:          * where we can store a partial ppc_saved_state structure,
                   1008:         * and r3 contains the active thread structure (used later)
                   1009:         */
                   1010: 
                   1011:        /* TODO NMGS - could only save callee saved regs for
                   1012:         * many(all?) Mach syscalls, not for unix since might be fork() etc
                   1013:         */
                   1014:        stw     r0,     SS_R0(r1)    /* Save trap number for debugging */
                   1015: 
                   1016:        lwz     r0,     PP_SAVE_CR(r2)
                   1017:        stw     r0,     SS_CR(r1)
                   1018:        
                   1019:        lwz     r0,     PP_SAVE_SRR0(r2)  /* Save SRR0 in debug call frame */
                   1020:        stw     r0,     SS_SRR0(r1)
                   1021: 
                   1022:        lwz     r0,     PP_SAVE_SRR1(r2)
                   1023:        oris    r0,     r0,     MSR_SYSCALL_MASK >> 16 /* Mark syscall state */
                   1024:        stw     r0,     SS_SRR1(r1)
                   1025:        
                   1026:        mfsprg  r0,     1
                   1027:        stw     r0,     SS_R1(r1)
                   1028: 
                   1029:        mfsprg  r0,     2
                   1030:        stw     r0,     SS_R2(r1)
                   1031: 
                   1032:        /* SAVE ARG REGISTERS? - YES, needed by server system calls */
                   1033:        mfsprg  r0,     3
                   1034:        stw     r0,     SS_R3(r1)
                   1035: 
                   1036:        stw     r4,     SS_R4(r1)
                   1037:        stw     r5,     SS_R5(r1)
                   1038:        stw     r6,     SS_R6(r1)
                   1039:        stw     r7,     SS_R7(r1)
                   1040:        stw     r8,     SS_R8(r1)
                   1041:        stw     r9,     SS_R9(r1)
                   1042:        stw     r10,    SS_R10(r1)
                   1043: 
                   1044:        stw     r11,    SS_R11(r1)
                   1045:        stw     r12,    SS_R12(r1)
                   1046:        stw     r13,    SS_R13(r1)
                   1047: 
                   1048:                /*
                   1049:                 * Callee saved state, need to save in case we
                   1050:                 * are executing a 'fork' unix system call or similar
                   1051:                 */
                   1052: 
                   1053:        stw     r14,    SS_R14(r1)
                   1054:        stw     r15,    SS_R15(r1)
                   1055:        stw     r16,    SS_R16(r1)
                   1056:        stw     r17,    SS_R17(r1)
                   1057:        stw     r18,    SS_R18(r1)
                   1058:        stw     r19,    SS_R19(r1)
                   1059:        stw     r20,    SS_R20(r1)
                   1060:        stw     r21,    SS_R21(r1)
                   1061:        stw     r22,    SS_R22(r1)
                   1062:        stw     r23,    SS_R23(r1)
                   1063:        stw     r24,    SS_R24(r1)
                   1064:        stw     r25,    SS_R25(r1)
                   1065: 
                   1066:        /* We use these registers in the code below, save them */
                   1067:        
                   1068:        stw     r26,    SS_R26(r1)
                   1069:        stw     r27,    SS_R27(r1)
                   1070:        stw     r28,    SS_R28(r1)
                   1071:        stw     r29,    SS_R29(r1)
                   1072:        stw     r30,    SS_R30(r1)
                   1073:        stw     r31,    SS_R31(r1)
                   1074:        
                   1075:        /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
                   1076:         * some of this comes back out from the per-processor structure
                   1077:         */
                   1078: 
                   1079:        mflr    r0
                   1080:        stw     r0,     SS_LR(r1)
                   1081: 
                   1082:        /* Volatile state, still restoring for sensible corefiles */
                   1083:        mfctr   r0
                   1084:        stw     r0,     SS_CTR(r1)
                   1085: 
                   1086:        mfxer   r0
                   1087:        stw     r0,     SS_XER(r1)
                   1088: 
                   1089:        /* Don't bother with MQ for now */
                   1090:        
                   1091:        /* Free the reservation whilst saving SR_COPYIN */
                   1092: 
                   1093:        mfsr    r0,     SR_COPYIN_NAME
                   1094:        li      r31,    SS_SR_COPYIN
                   1095:        sync                            /* bug fix for 3.2 processors */
                   1096:        stwcx.  r0,     r31,    r1
                   1097:        stw     r0,     SS_SR_COPYIN(r1)
                   1098:        
                   1099:        /* We saved state in the pcb, recover the stack pointer */
                   1100:        lwz     r31,    PCB_KSP(r1)     /* Get ksp */
                   1101: 
                   1102:        li      r0,     0
                   1103:        stw     r0,     PCB_KSP(r1)     /* Mark stack as busy with 0 val */
                   1104:        
                   1105:        /* Phew!
                   1106:         *
                   1107:         * To summarise, when we reach here, we have filled out
                   1108:         * a (partial) ppc_saved_state structure in the pcb, moved
                   1109:         * to kernel stack, and the stack is marked as busy.
                   1110:         * r1 holds a pointer to this state, and r3 holds a
                   1111:         * pointer to the active thread. r31 holds kernel stack ptr.
                   1112:         * We now move onto the kernel stack and generate a small
                   1113:         * stack frame to follow the calling
                   1114:         * conventions. We set up the backpointers to the calling
                   1115:         * routine allowing us to backtrace.
                   1116:         */
                   1117: 
                   1118:        mr      r30,    r1              /* Save pointer to state in r30 */
                   1119:        mr      r1,     r31             /* move to kernel stack */
                   1120:        mfsprg  r0,     1               /* get old stack pointer */
                   1121:        stw     r0,     FM_BACKPTR(r1)  /* store as backpointer */
                   1122:                
                   1123: #if    DEBUG
                   1124:        /* If debugging, we need two frames, the first being a dummy
                   1125:         * which links back to the trapped routine. The second is
                   1126:         * that which the C routine below will need
                   1127:         */
                   1128:        stw     r29,    FM_LR_SAVE(r1)  /* save old instr ptr as LR value */
                   1129:        //stwu  r1,     -FM_SIZE(r1)    /* point back to previous frame */
                   1130:        stw     r1,     -FM_SIZE(r1)    /* point back to previous frame */
                   1131:        subi    r1,     r1,     FM_SIZE
                   1132: #endif /* DEBUG */
                   1133: 
                   1134:        //stwu  r1,     -(FM_SIZE+ARG_SIZE)(r1)
                   1135:        //stwu  r1,     -(FM_SIZE+FM_REDZONE)(r1)
                   1136:        stw     r1,     -(FM_SIZE+FM_REDZONE)(r1)
                   1137:        subi    r1,     r1,     (FM_SIZE+FM_REDZONE)
                   1138: 
                   1139:        /* switch on interrupts now kernel stack is busy and valid */
                   1140:        mfmsr   r0
                   1141:        rlwimi  r0,     r0,     0,      MSR_EE_BIT,     MSR_EE_BIT
                   1142:        mtmsr   r0
                   1143: 
                   1144: 
                   1145:        /* we should still have r1=ksp, r3(ie ARG0)=current-thread,
                   1146:         * r30 = pointer to saved state (in pcb)
                   1147:         */
                   1148:        
                   1149:        /* Work out what kind of syscall we have to deal with. 
                   1150:         */
                   1151: 
                   1152: #if MACH_ASSERT
                   1153:        /* Call a function that can print out our syscall info */
                   1154:        mr      r4,     r30
                   1155:        bl      syscall_trace
                   1156:        /* restore those volatile argument registers */
                   1157:        lwz     r4,     SS_R4(r30)
                   1158:        lwz     r5,     SS_R5(r30)
                   1159:        lwz     r6,     SS_R6(r30)
                   1160:        lwz     r7,     SS_R7(r30)
                   1161:        lwz     r8,     SS_R8(r30)
                   1162:        lwz     r9,     SS_R9(r30)
                   1163:        lwz     r10,    SS_R10(r30)
                   1164:        
                   1165: #endif /* MACH_ASSERT */
                   1166:        mr      r3,     r30             /* put pcb in ARG0 */
                   1167:        lwz     r0,     SS_R0(r30)
                   1168:                
                   1169:        cmpwi   CR0,    r0,     0
                   1170:        blt-    .L_mach_kernel_syscall
                   1171: 
                   1172:        /* +ve syscall - go to server */
                   1173: 
                   1174:        b       EXT(unix_syscall)
                   1175: 
                   1176: .L_mach_kernel_syscall:
                   1177: 
                   1178:        b       EXT(mach_syscall)
                   1179: 
                   1180: 
                   1181: 
                   1182: .L_thread_syscall_return:
                   1183: 
                   1184:        li      r3, MSR_SUPERVISOR_INT_OFF
                   1185:        mtmsr   r3
                   1186:        
                   1187:        /* thread_exception_return returns to here, almost all
                   1188:         * registers intact. It expects a full context restore
                   1189:         * of what it hasn't restored itself (ie. what we use).
                   1190:         *
                   1191:         * In particular for us,
                   1192:         * we still have     r31 points to the current thread,
                   1193:         *                   r30 points to the current pcb
                   1194:         */
                   1195: 
                   1196:        mr      r3,     r30
                   1197:        mr      r1,     r31
                   1198:        /* r0-2 will be restored last, use as temp for now */
                   1199: 
                   1200: 
                   1201:        /* Callee saved state was saved and restored by the functions
                   1202:         * that we have called, assuming that we performed a standard
                   1203:         * function calling sequence. We only restore those that we
                   1204:         * are currently using.
                   1205:         *
                   1206:         * thread_exception_return arrives here, however, and it
                   1207:         * expects the full state to be restored
                   1208:         */
                   1209: #if DEBUG
                   1210:        /* the following callee-saved state should already be restored */
                   1211:        
                   1212:        lwz     r30,    SS_R14(r3)@ twne        r30,    r14
                   1213:        lwz     r30,    SS_R15(r3)@ twne        r30,    r15
                   1214:        lwz     r30,    SS_R16(r3)@ twne        r30,    r16
                   1215:        lwz     r30,    SS_R17(r3)@ twne        r30,    r17
                   1216:        lwz     r30,    SS_R18(r3)@ twne        r30,    r18
                   1217:        lwz     r30,    SS_R19(r3)@ twne        r30,    r19
                   1218:        lwz     r30,    SS_R20(r3)@ twne        r30,    r20
                   1219:        lwz     r30,    SS_R21(r3)@ twne        r30,    r21
                   1220:        lwz     r30,    SS_R22(r3)@ twne        r30,    r22
                   1221:        lwz     r30,    SS_R23(r3)@ twne        r30,    r23
                   1222:        lwz     r30,    SS_R24(r3)@ twne        r30,    r24
                   1223:        lwz     r30,    SS_R25(r3)@ twne        r30,    r25
                   1224:        lwz     r30,    SS_R26(r3)@ twne        r30,    r26
                   1225:        lwz     r30,    SS_R27(r3)@ twne        r30,    r27
                   1226:        lwz     r30,    SS_R28(r3)@ twne        r30,    r28
                   1227:        lwz     r30,    SS_R29(r3)@ twne        r30,    r29
                   1228: #endif /* DEBUG */
                   1229:                
                   1230:        lwz     r30,    SS_R30(r3)
                   1231:        lwz     r31,    SS_R31(r3)
                   1232: 
                   1233:        lwz     r0,     SS_LR(r3)
                   1234:        mtlr    r0
                   1235: 
                   1236:        /* Volatile state, still restoring for sensible corefiles */
                   1237:        lwz     r0,     SS_CTR(r3)
                   1238:        mtctr   r0
                   1239: 
                   1240:        lwz     r0,     SS_XER(r3)
                   1241:        mtxer   r0
                   1242: 
                   1243:        lwz     r0,     SS_SR_COPYIN(r3)
                   1244:        isync
                   1245:        mtsr    SR_COPYIN_NAME, r0
                   1246:        isync
                   1247: 
                   1248:        /* mark kernel stack as free before restoring r30, r31 */
                   1249: 
                   1250:        /* we no longer need r2 pointer to per_proc_info at this point */
                   1251:        
                   1252:        /* There may be a critical region here for traps(interrupts?)
                   1253:         * once the stack is marked as free, PCB_SR0 may be trampled on
                   1254:         * so interrupts must be off.
                   1255:         */
                   1256:        /* Clear reservation at the same time */
                   1257:        lwz     r2,     THREAD_KERNEL_STACK(r1)
                   1258:        addi    r0,     r2,     KSTK_SIZE-KS_SIZE-FM_SIZE
                   1259:        li      r2,     PCB_KSP
                   1260: /* we have to use an indirect store to clear reservation */
                   1261:        sync                            /* bug fix for 3.2 processors */
                   1262:        stwcx.  r0,     r2,     r3              /* clear reservation */
                   1263:        stw     r0,     PCB_KSP(r3)             /* mark stack as free */
                   1264: 
                   1265:        /* We may be returning to something in the kernel space.
                   1266:         * If we are, we can skip the trampoline and just rfi,
                   1267:         * since we don't want to restore the user's space regs
                   1268:         */
                   1269:        lwz     r0,     SS_SRR1(r3)
                   1270:        andi.   r0,     r0,     MASK(MSR_PR)
                   1271:        bne+    .L_syscall_returns_to_user
                   1272: 
                   1273:        /* TODO NMGS - is this code in common with interrupts and traps?*/
                   1274:        /* the syscall is returning to something in
                   1275:         * priviliged mode, can just rfi without modifying
                   1276:         * space registers
                   1277:         */
                   1278: 
                   1279:        lwz     r0,     SS_CR(r3)
                   1280:        mtcrf   0xFF,r0
                   1281:        lwz     r0,     SS_SRR0(r3)
                   1282:        mtsrr0  r0
                   1283:        lwz     r0,     SS_SRR1(r3)
                   1284:        mtsrr1  r0
                   1285: 
                   1286:        lwz     r0,     SS_R0(r3)
                   1287:        lwz     r1,     SS_R1(r3)
                   1288:        /* critical region for traps(interrupt?) since r1 no longer points
                   1289:         * to bottom of stack. Could be fixed. But interrupts are off (?).
                   1290:         */
                   1291: 
                   1292:        lwz     r2,     SS_R2(r3)
                   1293:        /* r3 restored last */
                   1294:        lwz     r3,     SS_R3(r3)
                   1295: 
                   1296:        rfi                             /* return to calling context */
                   1297: 
                   1298: .L_syscall_returns_to_user:    
                   1299: 
                   1300:        /* If jumping into user space, we should restore the user's
                   1301:         * segment register 0. We jump via a trampoline in physical mode
                   1302:         * TODO NMGS this trampoline code probably isn't needed
                   1303:         */
                   1304: 
                   1305:        lwz     r0,     SS_CR(r3)
                   1306:        mtcrf   0xFF,r0
                   1307: 
                   1308:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                   1309:         * as arguments */
                   1310:        lwz     r0,     SS_R1(r3)
                   1311:        mtsprg  1,      r0
                   1312:        lwz     r0,     SS_R2(r3)
                   1313:        mtsprg  2,      r0
                   1314:        lwz     r0,     SS_R3(r3)
                   1315:        mtsprg  3,      r0
                   1316: 
                   1317:        lwz     r0,     SS_R0(r3)
                   1318:        /* Prepare to rfi to the exception exit routine, which is
                   1319:         * in physical address space */
                   1320:        addis   r1,     0,      ha16(EXT(exception_exit))
                   1321:        addi    r1,     r1,     lo16(EXT(exception_exit))
                   1322:        lwz     r1,     0(r1)
                   1323:        mtsrr0  r1
                   1324:        li      r1,     MSR_VM_OFF
                   1325:        mtsrr1  r1
                   1326: 
                   1327:        lwz     r1,     PCB_SR0(r3)     /* For trampoline */
                   1328:        lwz     r2,     SS_SRR0(r3)     /* For trampoline */
                   1329:        lwz     r3,     SS_SRR1(r3)     /* load the last register... */
                   1330: 
                   1331:        rfi
                   1332: 
                   1333: 
                   1334: 
                   1335: /*
                   1336:  * thread_exception_return()
                   1337:  *
                   1338:  * Return to user mode directly from within a system call.
                   1339:  */
                   1340: 
                   1341: ENTRY(thread_exception_return, TAG_NO_FRAME_USED)
                   1342: 
                   1343: .L_thread_exc_ret_check_ast:   
                   1344: 
                   1345:        /* Disable interrupts */
                   1346:        li      r3,     MSR_SUPERVISOR_INT_OFF
                   1347:        mtmsr   r3
                   1348: 
                   1349:        /* Check to see if there's an outstanding AST */
                   1350:        /* We don't bother establishing a call frame even though CHECK_AST
                   1351:           can invoke ast_taken(), because it can just borrow our caller's
                   1352:           frame, given that we're not going to return.  */
                   1353:                
                   1354:        bl      EXT(check_for_ast)
                   1355:        
                   1356: .L_exc_ret_no_ast:
                   1357:        /* arriving here, interrupts should be disabled */
                   1358: 
                   1359:        mfsprg  r2,     0       /* HACK - need to get around r2 problem */
                   1360:        /* Get the active thread's PCB pointer to restore regs
                   1361:         */
                   1362:        
                   1363:        lwz     r31,    PP_CPU_DATA(r2)
                   1364:        lwz     r31,    CPU_ACTIVE_THREAD(r31)
                   1365:        lwz     r30,    THREAD_PCB(r31)
                   1366: 
                   1367:        /* If the MSR_SYSCALL_MASK isn't set, then we came from a trap,
                   1368:         * so warp into the return_from_trap (thread_return) routine,
                   1369:         * which takes PCB pointer in ARG0, not in r30!
                   1370:         */
                   1371:        lwz     r0,     SS_SRR1(r30)
                   1372:        mr      ARG0,   r30     /* Copy pcb pointer into ARG0 in case */
                   1373: 
                   1374:        /* test top half of msr */
                   1375:        srwi    r0,     r0,     16
                   1376:        cmpwi   CR0,    r0,     MSR_SYSCALL_MASK >> 16
                   1377:        bne-    CR0,    thread_return
                   1378: 
                   1379:        /* Otherwise, go to thread_syscall return, which requires
                   1380:         * r31 holding current thread, r30 holding current pcb
                   1381:         */
                   1382: 
                   1383:        /*
                   1384:         * restore saved state here
                   1385:         * except for r0-2, r3, r29, r30 and r31 used
                   1386:         * by thread_syscall_return,
                   1387:         */
                   1388:        lwz     r4,     SS_R4(r30)
                   1389:        lwz     r5,     SS_R5(r30)
                   1390:        lwz     r6,     SS_R6(r30)
                   1391:        lwz     r7,     SS_R7(r30)
                   1392:        lwz     r8,     SS_R8(r30)
                   1393:        lwz     r9,     SS_R9(r30)
                   1394:        lwz     r10,    SS_R10(r30)
                   1395:        lwz     r11,    SS_R11(r30)
                   1396:        lwz     r12,    SS_R12(r30)
                   1397:        lwz     r13,    SS_R13(r30)
                   1398:        lwz     r14,    SS_R14(r30)
                   1399:        lwz     r15,    SS_R15(r30)
                   1400:        lwz     r16,    SS_R16(r30)
                   1401:        lwz     r17,    SS_R17(r30)
                   1402:        lwz     r18,    SS_R18(r30)
                   1403:        lwz     r19,    SS_R19(r30)
                   1404:        lwz     r20,    SS_R20(r30)
                   1405:        lwz     r21,    SS_R21(r30)
                   1406:        lwz     r22,    SS_R22(r30)
                   1407:        lwz     r23,    SS_R23(r30)
                   1408:        lwz     r24,    SS_R24(r30)
                   1409:        lwz     r25,    SS_R25(r30)
                   1410:        lwz     r26,    SS_R26(r30)
                   1411:        lwz     r27,    SS_R27(r30)
                   1412:        lwz     r28,    SS_R28(r30)
                   1413:        lwz     r29,    SS_R29(r30)
                   1414: 
                   1415:        b       .L_thread_syscall_return
                   1416: 
                   1417: 
                   1418: 
                   1419: /*
                   1420:  * thread_bootstrap_return()
                   1421:  *
                   1422:  */
                   1423: ENTRY(thread_bootstrap_return, TAG_NO_FRAME_USED)
                   1424: 
                   1425:        /* Disable interrupts */
                   1426:        li      r3,     MSR_SUPERVISOR_INT_OFF
                   1427:        mtmsr   r3
                   1428: 
                   1429:        /* Check for any outstanding ASTs and deal with them */
                   1430: 
                   1431:        bl      EXT(check_for_ast)
                   1432:        
                   1433:        /*
                   1434:        ** Restore from AST check
                   1435:        */
                   1436:        mfsprg  r2,     0       /* HACK - need to get around r2 problem */
                   1437:        lwz     r3,     PP_CPU_DATA(r2)
                   1438:        lwz     r3,     CPU_ACTIVE_THREAD(r3)
                   1439:        lwz     r3,     THREAD_PCB(r3)
                   1440: 
                   1441:        /* Ok, we're all set, jump to thread_return as if we
                   1442:         * were just coming back from a trap (ie. r3 set up to point to pcb)
                   1443:         */     
                   1444: 
                   1445:        b       thread_return
                   1446: 
                   1447: 
                   1448: 
                   1449: /*
                   1450:  * ihandler(type)
                   1451:  *
                   1452:  * Entry:      VM switched ON
                   1453:  *             Interrupts  OFF
                   1454:  *              original r1-3 saved in sprg1-3
                   1455:  *              original srr0 and srr1 saved in per_proc structure
                   1456:  *              original cr            saved in per_proc structure
                   1457:  *              exception type (r3)    saved in per_proc structure
                   1458:  *              r1 = scratch
                   1459:  *              r2 = virt addr of per_proc_info
                   1460:  *             r3 = exception type (one of EXC_...) also in per_proc
                   1461:  *
                   1462:  * gdbhandler is a close derivative, bugfixes to one may apply to the other!
                   1463:  */
                   1464: 
                   1465: /* Build a saved state structure on the interrupt stack and call
                   1466:  * the routine interrupt()
                   1467:  */
                   1468: 
                   1469: ENTRY(ihandler, TAG_NO_FRAME_USED)     /* What tag should this have?! */
                   1470: 
                   1471:        /*
                   1472:         * get the value of istackptr, if it's zero then we're already on the
                   1473:         * interrupt stack, otherwise it points to a saved_state structure
                   1474:         * at the top of the interrupt stack.
                   1475:         */
                   1476: 
                   1477:        addis   r1,     0,      ha16(EXT(istackptr))
                   1478:        addi    r1,     r1,     lo16(EXT(istackptr))    /* TODO assumes 1 CPU */
                   1479:        lwz     r1,     0(r1)
                   1480:        cmpwi   CR0,    r1,     0
                   1481:        bne     CR0,    .L_istackfree
                   1482: 
                   1483:        /* We're already on the interrupt stack, get back the old
                   1484:         * stack pointer and make room for a frame
                   1485:         */
                   1486: 
                   1487:        mfsprg  r1,     1       /* recover old stack pointer */
                   1488: 
                   1489:        /* Move below the redzone where the interrupted thread may have
                   1490:         * been saving its state and make room for our saved state structure
                   1491:         */
                   1492:        subi    r1,     r1,     FM_REDZONE+SS_SIZE
                   1493: 
                   1494:        
                   1495:        
                   1496: .L_istackfree:
                   1497: 
                   1498:        /* Once we reach here, r1 contains the adjusted stack pointer
                   1499:          * where we can store a ppc_saved_state structure.
                   1500:         */
                   1501: 
                   1502:        stw     r0,     SS_R0(r1)
                   1503: 
                   1504:        mfsprg  r0,     1
                   1505:        stw     r0,     SS_R1(r1)
                   1506: 
                   1507:        mfsprg  r0,     2
                   1508:        stw     r0,     SS_R2(r1)
                   1509: 
                   1510:        mfsprg  r0,     3
                   1511:        stw     r0,     SS_R3(r1)
                   1512: 
                   1513:        stw     r4,     SS_R4(r1)
                   1514:        stw     r5,     SS_R5(r1)
                   1515:        stw     r6,     SS_R6(r1)
                   1516:        stw     r7,     SS_R7(r1)
                   1517:        stw     r8,     SS_R8(r1)
                   1518:        stw     r9,     SS_R9(r1)
                   1519:        stw     r10,    SS_R10(r1)
                   1520:        stw     r11,    SS_R11(r1)
                   1521:        stw     r12,    SS_R12(r1)
                   1522:        stw     r13,    SS_R13(r1)
                   1523:        stw     r14,    SS_R14(r1)
                   1524:        stw     r15,    SS_R15(r1)
                   1525:        stw     r16,    SS_R16(r1)
                   1526:        stw     r17,    SS_R17(r1)
                   1527:        stw     r18,    SS_R18(r1)
                   1528:        stw     r19,    SS_R19(r1)
                   1529:        stw     r20,    SS_R20(r1)
                   1530:        stw     r21,    SS_R21(r1)
                   1531:        stw     r22,    SS_R22(r1)
                   1532:        stw     r23,    SS_R23(r1)
                   1533:        stw     r24,    SS_R24(r1)
                   1534:        stw     r25,    SS_R25(r1)
                   1535:        stw     r26,    SS_R26(r1)
                   1536:        stw     r27,    SS_R27(r1)
                   1537:        stw     r28,    SS_R28(r1)
                   1538:        stw     r29,    SS_R29(r1)
                   1539:        stw     r30,    SS_R30(r1)
                   1540:        stw     r31,    SS_R31(r1)
                   1541: 
                   1542:        /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
                   1543:         * some of this comes back out from the per-processor structure
                   1544:         */
                   1545: 
                   1546:        lwz     r0,     PP_SAVE_CR(r2)
                   1547:        stw     r0,     SS_CR(r1)
                   1548:        
                   1549:        lwz     r5,     PP_SAVE_SRR0(r2)        /* r5 holds srr0 used below */
                   1550:        stw     r5,     SS_SRR0(r1)
                   1551: 
                   1552:        lwz     r0,     PP_SAVE_SRR1(r2)
                   1553:        stw     r0,     SS_SRR1(r1)
                   1554: 
                   1555:        mfxer   r0
                   1556:        stw     r0,     SS_XER(r1)
                   1557: 
                   1558:        mflr    r0
                   1559:        stw     r0,     SS_LR(r1)
                   1560: 
                   1561:        mfctr   r0
                   1562:        stw     r0,     SS_CTR(r1)
                   1563: 
                   1564:        /* Don't bother with MQ for now */
                   1565: 
                   1566:        /* Free the reservation whilst saving SR_COPYIN */
                   1567: 
                   1568:        mfsr    r0,     SR_COPYIN_NAME
                   1569:        li      r4,     SS_SR_COPYIN
                   1570:        sync                            /* bug fix for 3.2 processors */
                   1571:        stwcx.  r0,     r4,     r1
                   1572:        stw     r0,     SS_SR_COPYIN(r1)
                   1573:        
                   1574:        /* Mark that we're occupying the interrupt stack for sure now */
                   1575: 
                   1576:        addis   r4,     0,      ha16(EXT(istackptr))
                   1577:        addi    r4,     r4,     lo16(EXT(istackptr))
                   1578:        li      r0,     0
                   1579:        stw     r0,     0(r4)           /* TODO assumes 1 CPU */
                   1580: 
                   1581:        /*
                   1582:         * To summarise, when we reach here, we have filled out
                   1583:         * a ppc_saved_state structure on the interrupt stack, and
                   1584:         * the stack is marked as busy. We now generate a small
                   1585:         * stack frame with backpointers to follow the calling
                   1586:         * conventions. We set up the backpointers to the trapped
                   1587:         * routine allowing us to backtrace.
                   1588:         */
                   1589:        
                   1590:        mr      r4,     r1              /* Preserve saved_state in ARG1 */
                   1591:        subi    r1,     r1,     FM_SIZE
                   1592:        mfsprg  r0,     1
                   1593:        stw     r0,     FM_BACKPTR(r1)  /* point back to previous stackptr */
                   1594: 
                   1595: #if    DEBUG
                   1596:        /* If debugging, we need two frames, the first being a dummy
                   1597:         * which links back to the trapped routine. The second is
                   1598:         * that which the C routine below will need
                   1599:         */
                   1600: 
                   1601:        stw     r5,     FM_LR_SAVE(r1)  /* save old instr ptr as LR value */
                   1602: 
                   1603:        //stwu  r1,     -FM_SIZE(r1)    /* Mak new frame for C routine */
                   1604:        stw     r1,     -FM_SIZE(r1)    /* Mak new frame for C routine */
                   1605:        subi    r1,     r1,     FM_SIZE
                   1606: #endif /* DEBUG */
                   1607: 
                   1608:        /* r3 still holds the reason for the interrupt */
                   1609:        /* and r4 holds a pointer to the saved state */
                   1610:        mfdsisr ARG2
                   1611:        mfdar   ARG3
                   1612:        
                   1613:        bl      EXT(interrupt)
                   1614: 
                   1615:        /* interrupt() returns a pointer to the saved state in r3
                   1616:         *
                   1617:         * Ok, back from C. Disable interrupts while we restore things
                   1618:         */
                   1619: 
                   1620:        li      r0,     MSR_SUPERVISOR_INT_OFF
                   1621:        mtmsr   r0
                   1622: 
                   1623:        /* Reload the saved state */
                   1624: 
                   1625:        /* r0-2 will be restored last, use as temp for now */
                   1626: 
                   1627:        /* We don't restore r3-5, these are restored differently too.
                   1628:         * see trampoline code TODO NMGS evaluate need for this
                   1629:         */
                   1630: 
                   1631:        lwz     r6,     SS_R6(r3)
                   1632:        lwz     r7,     SS_R7(r3)
                   1633:        lwz     r8,     SS_R8(r3)
                   1634:        lwz     r9,     SS_R9(r3)
                   1635:        lwz     r10,    SS_R10(r3)
                   1636:        lwz     r11,    SS_R11(r3)
                   1637:        lwz     r12,    SS_R12(r3)
                   1638:        lwz     r13,    SS_R13(r3)
                   1639:        lwz     r14,    SS_R14(r3)
                   1640:        lwz     r15,    SS_R15(r3)
                   1641:        lwz     r16,    SS_R16(r3)
                   1642:        lwz     r17,    SS_R17(r3)
                   1643:        lwz     r18,    SS_R18(r3)
                   1644:        lwz     r19,    SS_R19(r3)
                   1645:        lwz     r20,    SS_R20(r3)
                   1646:        lwz     r21,    SS_R21(r3)
                   1647:        lwz     r22,    SS_R22(r3)
                   1648:        lwz     r23,    SS_R23(r3)
                   1649:        lwz     r24,    SS_R24(r3)
                   1650:        lwz     r25,    SS_R25(r3)
                   1651:        lwz     r26,    SS_R26(r3)
                   1652:        lwz     r27,    SS_R27(r3)
                   1653:        lwz     r28,    SS_R28(r3)
                   1654:        lwz     r29,    SS_R29(r3)
                   1655:        lwz     r30,    SS_R30(r3)
                   1656:        lwz     r31,    SS_R31(r3)
                   1657: 
                   1658:        lwz     r0,     SS_XER(r3)
                   1659:        mtxer   r0
                   1660:        lwz     r0,     SS_LR(r3)
                   1661:        mtlr    r0
                   1662:        lwz     r0,     SS_CTR(r3)
                   1663:        mtctr   r0
                   1664:        lwz     r0,     SS_SR_COPYIN(r3)
                   1665:        isync
                   1666:        mtsr    SR_COPYIN_NAME, r0
                   1667:        isync
                   1668: 
                   1669:        /* TODO NMGS don't restore mq since we're not 601-specific enough */
                   1670: 
                   1671:        /* Is this the first interrupt on the stack? */
                   1672: 
                   1673:        addis   r4,     0,      ha16(EXT(intstack_top_ss))
                   1674:        addi    r4,     r4,     lo16(EXT(intstack_top_ss))  /* TODO assumes 1 CPU */
                   1675:        lwz     r4,     0(r4)
                   1676: 
                   1677:        cmp     CR0,0,  r4,     r3
                   1678:        bne     CR0,    .L_notthelast_interrupt
                   1679: 
                   1680:        /* We're the last frame on the stack. Indicate that
                   1681:         * we've freed up the stack by putting our save state ptr in
                   1682:         * istackptr. Clear reservation at same time.
                   1683:         */
                   1684: 
                   1685:        addis   r4,     0,      ha16(EXT(istackptr))
                   1686:        addi    r4,     r4,     lo16(EXT(istackptr))    /* TODO assumes 1 CPU */
                   1687: /* we have to use an indirect store to clear reservation */
                   1688:        sync                            /* bug fix for 3.2 processors */
                   1689:        stwcx.  r3,     0,      r4              /* clear reservation */
                   1690:        stw     r3,     0(r4)
                   1691: 
                   1692:        /* We're the last frame on the stack.
                   1693:         * Check for ASTs if one of the below is true:  
                   1694:         *    returning to user mode
                   1695:         *    returning to a kloaded server
                   1696:         */
                   1697: 
                   1698:        lwz     r4,     SS_SRR1(r3)
                   1699:        andi.   r4,     r4,     MASK(MSR_PR)
                   1700:        bne+    .L_check_int_ast        /* returning to user level, check */
                   1701:        b       .L_no_int_ast   /* in kernel, no check */
                   1702: 
                   1703: .L_check_int_ast:
                   1704: 
                   1705:        /*
                   1706:         * There is a pending AST. Massage things to make it look like
                   1707:         * we took a trap and jump into the trap handler.  To do this
                   1708:         * we essentially pretend to return from the interrupt but
                   1709:         * at the last minute jump into the trap handler with an AST
                   1710:         * trap instead of performing an rfi.
                   1711:         */
                   1712: 
                   1713:        lwz     r0,     SS_R1(r3)
                   1714:        mtsprg  1,      r0
                   1715:        lwz     r0,     SS_R2(r3)
                   1716:        mtsprg  2,      r0
                   1717:        lwz     r0,     SS_R3(r3)
                   1718:        mtsprg  3,      r0
                   1719: 
                   1720:        lwz     r0,     SS_CR(r3)       /* store state in per_proc struct */
                   1721:        stw     r0,     PP_SAVE_CR(r2)
                   1722:        lwz     r0,     SS_SRR0(r3)
                   1723:        stw     r0,     PP_SAVE_SRR0(r2)
                   1724:        lwz     r0,     SS_SRR1(r3)
                   1725:        stw     r0,     PP_SAVE_SRR1(r2)
                   1726:        li      r0,     EXC_AST
                   1727:        stw     r0,     PP_SAVE_EXCEPTION_TYPE(r2)
                   1728:        
                   1729:        lwz     r0,     SS_R0(r3)
                   1730:        lwz     r4,     SS_R4(r3)
                   1731:        lwz     r5,     SS_R5(r3)
                   1732: 
                   1733:        /* r2 remains a constant - virt addr of per_proc_info */
                   1734:        li      r3,     EXC_AST /* TODO r3 isn't used by thandler -optimise? */
                   1735:        b       EXT(thandler)           /* hyperspace into AST trap */
                   1736: 
                   1737: .L_no_int_ast: 
                   1738: 
                   1739:        /* We're committed to performing the rfi now.
                   1740:         * If returning to the user space, we should restore the user's
                   1741:         * segment registers. We jump via a trampoline in physical mode
                   1742:         * TODO NMGS this trampoline code probably isn't needed
                   1743:         */
                   1744:        lwz     r0,     SS_SRR1(r3)
                   1745:        andi.   r0,     r0,     MASK(MSR_PR)
                   1746:        beq-    .L_interrupt_returns_to_kspace
                   1747: 
                   1748:        /* TODO NMGS would it be better to store SR0 in saved_state
                   1749:         * rather than perform this expensive lookup?
                   1750:         */
                   1751:        lwz     r1,     PP_CPU_DATA(r2)
                   1752:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                   1753:        lwz     r1,     THREAD_PCB(r1)
                   1754:        lwz     r1,     PCB_SR0(r1)     /* For trampoline */
                   1755: 
                   1756:        lwz     r0,     SS_CR(r3)
                   1757:        mtcrf   0xFF,r0
                   1758: 
                   1759:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                   1760:         * as arguments */
                   1761:        lwz     r0,     SS_R1(r3)
                   1762:        mtsprg  1,      r0
                   1763:        lwz     r0,     SS_R2(r3)
                   1764:        mtsprg  2,      r0
                   1765:        lwz     r0,     SS_R3(r3)
                   1766:        mtsprg  3,      r0
                   1767: 
                   1768:        lwz     r0,     SS_R0(r3)
                   1769:        lwz     r4,     SS_R4(r3)
                   1770:        lwz     r5,     SS_R5(r3)
                   1771: 
                   1772:        /* Prepare to rfi to the exception exit routine */
                   1773:        addis   r2,     0,      ha16(EXT(exception_exit))
                   1774:        addi    r2,     r2,     lo16(EXT(exception_exit))
                   1775:        lwz     r2,     0(r2)
                   1776:        mtsrr0  r2
                   1777:        li      r2,     MSR_VM_OFF
                   1778:        mtsrr1  r2
                   1779: 
                   1780:        /* r1 already loaded above */
                   1781:        lwz     r2,     SS_SRR0(r3)     /* For trampoline */
                   1782:        lwz     r3,     SS_SRR1(r3)     /* load the last register... */
                   1783:        
                   1784:        rfi
                   1785: .L_interrupt_returns_to_kspace:        
                   1786: .L_notthelast_interrupt:
                   1787:        /* If we're not the last interrupt on the interrupt stack
                   1788:         * life is easier, we don't need to switch back into the
                   1789:         * user's segment. we can simply restore the last registers and rfi
                   1790:         */
                   1791: 
                   1792:        lwz     r0,     SS_CR(r3)
                   1793:        mtcrf   0xFF,r0
                   1794:        lwz     r0,     SS_SRR0(r3)
                   1795:        mtsrr0  r0
                   1796:        lwz     r0,     SS_SRR1(r3)
                   1797:        mtsrr1  r0
                   1798: 
                   1799:        lwz     r0,     SS_R0(r3)
                   1800:        lwz     r1,     SS_R1(r3)
                   1801:        lwz     r2,     SS_R2(r3)       /* r2 is a constant - why restore?*/
                   1802:        /* r3 restored last */
                   1803:        lwz     r4,     SS_R4(r3)
                   1804:        lwz     r5,     SS_R5(r3)
                   1805:        /* and lastly... */
                   1806:        lwz     r3,     SS_R3(r3)
                   1807: 
                   1808:        rfi                             /* return to calling context */
                   1809:        
                   1810: /*
                   1811:  * gdbhandler(type)
                   1812:  *
                   1813:  * Entry:      VM switched ON
                   1814:  *             Interrupts  OFF
                   1815:  *              original r1-3 saved in sprg1-3
                   1816:  *              original srr0 and srr1 saved in per_proc structure
                   1817:  *              original cr            saved in per_proc structure
                   1818:  *              exception type (r3)    saved in per_proc structure
                   1819:  *              r1 = scratch
                   1820:  *              r2 = virt addr of per_proc_info
                   1821:  *             r3 = exception type (one of EXC_...) also in per_proc
                   1822:  *
                   1823:  *  Closely based on ihandler - bugfixes to one may apply to the other!
                   1824:  */
                   1825: 
                   1826: /* build a saved state structure on the debugger stack and call
                   1827:  * the routine enterDebugger()
                   1828:  */
                   1829: 
                   1830: ENTRY(gdbhandler, TAG_NO_FRAME_USED)   /* What tag should this have?! */
                   1831: #if DEBUG
                   1832:        /*
                   1833:         * get the value of gdbstackptr, if it's zero then we're already on the
                   1834:         * debugger stack, otherwise it points to a saved_state structure
                   1835:         * at the top of the debugger stack.
                   1836:         */
                   1837: 
                   1838:        addis   r1,     0,      ha16(EXT(gdbstackptr))
                   1839:        addi    r1,     r1,     lo16(EXT(gdbstackptr))  /* TODO assumes 1 CPU */
                   1840:        lwz     r1,     0(r1)
                   1841:        cmpwi   CR0,    r1,     0
                   1842:        bne     CR0,    .L_gdbstackfree
                   1843: 
                   1844:        /* We're already on the debugger stack, get back the old
                   1845:         * stack pointer and make room for a frame
                   1846:         */
                   1847: 
                   1848:        mfsprg  r1,     1       /* recover old stack pointer */
                   1849: 
                   1850:        /* Move below the redzone where the interrupted thread may have
                   1851:         * been saving its state and make room for our saved state structure
                   1852:         */
                   1853:        subi    r1,     r1,     FM_REDZONE+SS_SIZE
                   1854: 
                   1855:        /* TODO NMGS - how about checking for stack overflow, huh?! */
                   1856: 
                   1857: .L_gdbstackfree:
                   1858: 
                   1859:        /* Once we reach here, r1 contains the adjusted stack pointer
                   1860:          * where we can store a ppc_saved_state structure.
                   1861:         */
                   1862: 
                   1863:        stw     r0,     SS_R0(r1)
                   1864: 
                   1865:        mfsprg  r0,     1
                   1866:        stw     r0,     SS_R1(r1)
                   1867: 
                   1868:        mfsprg  r0,     2
                   1869:        stw     r0,     SS_R2(r1)
                   1870: 
                   1871:        mfsprg  r0,     3
                   1872:        stw     r0,     SS_R3(r1)
                   1873: 
                   1874:        stw     r4,     SS_R4(r1)
                   1875:        stw     r5,     SS_R5(r1)
                   1876:        stw     r6,     SS_R6(r1)
                   1877:        stw     r7,     SS_R7(r1)
                   1878:        stw     r8,     SS_R8(r1)
                   1879:        stw     r9,     SS_R9(r1)
                   1880:        stw     r10,    SS_R10(r1)
                   1881:        stw     r11,    SS_R11(r1)
                   1882:        stw     r12,    SS_R12(r1)
                   1883:        stw     r13,    SS_R13(r1)
                   1884:        stw     r14,    SS_R14(r1)
                   1885:        stw     r15,    SS_R15(r1)
                   1886:        stw     r16,    SS_R16(r1)
                   1887:        stw     r17,    SS_R17(r1)
                   1888:        stw     r18,    SS_R18(r1)
                   1889:        stw     r19,    SS_R19(r1)
                   1890:        stw     r20,    SS_R20(r1)
                   1891:        stw     r21,    SS_R21(r1)
                   1892:        stw     r22,    SS_R22(r1)
                   1893:        stw     r23,    SS_R23(r1)
                   1894:        stw     r24,    SS_R24(r1)
                   1895:        stw     r25,    SS_R25(r1)
                   1896:        stw     r26,    SS_R26(r1)
                   1897:        stw     r27,    SS_R27(r1)
                   1898:        stw     r28,    SS_R28(r1)
                   1899:        stw     r29,    SS_R29(r1)
                   1900:        stw     r30,    SS_R30(r1)
                   1901:        stw     r31,    SS_R31(r1)
                   1902: 
                   1903:        /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
                   1904:         * some of this comes back out from the per-processor structure
                   1905:         */
                   1906: 
                   1907:        lwz     r0,     PP_SAVE_CR(r2)
                   1908:        stw     r0,     SS_CR(r1)
                   1909:        
                   1910:        lwz     r5,     PP_SAVE_SRR0(r2)        /* r5 holds srr0 used below */
                   1911:        stw     r5,     SS_SRR0(r1)
                   1912: 
                   1913:        lwz     r0,     PP_SAVE_SRR1(r2)
                   1914:        stw     r0,     SS_SRR1(r1)
                   1915: 
                   1916:        mfxer   r0
                   1917:        stw     r0,     SS_XER(r1)
                   1918: 
                   1919:        mflr    r0
                   1920:        stw     r0,     SS_LR(r1)
                   1921: 
                   1922:        mfctr   r0
                   1923:        stw     r0,     SS_CTR(r1)
                   1924: 
                   1925:        /* Don't bother with MQ for now */
                   1926: 
                   1927:        /* Free the reservation whilst saving SR_COPYIN */
                   1928: 
                   1929:        mfsr    r0,     SR_COPYIN_NAME
                   1930:        li      r4,     SS_SR_COPYIN
                   1931:        sync                            /* bug fix for 3.2 processors */
                   1932:        stwcx.  r0,     r4,     r1
                   1933:        stw     r0,     SS_SR_COPYIN(r1)
                   1934:        
                   1935:        /* Mark that we're occupying the gdb stack for sure now */
                   1936: 
                   1937:        addis   r4,     0,      ha16(EXT(gdbstackptr))
                   1938:        addi    r4,     r4,     lo16(EXT(gdbstackptr))
                   1939:        li      r0,     0
                   1940:        stw     r0,     0(r4)           /* TODO assumes 1 CPU */
                   1941: 
                   1942:        /*
                   1943:         * To summarise, when we reach here, we have filled out
                   1944:         * a ppc_saved_state structure on the gdb stack, and
                   1945:         * the stack is marked as busy. We now generate a small
                   1946:         * stack frame with backpointers to follow the calling
                   1947:         * conventions. We set up the backpointers to the trapped
                   1948:         * routine allowing us to backtrace.
                   1949:         *
                   1950:         * This probably isn't needed in gdbhandler, but I've left
                   1951:         * it in place
                   1952:         */
                   1953:        
                   1954:        mr      r4,     r1              /* Preserve saved_state in ARG1 */
                   1955:        subi    r1,     r1,     FM_SIZE
                   1956:        mfsprg  r0,     1
                   1957:        stw     r0,     FM_BACKPTR(r1)  /* point back to previous stackptr */
                   1958: 
                   1959: #if    DEBUG
                   1960:        /* If debugging, we need two frames, the first being a dummy
                   1961:         * which links back to the trapped routine. The second is
                   1962:         * that which the C routine below will need
                   1963:         * TODO NMGS debugging call frame not correct yet
                   1964:         */
                   1965:        stw     r5,     FM_LR_SAVE(r1)  /* save old instr ptr as LR value */
                   1966:        //stwu  r1,     -FM_SIZE(r1)    /* point back to previous frame */
                   1967:        stw     r1,     -FM_SIZE(r1)    /* point back to previous frame */
                   1968:        subi    r1,     r1,     FM_SIZE
                   1969: #endif /* DEBUG */
                   1970: 
                   1971:        /* r3 still holds the reason for the trap */
                   1972:        /* and r4 holds a pointer to the saved state */
                   1973: 
                   1974:        mfdsisr ARG2
                   1975: 
                   1976:        bl      EXT(enterDebugger)
                   1977: 
                   1978:        /* enterDebugger() returns a pointer to the saved state in r3
                   1979:         *
                   1980:         * Ok, back from C. Disable interrupts while we restore things
                   1981:         */
                   1982: 
                   1983:        li      r0,     MSR_SUPERVISOR_INT_OFF
                   1984:        mtmsr   r0
                   1985: 
                   1986:        /* Reload the saved state */
                   1987: 
                   1988:        /* r0-2 will be restored last, use as temp for now */
                   1989: 
                   1990:        /* We do not restore r3-5, these are restored differently too.
                   1991:         * see trampoline code TODO NMGS evaluate need for this
                   1992:         */
                   1993: 
                   1994:        lwz     r6,     SS_R6(r3)
                   1995:        lwz     r7,     SS_R7(r3)
                   1996:        lwz     r8,     SS_R8(r3)
                   1997:        lwz     r9,     SS_R9(r3)
                   1998:        lwz     r10,    SS_R10(r3)
                   1999:        lwz     r11,    SS_R11(r3)
                   2000:        lwz     r12,    SS_R12(r3)
                   2001:        lwz     r13,    SS_R13(r3)
                   2002:        lwz     r14,    SS_R14(r3)
                   2003:        lwz     r15,    SS_R15(r3)
                   2004:        lwz     r16,    SS_R16(r3)
                   2005:        lwz     r17,    SS_R17(r3)
                   2006:        lwz     r18,    SS_R18(r3)
                   2007:        lwz     r19,    SS_R19(r3)
                   2008:        lwz     r20,    SS_R20(r3)
                   2009:        lwz     r21,    SS_R21(r3)
                   2010:        lwz     r22,    SS_R22(r3)
                   2011:        lwz     r23,    SS_R23(r3)
                   2012:        lwz     r24,    SS_R24(r3)
                   2013:        lwz     r25,    SS_R25(r3)
                   2014:        lwz     r26,    SS_R26(r3)
                   2015:        lwz     r27,    SS_R27(r3)
                   2016:        lwz     r28,    SS_R28(r3)
                   2017:        lwz     r29,    SS_R29(r3)
                   2018:        lwz     r30,    SS_R30(r3)
                   2019:        lwz     r31,    SS_R31(r3)
                   2020: 
                   2021:        lwz     r0,     SS_XER(r3)
                   2022:        lwz     r5,     SS_LR(r3)
                   2023:        mtxer   r0
                   2024:        mtlr    r5
                   2025:        lwz     r0,     SS_CTR(r3)
                   2026:        lwz     r5,     SS_SR_COPYIN(r3)
                   2027:        mtctr   r0
                   2028:        isync
                   2029:        mtsr    SR_COPYIN_NAME, r5
                   2030:        isync
                   2031: 
                   2032:        /* TODO NMGS don't restore mq since we're not 601-specific enough */
                   2033: 
                   2034:        /* Is this the first frame on the stack? */
                   2035: 
                   2036:        addis   r4,     0,      ha16(EXT(gdbstack_top_ss))
                   2037:        addi    r4,     r4,     lo16(EXT(gdbstack_top_ss))  /* TODO assumes 1 CPU */
                   2038:        lwz     r4,     0(r4)
                   2039: 
                   2040:        cmp     CR0, 0, r4,     r3
                   2041:        bne     CR0,    .L_notthelast_gdbframe
                   2042: 
                   2043:        /* We're the last frame on the stack. Indicate that
                   2044:         * we've freed up the stack by putting our save state ptr in
                   2045:         * istackptr. Clear reservation at same time.
                   2046:         */
                   2047:        addis   r4,     0,      ha16(EXT(gdbstackptr))
                   2048:        addi    r4,     r4,     lo16(EXT(gdbstackptr))  /* TODO assumes 1 CPU */
                   2049: /* we have to use an indirect store to clear reservation */
                   2050:        sync                            /* bug fix for 3.2 processors */
                   2051:        stwcx.  r3,     0,      r4              /* clear reservation */
                   2052:        stw     r3,     0(r4)
                   2053: 
                   2054:        /* We may be returning to something in the kernel space.
                   2055:         * If we are, we can skip the trampoline and just rfi,
                   2056:         * since we don't want to restore the user's space regs
                   2057:         */
                   2058: 
                   2059:        lwz     r0,     SS_SRR1(r3)
                   2060:        andi.   r0,     r0,     MASK(MSR_PR)
                   2061:        beq-    .L_gdb_ret_to_kspace
                   2062: 
                   2063:        /* If jumping into user space, we should restore the user's
                   2064:         * segment register 0. We jump via a trampoline in physical mode
                   2065:         * TODO NMGS this trampoline code probably isn't needed
                   2066:         */
                   2067: 
                   2068:        /* TODO NMGS would it be better to store SR0 in saved_state
                   2069:         * rather than perform this expensive lookup?
                   2070:         */
                   2071:        lwz     r1,     PP_CPU_DATA(r2)
                   2072:        lwz     r1,     CPU_ACTIVE_THREAD(r1)
                   2073:        lwz     r1,     THREAD_PCB(r1)
                   2074:        lwz     r1,     PCB_SR0(r1)     /* For trampoline */
                   2075: 
                   2076: #if DEBUG
                   2077:        /* Assert that PCB_SR0 is not in kernel space */
                   2078:        rlwinm. r0,     r1,     0,      8,      27
                   2079:        bne+    .Lbp_skip
                   2080:        BREAKPOINT_TRAP
                   2081: .Lbp_skip:
                   2082: #endif /* DEBUG */
                   2083: 
                   2084:        lwz     r0,     SS_CR(r3)
                   2085:        mtcrf   0xFF,r0
                   2086: 
                   2087:        /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
                   2088:         * as arguments
                   2089:         */
                   2090:        lwz     r0,     SS_R1(r3)
                   2091:        mtsprg  1,      r0
                   2092:        lwz     r0,     SS_R2(r3)
                   2093:        mtsprg  2,      r0
                   2094:        lwz     r0,     SS_R3(r3)
                   2095:        mtsprg  3,      r0
                   2096: 
                   2097:        lwz     r0,     SS_R0(r3)
                   2098:        lwz     r4,     SS_R4(r3)
                   2099:        lwz     r5,     SS_R5(r3)
                   2100: 
                   2101:        /* Prepare to rfi to the exception exit routine */
                   2102:        addis   r2,     0,      ha16(EXT(exception_exit))
                   2103:        addi    r2,     r2,     lo16(EXT(exception_exit))
                   2104:        lwz     r2,     0(r2)
                   2105:        mtsrr0  r2
                   2106:        li      r2,     MSR_VM_OFF
                   2107:        mtsrr1  r2
                   2108: 
                   2109:        /* r1 already loaded above */
                   2110:        lwz     r2,     SS_SRR0(r3)     /* For trampoline */
                   2111:        lwz     r3,     SS_SRR1(r3)     /* load the last register... */
                   2112:        
                   2113: 
                   2114:        rfi
                   2115:        
                   2116: .L_gdb_ret_to_kspace:  
                   2117: .L_notthelast_gdbframe:
                   2118:        /* If we're not the last frame on the stack
                   2119:         * life is easier, we don't need to switch back into the
                   2120:         * user's segment. we can simply restore the last registers and rfi
                   2121:         */
                   2122: 
                   2123:        lwz     r0,     SS_CR(r3)
                   2124:        mtcrf   0xFF,r0
                   2125:        lwz     r0,     SS_SRR0(r3)
                   2126:        mtsrr0  r0
                   2127:        lwz     r0,     SS_SRR1(r3)
                   2128:        mtsrr1  r0
                   2129: 
                   2130:        lwz     r0,     SS_R0(r3)
                   2131:        lwz     r1,     SS_R1(r3)
                   2132:        lwz     r2,     SS_R2(r3)       /* r2 is a constant - why restore?*/
                   2133:        /* r3 restored last */
                   2134:        lwz     r4,     SS_R4(r3)
                   2135:        lwz     r5,     SS_R5(r3)
                   2136:        /* and lastly... */
                   2137:        lwz     r3,     SS_R3(r3)
                   2138: 
                   2139:        rfi                             /* return to calling context */
                   2140: #endif /* DEBUG */     

unix.superglobalmegacorp.com

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