Annotation of kernel/machdep/ppc/hw_exception.s, revision 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.