Annotation of XNU/osfmk/ppc/hw_exception.s, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: 
        !            26: /* Low level routines dealing with exception entry and exit.
        !            27:  * There are various types of exception:
        !            28:  *
        !            29:  *    Interrupt, trap, system call and debugger entry. Each has it's own
        !            30:  *    handler since the state save routine is different for each. The
        !            31:  *    code is very similar (a lot of cut and paste).
        !            32:  *
        !            33:  *    The code for the FPU disabled handler (lazy fpu) is in cswtch.s
        !            34:  */
        !            35: 
        !            36: #include <debug.h>
        !            37: #include <mach_assert.h>
        !            38: #include <mach/exception_types.h>
        !            39: #include <mach/ppc/vm_param.h>
        !            40: 
        !            41: #include <assym.s>
        !            42: 
        !            43: #include <ppc/asm.h>
        !            44: #include <ppc/proc_reg.h>
        !            45: #include <ppc/trap.h>
        !            46: #include <ppc/exception.h>
        !            47: #include <ppc/spl.h>
        !            48: 
        !            49: 
        !            50: #define VERIFYSAVE 0
        !            51: #define FPVECDBG 0
        !            52:        
        !            53: /*
        !            54:  * thandler(type)
        !            55:  *
        !            56:  * ENTRY:      VM switched ON
        !            57:  *                     Interrupts  OFF
        !            58:  *                     R3 contains exception code
        !            59:  *                     R4 points to the saved context (virtual address)
        !            60:  *                     Everything is saved in savearea
        !            61:  */
        !            62: 
        !            63: /*
        !            64:  * If pcb.ksp == 0 then the kernel stack is already busy,
        !            65:  *                 we save ppc_saved state below the current stack pointer,
        !            66:  *                leaving enough space for the `red zone' in case the
        !            67:  *                trapped thread was in the middle of saving state below
        !            68:  *                its stack pointer.
        !            69:  *
        !            70:  * otherwise       we save a ppc_saved_state in the pcb, and switch to
        !            71:  *                the kernel stack (setting pcb.ksp to 0)
        !            72:  *
        !            73:  * on return, we do the reverse, the last state is popped from the pcb
        !            74:  * and pcb.ksp is set to the top of stack                  
        !            75:  */
        !            76: 
        !            77: 
        !            78: #if DEBUG
        !            79: 
        !            80: /* TRAP_SPACE_NEEDED is the space assumed free on the kernel stack when
        !            81:  * another trap is taken. We need at least enough space for a saved state
        !            82:  * structure plus two small backpointer frames, and we add a few
        !            83:  * hundred bytes for the space needed by the C (which may be less but
        !            84:  * may be much more). We're trying to catch kernel stack overflows :-)
        !            85:  */
        !            86: 
        !            87: #define TRAP_SPACE_NEEDED      FM_REDZONE+(2*FM_SIZE)+256
        !            88: 
        !            89: #endif /* DEBUG */
        !            90: 
        !            91:                        .text
        !            92: 
        !            93: ENTRY(thandler, TAG_NO_FRAME_USED)     /* What tag should this have?! */
        !            94: 
        !            95:                        mfsprg  r25,0                                           /* Get the per_proc */
        !            96:                
        !            97:                        lwz             r1,PP_ISTACKPTR(r25)            ; Get interrupt stack pointer
        !            98:        
        !            99: 
        !           100:                        lwz             r6,PP_CPU_DATA(r25)                     /* Get point to cpu specific data */
        !           101:                        cmpwi   cr0,r1,0                                        ; Are we on interrupt stack?                                    
        !           102:                        lwz             r6,CPU_ACTIVE_THREAD(r6)        /* Get the pointer to the currently active thread */
        !           103:                        beq-    cr0,EXT(ihandler)                       ; Yes, not allowed except when debugger
        !           104:                                                                                                ; is active.  We will let the ihandler do this...
        !           105:                        lwz             r9,THREAD_TOP_ACT(r6)           /* Point to the active activation */
        !           106:                        lwz             r26,ACT_MACT_BDA(r9)            /* Pick up the pointer to the blue box data area */
        !           107:                        lwz             r8,ACT_MACT_PCB(r9)                     /* Get the last savearea used */
        !           108:                        mr.             r26,r26                                         /* Do we have Blue Box Assist active? */
        !           109:                        lwz             r1,ACT_MACT_KSP(r9)                     /* Get the stack */
        !           110:                        bnel-   checkassist                                     /* See if we should assist this */
        !           111:                        stw             r4,ACT_MACT_PCB(r9)                     /* Point to our savearea */
        !           112:                        stw             r8,SAVprev(r4)                          /* Queue the new save area in the front */
        !           113:                        
        !           114: #if VERIFYSAVE
        !           115:                        bl              versave                                         ; (TEST/DEBUG)
        !           116: #endif
        !           117:                        
        !           118:                        cmpwi   cr1,r1, 0                                       /* zero implies already on kstack */
        !           119:                        stw             r9,SAVact(r4)                           /* Point the savearea at its activation */
        !           120:                        bne             cr1,.L_kstackfree                       /* This test is also used below */              
        !           121:                        lwz             r1,saver1(r4)                           /* Get the stack at 'rupt time */
        !           122: 
        !           123: 
        !           124: /* On kernel stack, allocate stack frame and check for overflow */
        !           125: #if DEBUG
        !           126: /*
        !           127:  * Test if we will overflow the Kernel Stack. We 
        !           128:  * check that there is at least TRAP_SPACE_NEEDED bytes
        !           129:  * free on the kernel stack
        !           130: */
        !           131: 
        !           132:                        lwz             r7,THREAD_KERNEL_STACK(r6)
        !           133:                        addi    r7,r7,TRAP_SPACE_NEEDED
        !           134:                        cmp             cr0,r1,r7
        !           135:                        bng-    EXT(ihandler)
        !           136: #endif /* DEBUG */
        !           137: 
        !           138:                        subi    r1,r1,FM_REDZONE                        /* Back up stack and leave room for a red zone */ 
        !           139: 
        !           140: .L_kstackfree:
        !           141: #if 0
        !           142:                        lis             r0,HIGH_ADDR(CutTrace)          /* (TEST/DEBUG) */
        !           143:                        oris    r0,r0,LOW_ADDR(CutTrace)        /* (TEST/DEBUG) */
        !           144:                        sc                                                                      /* (TEST/DEBUG) */
        !           145: #endif
        !           146:                        lwz             r7,savesrr1(r4)                         /* Pick up the entry MSR */
        !           147:                        mfmsr   r8                                                      /* Get the kernel's MSR state */
        !           148:                        li              r0,0                                            /* Make this 0 */
        !           149:                        rlwimi  r8,r7,0,MSR_EE_BIT,MSR_EE_BIT   /* Copy in the interrupt mask from the save area */
        !           150:                        
        !           151:                        beq             cr1,.L_state_on_kstack          /* using above test for pcb/stack */
        !           152: 
        !           153:                        stw             r0,ACT_MACT_KSP(r9)                     /* Show that we have taken the stack */
        !           154: 
        !           155: .L_state_on_kstack:    
        !           156:                        rlwinm. r6,r7,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on?
        !           157:                        lwz             r6,saver1(r4)                           /* Grab interrupt time stack */
        !           158:                        beq+    tvecoff                                         ; Vector off, do not save vrsave...
        !           159:                        mfspr   r7,vrsave                                       ; Get the VRSAVE register
        !           160:                        stw             r7,liveVRS(r25)                         ; Set the live value
        !           161: 
        !           162: tvecoff:       subi    r1,r1,FM_SIZE                           /* Push a header onto the current stack */
        !           163:                        stw             r6,FM_BACKPTR(r1)                       /* Link backwards */
        !           164: 
        !           165: #if    DEBUG
        !           166: /* If debugging, we need two frames, the first being a dummy
        !           167:  * which links back to the trapped routine. The second is
        !           168:  * that which the C routine below will need
        !           169:  */
        !           170:                        lwz             r7,savesrr0(r4)                         /* Get the point of interruption */
        !           171:                        stw             r7,FM_LR_SAVE(r1)                       /* save old instr ptr as LR value */
        !           172:                        stwu    r1,     -FM_SIZE(r1)                    /* and make new frame */
        !           173: #endif /* DEBUG */
        !           174: 
        !           175: 
        !           176: /* call trap handler proper, with
        !           177:  *   ARG0 = type               (not yet, holds pcb ptr)
        !           178:  *   ARG1 = saved_state ptr    (already there)
        !           179:  *   ARG2 = dsisr              (already there)
        !           180:  *   ARG3 = dar                        (already there)
        !           181:  */
        !           182: 
        !           183:                        lwz             r3,saveexception(r4)            /* Get the exception code */
        !           184:                        lwz             r5,savedsisr(r4)                        /* Get the saved DSISR */
        !           185:                        lwz             r6,savedar(r4)                          /* Get the DAR */
        !           186:        
        !           187:                        mtmsr   r8                                                      /* Turn on interrupts if enabled at 'rupt time */
        !           188: 
        !           189: /* syscall exception might warp here if there's nothing left
        !           190:  * to do except generate a trap
        !           191:  */
        !           192: 
        !           193: .L_call_trap:  
        !           194: #if 0
        !           195:                        lis             r0,HIGH_ADDR(CutTrace)          /* (TEST/DEBUG) */
        !           196:                        oris    r0,r0,LOW_ADDR(CutTrace)        /* (TEST/DEBUG) */
        !           197:                        sc                                                                      /* (TEST/DEBUG) */
        !           198: #endif
        !           199: 
        !           200:                        bl      EXT(trap)
        !           201: 
        !           202: /*
        !           203:  * Ok, return from C function
        !           204:  *
        !           205:  * This is also the point where new threads come when they are created.
        !           206:  * The new thread is setup to look like a thread that took an 
        !           207:  * interrupt and went immediatly into trap.
        !           208:  *
        !           209:  */
        !           210: 
        !           211: thread_return:
        !           212: 
        !           213:                        lwz             r4,SAVprev(r3)                          /* Pick up the previous savearea */
        !           214:                        mfmsr   r7                                                      /* Get the MSR */
        !           215:                        lwz             r11,SAVflags(r3)                        /* Get the flags of the current savearea */
        !           216:                        rlwinm  r7,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1       /* Clear the interrupt enable mask */
        !           217:                        mtmsr   r7                                                      /* Disable for interrupts */
        !           218:                
        !           219:                        mfsprg  r10,0                                           /* Restore the per_proc info */
        !           220:                        
        !           221:                        lwz             r8,savesrr1(r3)                         ; Get the MSR we are going to
        !           222:                        lwz             r1,PP_CPU_DATA(r10)                     /* Get the CPU data area */
        !           223:                        rlwinm  r11,r11,0,15,13                         /* Clear the syscall flag */
        !           224:                        lwz             r1,CPU_ACTIVE_THREAD(r1)        /* and the active thread */
        !           225:                        rlwinm. r8,r8,0,MSR_PR_BIT,MSR_PR_BIT   ; Are we going to the user?
        !           226:                        lwz             r8,THREAD_TOP_ACT(r1)           /* Now find the current activation */
        !           227:                        stw             r11,SAVflags(r3)                        /* Save back the flags (with reset stack cleared) */
        !           228: 
        !           229: #if 0
        !           230:                        lis             r0,HIGH_ADDR(CutTrace)          /* (TEST/DEBUG) */
        !           231:                        oris    r0,r0,LOW_ADDR(CutTrace)        /* (TEST/DEBUG) */
        !           232:                        sc                                                                      /* (TEST/DEBUG) */
        !           233: #endif
        !           234:                        stw             r4,ACT_MACT_PCB(r8)                     /* Point to the previous savearea (or 0 if none) */
        !           235: 
        !           236:                        beq-    chkfac                                          ; We are not leaving the kernel yet...
        !           237: 
        !           238:                        lwz             r5,THREAD_KERNEL_STACK(r1)      /* Get the base pointer to the stack */
        !           239:                        addi    r5,r5,KERNEL_STACK_SIZE-FM_SIZE /* Reset to empty */
        !           240:                        stw             r5,ACT_MACT_KSP(r8)                     /* Save the empty stack pointer */
        !           241:                        b               chkfac                                          /* Go end it all... */
        !           242: 
        !           243: 
        !           244: 
        !           245: /*
        !           246:  * shandler(type)
        !           247:  *
        !           248:  * ENTRY:      VM switched ON
        !           249:  *                     Interrupts  OFF
        !           250:  *                     R3 contains exception code
        !           251:  *                     R4 points to the saved context (virtual address)
        !           252:  *                     Everything is saved in savearea
        !           253:  */
        !           254: 
        !           255: /*
        !           256:  * If pcb.ksp == 0 then the kernel stack is already busy,
        !           257:  *                 this is an error - jump to the debugger entry
        !           258:  * 
        !           259:  * otherwise       depending upon the type of
        !           260:  *                 syscall, look it up in the kernel table
        !           261:  *                                or pass it to the server.
        !           262:  *
        !           263:  * on return, we do the reverse, the state is popped from the pcb
        !           264:  * and pcb.ksp is set to the top of stack.
        !           265:  */
        !           266: 
        !           267: ENTRY(shandler, TAG_NO_FRAME_USED)
        !           268: 
        !           269:                        mfsprg  r25,0                                           /* Get the per proc area */
        !           270:                        lwz             r0,saver0(r4)                           /* Get the original syscall number */
        !           271:                        lwz             r17,PP_ISTACKPTR(r25)           ; Get interrupt stack pointer
        !           272:                        andi.   r15,r0,0x7000                           /* Isolate the fastpath code */
        !           273:                        lwz             r16,PP_CPU_DATA(r25)            /* Assume we need this */
        !           274:                        mr.             r17,r17                                         ; Are we on interrupt stack?
        !           275:                        lwz             r7,savesrr1(r4)                         ; Get the SRR1 value
        !           276:                        beq-    EXT(ihandler)                           ; On interrupt stack, not allowed...
        !           277:                        lwz             r16,CPU_ACTIVE_THREAD(r16)      /* Get the thread pointer */
        !           278: 
        !           279: 
        !           280:                        rlwinm. r6,r7,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on?
        !           281:                        beq+    svecoff                                         ; Vector off, do not save vrsave...
        !           282:                        mfspr   r7,vrsave                                       ; Get the VRSAVE register
        !           283:                        stw             r7,liveVRS(r25)                         ; Set the live value
        !           284: 
        !           285: svecoff:       lwz             r13,THREAD_TOP_ACT(r16)         /* Pick up the active thread */
        !           286:                        cmplwi  r15,0x7000                                      /* Do we have a fast path trap? */
        !           287:                        lwz             r14,ACT_MACT_PCB(r13)           /* Now point to the PCB */
        !           288:                        beql+   fastpath                                        /* We think it's a fastpath... */
        !           289: 
        !           290:                        lwz             r1,ACT_MACT_KSP(r13)            /* Get the kernel stack pointer */
        !           291: #if DEBUG
        !           292:                        mr.             r1,r1                                           /* Are we already on the kernel stack? */
        !           293:                        li              r3,T_SYSTEM_CALL                        /* Yup, pretend we had an interrupt... */
        !           294:                        beq-    EXT(ihandler)                           /* Bad boy, bad boy... What'cha gonna do when they come for you? */
        !           295: #endif /* DEBUG */
        !           296: 
        !           297:                        stw             r4,ACT_MACT_PCB(r13)            /* Point to our savearea */
        !           298:                        li              r0,0                                            /* Clear this out */
        !           299:                        stw             r14,SAVprev(r4)                         /* Queue the new save area in the front */
        !           300:                        stw             r13,SAVact(r4)                          /* Point the savearea at its activation */
        !           301:                        
        !           302: #if VERIFYSAVE
        !           303:                        bl              versave                                         ; (TEST/DEBUG)
        !           304: #endif                 
        !           305:                        
        !           306:                        mr              r30,r4                                          /* Save pointer to the new context savearea */
        !           307:                        lwz             r15,saver1(r4)                          /* Grab interrupt time stack */
        !           308:                        stw             r0,ACT_MACT_KSP(r13)            /* Mark stack as busy with 0 val */
        !           309:                        stw             r15,FM_BACKPTR(r1)                      /* Link backwards */
        !           310:                
        !           311: #if    DEBUG
        !           312:        /* If debugging, we need two frames, the first being a dummy
        !           313:         * which links back to the trapped routine. The second is
        !           314:         * that which the C routine below will need
        !           315:         */
        !           316:                        lwz             r8,savesrr0(r30)                        /* Get the point of interruption */
        !           317:                        stw             r8,FM_LR_SAVE(r1)                       /* save old instr ptr as LR value */
        !           318:                        stwu    r1,     -FM_SIZE(r1)                    /* and make new frame */
        !           319: #endif /* DEBUG */
        !           320: 
        !           321:                        mfmsr   r0                                                      /* Get the MSR */
        !           322:                        lwz             r15,SAVflags(r4)                        /* Get the savearea flags */
        !           323:                        ori             r0,r0,lo16(MASK(MSR_EE))        /* Turn on interruption enabled bit */
        !           324:                        oris    r15,r15,SAVsyscall >> 16        /* Mark that it this is a syscall */
        !           325:                        stwu    r1,-(FM_SIZE+ARG_SIZE)(r1)      /* Make a stack frame */
        !           326:                        stw             r15,SAVflags(r30)                       /* Save syscall marker */
        !           327: 
        !           328:                        mtmsr   r0                                                      /* Enable interruptions */
        !           329: 
        !           330: 
        !           331:                        /* Call a function that can print out our syscall info */
        !           332:                        /* Note that we don't care about any volatiles yet */
        !           333:                        mr              r4,r30
        !           334:                        bl              EXT(syscall_trace)      
        !           335:        
        !           336:                        lwz             r0,saver0(r30)                          /* Get the system call selector */
        !           337:                        mr.             r0,r0                                           /* What kind is it? */
        !           338:                        blt-    .L_kernel_syscall                       /* -ve syscall - go to kernel */
        !           339:                                                                                                /* +ve syscall - go to server */
        !           340:                        cmpwi   cr0,    r0,0x7FFA
        !           341:                        beq-    .L_notify_interrupt_syscall
        !           342:                                                                                                /* +ve syscall - go to server */
        !           343: #ifdef MACH_BSD
        !           344:                        mr              r3,r30                                          /* Get PCB/savearea */
        !           345:                        lwz             r4,saver4(r30)                  /* Restore r4 */
        !           346:                        lwz             r5,saver5(r30)                  /* Restore r5 */
        !           347:                        lwz             r6,saver6(r30)                  /* Restore r6 */
        !           348:                        lwz             r7,saver7(r30)                  /* Restore r7 */
        !           349:                        lwz             r8,saver8(r30)                  /* Restore r8 */
        !           350:                        lwz             r9,saver9(r30)                  /* Restore r9 */
        !           351:                        lwz             r10,saver10(r30)                /* Restore r10 */
        !           352:                        bl              EXT(unix_syscall)                       /* Check out unix... */
        !           353: #endif
        !           354: 
        !           355: .L_call_server_syscall_exception:              
        !           356:                        li              r3,EXC_SYSCALL                          /* doexception(EXC_SYSCALL, num, 1) */
        !           357: 
        !           358: .L_call_server_exception:
        !           359:                        mr              r4,r0                                           /* Set syscall selector */
        !           360:                        li              r5,1
        !           361:                        b               EXT(doexception)                        /* Go away, never to return... */
        !           362: 
        !           363: /* The above, but with EXC_MACH_SYSCALL */
        !           364: .L_call_server_mach_syscall:
        !           365:                        li              r3,EXC_MACH_SYSCALL
        !           366:                        b               .L_call_server_exception        /* Join the common above... */
        !           367: 
        !           368: .L_notify_interrupt_syscall:
        !           369:                        lwz             r3,saver3(r30)                          ; Get the new PC address to pass in
        !           370:                        bl              EXT(syscall_notify_interrupt)
        !           371:                        b               .L_syscall_return
        !           372:        
        !           373: 
        !           374: 
        !           375: /* Once here, we know that the syscall was -ve
        !           376:  * we should still have r1=ksp,
        !           377:  * r16         = pointer to current thread,
        !           378:  * r13         = pointer to top activation,
        !           379:  * r0          = syscall number
        !           380:  * r30         = pointer to saved state (in pcb)
        !           381:  */
        !           382: .L_kernel_syscall:     
        !           383: 
        !           384: /*
        !           385:  * Are we allowed to do mach system calls?
        !           386:  */
        !           387: 
        !           388:                        addis   r31,0,HIGH_ADDR(EXT(realhost))
        !           389:                        lwz             r29,ACT_MACH_EXC_PORT(r13)      /* See if we have one of these ports */
        !           390:                        ori             r31,r31,LOW_ADDR(EXT(realhost))
        !           391:                        lwz             r31,HOST_SELF(r31)                      /* Find ourselves */
        !           392: 
        !           393: /* If thread_exception_port == realhost->hostname do syscall */        
        !           394:                        cmpw    cr1,r29,r31                                     /* Are we the host? */
        !           395:                        mr.             r29,r29                                         /* Is our port null? */
        !           396:                        beq+    cr1,.L_syscall_do_mach_syscall  /* We are the host... */
        !           397:                        bne+    .L_call_server_mach_syscall     /* Not host and not null, call the handler... */
        !           398: 
        !           399:                        lwz             r29,ACT_TASK(r13)                       /* Get our task */
        !           400:                        lwz             r29,TASK_MACH_EXC_PORT(r29)     /* Now get the exception port for it */
        !           401: 
        !           402: /* If task_exception_port == realhost->hostname do syscall */  
        !           403:                        cmpw    cr1,r29,r31                                     /* Is this the host? */
        !           404:                        mr.             r29,r29                                         /* Is it null? */
        !           405:                        beq+    cr1,.L_syscall_do_mach_syscall  /* We are the host... */
        !           406:                        bne+    .L_call_server_mach_syscall     /* Not host and not null, call the handler... */
        !           407: 
        !           408: /* else the syscall has failed, treat as priv instruction trap,
        !           409:  * set SRR1 to indicate privileged instruction
        !           410:  */
        !           411:                        
        !           412:                        li              r3,T_PROGRAM
        !           413:                        lwz             r29,savesrr1(r30)
        !           414:                        mr              r4,r30
        !           415:                        li              r5,0
        !           416:                        oris    r29,r29,MASK(SRR1_PRG_PRV_INS)>>16
        !           417:                        li              r6,0
        !           418:                        stw             r29,savesrr1(r30)
        !           419:                        b               .L_call_trap
        !           420: 
        !           421: /* When here, we know that we're allowed to do a mach syscall,
        !           422:  * and still have syscall number in r0, pcb pointer in r30
        !           423:  */
        !           424: 
        !           425: .L_syscall_do_mach_syscall:
        !           426:                        neg     r31,    r0              /* Make number +ve and put in r31*/
        !           427: 
        !           428: #ifdef MACHO_SYSCALL_BEGIN
        !           429: /*
        !           430:  * There's a bit of a problem with supporting both ELF and
        !           431:  * MACHO generated binaries. Each has their own location for
        !           432:  * storing the 8th and above arguments on the stack.
        !           433:  *
        !           434:  * Current the MACHO generated system calls have a BIT
        !           435:  * set telling the kernel its a MACHO style ABI.
        !           436:  */
        !           437: 
        !           438:                        li      r29,MACHO_SYSCALL_BEGIN
        !           439:                        and.    r25,r31,r29
        !           440:                        beq     not_macho
        !           441: 
        !           442:                        andc    r31,r31,r29             /* Clear the bit to get real trap */
        !           443:                        li      r25,FM_MACHO_ARG0-4
        !           444:                        b       continue2
        !           445: 
        !           446: not_macho:
        !           447:                        li      r25,FM_ELF_ARG0-4
        !           448: 
        !           449: continue2:
        !           450: #endif
        !           451: 
        !           452:        /* If out of range, call server with syscall exception */
        !           453:        addis   r29,    0,      HIGH_CADDR(EXT(mach_trap_count))
        !           454:        addi    r29,    r29,    LOW_ADDR(EXT(mach_trap_count))
        !           455:        lwz     r29,    0(r29)
        !           456: 
        !           457:        cmp     cr0,    r31,    r29
        !           458:        bge-    cr0,    .L_call_server_syscall_exception
        !           459: 
        !           460:        addis   r29,    0,      HIGH_CADDR(EXT(mach_trap_table))
        !           461:        addi    r29,    r29,    LOW_ADDR(EXT(mach_trap_table))
        !           462:        
        !           463:        /* multiply the trap number to get offset into table */
        !           464:        slwi    r31,    r31,    MACH_TRAP_OFFSET_POW2
        !           465: 
        !           466:        /* r31 now holds offset into table of our trap entry,
        !           467:         * add on the table base, and it then holds pointer to entry
        !           468:         */
        !           469:        add     r31,    r31,    r29
        !           470: 
        !           471:        /* If the function is kern_invalid, prepare to send an exception.
        !           472:           This is messy, but parallels the x86.  We need it for task_by_pid,
        !           473:           at least.  */
        !           474:        lis     r29,    HIGH_CADDR(EXT(kern_invalid))
        !           475:        addi    r29,    r29,    LOW_ADDR(EXT(kern_invalid))
        !           476:        lwz     r0,     MACH_TRAP_FUNCTION(r31)
        !           477:        cmp     cr0,    r0,     r29
        !           478:        beq-    .L_call_server_syscall_exception
        !           479: 
        !           480:        /* get arg count. If argc > 8 then not all args were in regs,
        !           481:         * so we must perform copyin.
        !           482:         */
        !           483:        lwz     r29,    MACH_TRAP_ARGC(r31)
        !           484:        cmpwi   cr0,    r29,    8
        !           485:        ble+    .L_syscall_got_args
        !           486: 
        !           487: /* argc > 8  - perform a copyin */
        !           488: /* if the syscall came from kernel space, we can just copy */
        !           489: 
        !           490:                        lwz             r0,savesrr1(r30)                                /* Pick up exception time MSR */
        !           491:                        andi.   r0,r0,MASK(MSR_PR)                              /* Check the priv bit */
        !           492:                        bne+    .L_syscall_arg_copyin                   /* We're not priviliged... */
        !           493: 
        !           494: /* we came from a privilaged task, just do a copy */
        !           495: /* get user's stack pointer */
        !           496: 
        !           497:                        lwz             r28,saver1(r30)                                 /* Get the stack pointer */
        !           498: 
        !           499:                        subi    r29,r29,8                                               /* Get the number of arguments to copy */
        !           500: 
        !           501: #ifdef MACHO_SYSCALL_BEGIN
        !           502:                        add             r28,r28,r25                                             /* Point to source - 4 */
        !           503: #else
        !           504:                        addi    r28,r28,COPYIN_ARG0_OFFSET-4    /* Point to source - 4 */
        !           505: #endif
        !           506:                        addi    r27,r1,FM_ARG0-4                                /* Point to sink - 4 */
        !           507: 
        !           508: .L_syscall_copy_word_loop:
        !           509:                        addic.  r29,r29,-1                                              /* Count down the number of arguments left */
        !           510:                        lwz             r0,4(r28)                                               /* Pick up the argument from the stack */
        !           511:                        addi    r28,r28,4                                               /* Point to the next source */
        !           512:                        stw             r0,4(r27)                                               /* Store the argument */
        !           513:                        addi    r27,r27,4                                               /* Point to the next sink */
        !           514:                        bne+    .L_syscall_copy_word_loop               /* Move all arguments... */
        !           515:                        b               .L_syscall_got_args                             /* Go call it now... */
        !           516: 
        !           517: 
        !           518: /* we came from a user task, pay the price of a real copyin */ 
        !           519: /* set recovery point */
        !           520: 
        !           521: .L_syscall_arg_copyin:
        !           522:                        addis   r28,0,HIGH_CADDR(.L_syscall_copyin_recover)
        !           523:                        addi    r28,r28,LOW_ADDR(.L_syscall_copyin_recover)
        !           524:                        stw             r28,THREAD_RECOVER(r16)                 /* R16 still holds thread ptr */
        !           525: 
        !           526: /* We can manipulate the COPYIN segment register quite easily
        !           527:  * here, but we've also got to make sure we don't go over a
        !           528:  * segment boundary - hence some mess.
        !           529:  * Registers from 12-29 are free for our use.
        !           530:  */
        !           531:        
        !           532: 
        !           533:                        lwz             r28,saver1(r30)                                 /* Get the stack pointer */
        !           534:                        subi    r29,r29,8                                               /* Get the number of arguments to copy */
        !           535:                        mfsr    r10,SR_UNUSED_BY_KERN                   ; Get the user state SR value
        !           536: 
        !           537: #ifdef MACHO_SYSCALL_BEGIN
        !           538:                        add             r28,r28,r25                                             /* Set source in user land */
        !           539:                        addi    r28,r28,4
        !           540: #else
        !           541:                        addi    r28,r28,COPYIN_ARG0_OFFSET      /* Set source in user land */
        !           542: #endif
        !           543: 
        !           544: /* set up SR_COPYIN to allow us to copy, we may need to loop
        !           545:  * around if we change segments. We know that this previously
        !           546:  * pointed to user space, so the sid doesn't need setting.
        !           547:  */
        !           548: .L_syscall_copyin_seg_loop:
        !           549:                        
        !           550:                        rlwimi  r10,r28,24,8,11                                 ; Blast the segment number into the SR
        !           551:                        rlwinm  r26,r28,0,4,31                                  ; Clear the segment number from source address
        !           552:                        mtsr    SR_COPYIN,r10                                   ; Set the copyin SR
        !           553:                        isync
        !           554: 
        !           555:                        oris    r26,r26,(SR_COPYIN_NUM << (28-16))      ; Insert the copyin segment number into source address
        !           556:        
        !           557: /* Make r27 point to address-4 of where we will store copied args */
        !           558:                        addi    r27,r1,FM_ARG0-4
        !           559:        
        !           560: .L_syscall_copyin_word_loop:
        !           561:                        
        !           562:                        lwz             r0,0(r26)                                               /* MAY CAUSE PAGE FAULT! */
        !           563:                        subi    r29,r29,1                                               ; Decrement count
        !           564:                        addi    r26,r26,4                                               ; Bump input
        !           565:                        stw             r0,4(r27)                                               ; Save the copied in word
        !           566:                        mr.             r29,r29                                                 ; Are they all moved?
        !           567:                        addi    r27,r27,4                                               ; Bump output
        !           568:                        beq+    .L_syscall_copyin_done                  ; Escape if we are done...
        !           569:        
        !           570:                        rlwinm. r0,r26,0,4,29                                   ; Did we just step into a new segment?          
        !           571:                        addi    r28,r28,4                                               ; Bump up user state address also
        !           572:                        bne+    .L_syscall_copyin_word_loop             ; We are still on the same segment...
        !           573:                        b               .L_syscall_copyin_seg_loop              /* On new segment! remap */
        !           574: 
        !           575: /* Don't bother restoring SR_COPYIN, we can leave it trashed */
        !           576: /* clear thread recovery as we're done touching user data */
        !           577: 
        !           578: .L_syscall_copyin_done:        
        !           579:                        li              r0,0
        !           580:                        stw             r0,THREAD_RECOVER(r16) /* R16 still holds thread ptr */
        !           581: 
        !           582: .L_syscall_got_args:
        !           583:                        lwz             r8,ACT_TASK(r13)                /* Get our task */
        !           584:                        lis             r10,hi16(EXT(c_syscalls_mach))  /* Get top half of counter address */
        !           585:                        lwz             r7,TASK_SYSCALLS_MACH(r8)               ; Get the current count
        !           586:                        lwz             r3,saver3(r30)                  /* Restore r3 */
        !           587:                        addi    r7,r7,1                                 ; Bump it
        !           588:                        ori             r10,r10,lo16(EXT(c_syscalls_mach)) /* Get low half of counter address */
        !           589:                        stw             r7,TASK_SYSCALLS_MACH(r8)               ; Save it
        !           590:                        lwz             r4,saver4(r30)                  /* Restore r4 */
        !           591:                        lwz             r9,0(r10)                               /* Get counter */       
        !           592:                        lwz             r5,saver5(r30)                  /* Restore r5 */
        !           593:                        lwz             r6,saver6(r30)                  /* Restore r6 */
        !           594:                        addi    r9,r9,1                                 /* Add 1 */
        !           595:                        lwz             r7,saver7(r30)                  /* Restore r7 */
        !           596:                        lwz             r8,saver8(r30)                  /* Restore r8 */
        !           597:                        stw             r9,0(r10)                               /* Save it back */
        !           598:                        lwz             r9,saver9(r30)                  /* Restore r9 */
        !           599:                        lwz             r10,saver10(r30)                /* Restore r10 */
        !           600: 
        !           601:                        lwz             r0,MACH_TRAP_FUNCTION(r31)
        !           602: 
        !           603: /* calling this function, all the callee-saved registers are
        !           604:  * still valid except for r30 and r31 which are in the PCB
        !           605:  * r30 holds pointer to saved state (ie. pcb)
        !           606:  * r31 is scrap
        !           607:  */
        !           608:                        mtctr   r0
        !           609:                        bctrl                                                   /* perform the actual syscall */
        !           610: 
        !           611: /* 'standard' syscall returns here - INTERRUPTS ARE STILL ON */
        !           612: 
        !           613: /* r3 contains value that we're going to return to the user
        !           614:  */
        !           615: 
        !           616: /*
        !           617:  * Ok, return from C function, ARG0 = return value
        !           618:  *
        !           619:  * get the active thread's PCB pointer and thus pointer to user state
        !           620:  * saved state is still in R30 and the active thread is in R16 .       
        !           621:  */
        !           622: 
        !           623: /* Store return value into saved state structure, since
        !           624:  * we need to pick up the value from here later - the
        !           625:  * syscall may perform a thread_set_syscall_return
        !           626:  * followed by a thread_exception_return, ending up
        !           627:  * at thread_syscall_return below, with SS_R3 having
        !           628:  * been set up already
        !           629:  */
        !           630: 
        !           631: /* When we are here, r16 should point to the current thread,
        !           632:  *                   r30 should point to the current pcb
        !           633:  */
        !           634: 
        !           635: /* save off return value, we must load it
        !           636:  * back anyway for thread_exception_return
        !           637:  * TODO NMGS put in register?
        !           638:  */
        !           639: .L_syscall_return:     
        !           640:                        mr              r31,r16                                                         /* Move the current thread pointer */
        !           641:                        stw             r3,saver3(r30)                                          /* Stash the return code */
        !           642:        
        !           643:                        /* Call a function that records the end of */
        !           644:                        /* the mach system call */
        !           645:                        mr              r4,r30
        !           646:                        bl              EXT(syscall_trace_end)  
        !           647:        
        !           648: #if 0
        !           649:                        lis             r0,HIGH_ADDR(CutTrace)                          /* (TEST/DEBUG) */
        !           650:                        mr              r4,r31                                                          /* (TEST/DEBUG) */
        !           651:                        oris    r0,r0,LOW_ADDR(CutTrace)                        /* (TEST/DEBUG) */
        !           652:                        mr              r5,r30                                                          /* (TEST/DEBUG) */
        !           653:                        sc                                                                                      /* (TEST/DEBUG) */
        !           654: #endif
        !           655: 
        !           656: .L_thread_syscall_ret_check_ast:       
        !           657:                        mfmsr   r12                                                                     /* Get the current MSR */
        !           658:                        rlwinm  r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1     /* Turn of interruptions enable bit */
        !           659:                        mtmsr   r12                                                                     /* Turn interruptions off */
        !           660:                        
        !           661:                        mfsprg  r10,0                                                           /* Get the per_processor block */
        !           662: 
        !           663: /* Check to see if there's an outstanding AST */
        !           664:                
        !           665:                        lwz             r4,PP_NEED_AST(r10)
        !           666:                        lwz             r4,0(r4)
        !           667:                        cmpi    cr0,r4, 0
        !           668:                        beq             cr0,.L_syscall_no_ast
        !           669: 
        !           670: /* Yes there is, call ast_taken 
        !           671:  * pretending that the user thread took an AST exception here,
        !           672:  * ast_taken will save all state and bring us back here
        !           673:  */
        !           674: 
        !           675: #if    DEBUG
        !           676: /* debug assert - make sure that we're not returning to kernel */
        !           677:                        lwz             r3,savesrr1(r30)
        !           678:                        andi.   r3,r3,MASK(MSR_PR)
        !           679:                        bne+    0f                                                                      /* returning to user level, check */
        !           680:                        
        !           681:                        BREAKPOINT_TRAP
        !           682: 0:             
        !           683: #endif /* DEBUG */
        !           684:        
        !           685:                        li      r3,     0
        !           686:                        li      r4,     AST_ALL
        !           687:                        li      r5,     1
        !           688:                        bl      EXT(ast_taken)
        !           689:                        
        !           690:                        b       .L_thread_syscall_ret_check_ast
        !           691: 
        !           692: /* thread_exception_return returns to here, almost all
        !           693:  * registers intact. It expects a full context restore
        !           694:  * of what it hasn't restored itself (ie. what we use).
        !           695:  *
        !           696:  * In particular for us,
        !           697:  * we still have     r31 points to the current thread,
        !           698:  *                   r30 points to the current pcb
        !           699:  */
        !           700:  
        !           701: .L_syscall_no_ast:
        !           702: .L_thread_syscall_return:
        !           703: 
        !           704:                        mr              r3,r30                                          ; Get savearea to the correct register for common exit
        !           705:                        lwz             r8,THREAD_TOP_ACT(r31)          /* Now find the current activation */
        !           706: 
        !           707:                        lwz             r11,SAVflags(r30)                       /* Get the flags */
        !           708:                        lwz             r5,THREAD_KERNEL_STACK(r31)     /* Get the base pointer to the stack */
        !           709:                        rlwinm  r11,r11,0,15,13                         /* Clear the syscall flag */
        !           710:                        lwz             r4,SAVprev(r30)                         ; Get the previous save area
        !           711:                        stw             r11,SAVflags(r30)                       /* Stick back the flags */
        !           712:                        addi    r5,r5,KERNEL_STACK_SIZE-FM_SIZE /* Reset to empty */
        !           713:                        stw             r4,ACT_MACT_PCB(r8)                     ; Save previous save area
        !           714:                        stw             r5,ACT_MACT_KSP(r8)                     /* Save the empty stack pointer */
        !           715:                
        !           716:                        b               chkfac                                          ; Go end it all...
        !           717: 
        !           718: 
        !           719: .L_syscall_copyin_recover:
        !           720: 
        !           721:        /* This is the catcher for any data faults in the copyin
        !           722:         * of arguments from the user's stack.
        !           723:         * r30 still holds a pointer to the PCB
        !           724:         *
        !           725:         * call syscall_error(EXC_BAD_ACCESS, EXC_PPC_VM_PROT_READ, sp, ssp),
        !           726:         *
        !           727:         * we already had a frame so we can do this
        !           728:         */     
        !           729:        
        !           730:                        li              r3,EXC_BAD_ACCESS
        !           731:                        li              r4,EXC_PPC_VM_PROT_READ
        !           732:                        lwz             r5,saver1(r30)
        !           733:                        mr              r6,r30
        !           734:                
        !           735:                        bl              EXT(syscall_error)
        !           736:                        b               .L_syscall_return
        !           737: 
        !           738: 
        !           739: /*
        !           740:  * thread_exception_return()
        !           741:  *
        !           742:  * Return to user mode directly from within a system call.
        !           743:  */
        !           744: 
        !           745: ENTRY(thread_exception_return, TAG_NO_FRAME_USED)
        !           746: 
        !           747: .L_thread_exc_ret_check_ast:   
        !           748: 
        !           749:                        mfmsr   r3                                                      /* Get the MSR */
        !           750:                        rlwinm  r3,r3,0,MSR_EE_BIT+1,MSR_EE_BIT-1       /* Clear EE */
        !           751:                        mtmsr   r3                                                      /* Disable interrupts */
        !           752: 
        !           753: /* Check to see if there's an outstanding AST */
        !           754: /* We don't bother establishing a call frame even though CHECK_AST
        !           755:    can invoke ast_taken(), because it can just borrow our caller's
        !           756:    frame, given that we're not going to return.  
        !           757: */
        !           758:                
        !           759:                        mfsprg  r10,0                                           /* Get the per_processor block */
        !           760:                        lwz             r4,PP_NEED_AST(r10)
        !           761:                        lwz             r4,0(r4)
        !           762:                        cmpi    cr0,r4, 0
        !           763:                        beq             cr0,.L_exc_ret_no_ast
        !           764:                
        !           765:        /* Yes there is, call ast_taken 
        !           766:         * pretending that the user thread took an AST exception here,
        !           767:         * ast_taken will save all state and bring us back here
        !           768:         */
        !           769:        
        !           770: #if    DEBUG
        !           771:        /* debug assert - make sure that we're not returning to kernel
        !           772:         *
        !           773:         * get the active thread's PCB pointer and thus pointer to user state
        !           774:         */
        !           775:                        lwz             r30,PP_CPU_DATA(r10)
        !           776:                        lwz             r30,CPU_ACTIVE_THREAD(r30)
        !           777:                        lwz             r30,THREAD_TOP_ACT(r30)
        !           778:                        lwz             r30,ACT_MACT_PCB(r30)
        !           779:                
        !           780:                        lwz             r3,savesrr1(r30)
        !           781:                        andi.   r3,r3,MASK(MSR_PR)
        !           782:                        bne+    ret_user2                       /* returning to user level, check */
        !           783: 
        !           784:                        BREAKPOINT_TRAP
        !           785: ret_user2:             
        !           786: #endif /* DEBUG */
        !           787: 
        !           788:                        li              r3,0
        !           789:                        li              r4,AST_ALL
        !           790:                        li              r5,1
        !           791:                        
        !           792:                        bl              EXT(ast_taken)
        !           793:                        b       .L_thread_exc_ret_check_ast     /* check for a second AST (rare)*/
        !           794:        
        !           795: /* arriving here, interrupts should be disabled */
        !           796: /* Get the active thread's PCB pointer to restore regs
        !           797:  */
        !           798: .L_exc_ret_no_ast:
        !           799:                        
        !           800:                        lwz             r31,PP_CPU_DATA(r10)
        !           801:                        lwz             r31,CPU_ACTIVE_THREAD(r31)
        !           802:                        lwz             r30,THREAD_TOP_ACT(r31)
        !           803:                        lwz             r30,ACT_MACT_PCB(r30)
        !           804:                
        !           805: /* If the MSR_SYSCALL_MASK isn't set, then we came from a trap,
        !           806:  * so warp into the return_from_trap (thread_return) routine,
        !           807:  * which takes PCB pointer in R3, not in r30!
        !           808:  */
        !           809:                        lwz             r0,SAVflags(r30)
        !           810:                        mr              r3,r30                                                          /* Copy pcb pointer into r3 in case */
        !           811:                        andis.  r0,r0,SAVsyscall>>16                            /* Are we returning from a syscall? */
        !           812:                        beq-    cr0,thread_return                                       /* Nope, must be a thread return... */
        !           813:                        b               .L_thread_syscall_return
        !           814:                
        !           815: /*
        !           816:  * thread_bootstrap_return()
        !           817:  *
        !           818:  */
        !           819: 
        !           820: ENTRY(thread_bootstrap_return, TAG_NO_FRAME_USED)
        !           821: 
        !           822:                        mfmsr   r12                                                                     /* Get the current MSR */
        !           823:                        rlwinm  r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1     /* Turn of interruptions enable bit */
        !           824:                        mtmsr   r12                                                                     /* Turn interruptions off */
        !           825:                
        !           826:                        mfsprg  r10,0                                                           /* Get the per_processor block */
        !           827: 
        !           828: 
        !           829: #if 0
        !           830:                        lis             r0,HIGH_ADDR(CutTrace)                          /* (TEST/DEBUG) */
        !           831:                        oris    r0,r0,LOW_ADDR(CutTrace)                        /* (TEST/DEBUG) */
        !           832:                        sc                                                                                      /* (TEST/DEBUG) */
        !           833: #endif
        !           834:        
        !           835:                        lwz             r31,PP_CPU_DATA(r10)
        !           836:                        
        !           837:                        lwz             r31,CPU_ACTIVE_THREAD(r31)
        !           838:                        lwz             r31,THREAD_TOP_ACT(r31)
        !           839: 
        !           840: .L_bootstrap_ret_check_ast:
        !           841:                        mfmsr   r12                                                                     /* Get the current MSR */
        !           842:                        rlwinm  r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1     /* Turn off interruptions enable bit */
        !           843:                        mtmsr   r12                                                                     /* Turn interruptions off */
        !           844:                        mfsprg  r10,0                                                           /* Get the per_processor block */
        !           845: /* Check for any outstanding ASTs and deal with them */
        !           846:                        lwz             r4,PP_NEED_AST(r10)
        !           847:                        lwz             r4,0(r4)
        !           848:                        cmpi    cr0,r4, 0
        !           849:                        beq             cr0,.L_bootstrap_ret_no_ast
        !           850:        
        !           851: /* we have a pending AST, now is the time to jump, args as below
        !           852:  * void ast_taken(boolean_t preemption, ast_t mask, boolean_t interrupts)
        !           853:  */
        !           854:                        li              r3,     0
        !           855:                        li              r4,AST_ALL
        !           856:                        li              r5,1
        !           857: 
        !           858:                        bl      EXT(ast_taken)
        !           859:                        b               .L_bootstrap_ret_check_ast                      /* Check for another AST (rare) */
        !           860:        
        !           861: 
        !           862: /* Back from dealing with ASTs, if there were any.
        !           863:  * r31 still holds pointer to ACT.
        !           864:  * 
        !           865:  * Time to deal with kloading or kloaded threads
        !           866:  */
        !           867: .L_bootstrap_ret_no_ast:
        !           868:                        lwz             r3,ACT_KLOADING(r31)
        !           869:                        li              r0,0
        !           870:                        cmpi    cr0,r3, 0
        !           871:                        li              r9,1
        !           872:                        beq+    .L_bootstrap_ret_no_kload
        !           873:                        stw             r0,ACT_KLOADING(r31)
        !           874:                        lwz             r3,PP_ACTIVE_KLOADED(r10)
        !           875:                        stw             r0,ACT_KLOADED(r31)
        !           876:                        stw             r31,0(r3)
        !           877: 
        !           878: /* Ok, we're all set, jump to thread_return as if we
        !           879:  * were just coming back from a trap (ie. r3 set up to point to pcb)
        !           880:  */    
        !           881: .L_bootstrap_ret_no_kload:
        !           882: 
        !           883:                        lwz             r3,ACT_MACT_PCB(r31)            /* Point to our saved context */
        !           884: #if 0
        !           885:                        lis             r0,HIGH_ADDR(CutTrace)          /* (TEST/DEBUG) */
        !           886:                        oris    r0,r0,LOW_ADDR(CutTrace)        /* (TEST/DEBUG) */
        !           887:                        sc                                                                      /* (TEST/DEBUG) */
        !           888: #endif
        !           889:        
        !           890:                        b               thread_return
        !           891:        
        !           892: /*
        !           893:  * ihandler(type)
        !           894:  *
        !           895:  * ENTRY:      VM switched ON
        !           896:  *                     Interrupts  OFF
        !           897:  *                     R3 contains exception code
        !           898:  *                     R4 points to the saved context (virtual address)
        !           899:  *                     Everything is saved in savearea
        !           900:  *
        !           901:  */
        !           902: 
        !           903: ENTRY(ihandler, TAG_NO_FRAME_USED)     /* What tag should this have?! */
        !           904: 
        !           905: /*
        !           906:  * get the value of istackptr, if it's zero then we're already on the
        !           907:  * interrupt stack, otherwise it points to a saved_state structure
        !           908:  * at the top of the interrupt stack.
        !           909:  */
        !           910: 
        !           911:                        lwz             r10,savesrr1(r4)                        /* Get SRR0 */
        !           912:                        mfsprg  r25,0                                           /* Get the per_proc block */
        !           913:                        li              r14,0                                           /* Zero this for now */
        !           914:                        lwz             r16,PP_CPU_DATA(r25)            /* Assume we need this */
        !           915:                        rlwinm. r10,r10,0,MSR_VEC_BIT,MSR_VEC_BIT       ; Was vector on?
        !           916:                        lwz             r1,     PP_ISTACKPTR(r25)               /* Get the interrupt stack */
        !           917:                        li              r13,0                                           /* Zero this for now */
        !           918:                        lwz             r16,CPU_ACTIVE_THREAD(r16)      /* Get the thread pointer */
        !           919: 
        !           920:                        beq+    ivecoff                                         ; Vector off, do not save vrsave...
        !           921:                        mfspr   r7,vrsave                                       ; Get the VRSAVE register
        !           922:                        stw             r7,liveVRS(r25)                         ; Set the live value
        !           923: 
        !           924: ivecoff:       li              r0,0                                            /* Get a constant 0 */
        !           925:                        cmplwi  cr1,r16,0                                       /* Are we still booting? */
        !           926:                        mr.             r1,r1                                           /* Is it active? */
        !           927:                        beq-    cr1,ihboot1                                     /* We're still coming up... */
        !           928:                        lwz             r13,THREAD_TOP_ACT(r16)         /* Pick up the active thread */
        !           929:                        lwz             r14,ACT_MACT_PCB(r13)           /* Now point to the PCB */
        !           930: 
        !           931: ihboot1:       lwz             r9,saver1(r4)                           /* Pick up the 'rupt time stack */
        !           932:                        stw             r14,SAVprev(r4)                         /* Queue the new save area in the front */
        !           933:                        stw             r13,SAVact(r4)                          /* Point the savearea at its activation */
        !           934:                        beq-    cr1,ihboot4                                     /* We're still coming up... */
        !           935:                        stw             r4,ACT_MACT_PCB(r13)            /* Point to our savearea */
        !           936: 
        !           937: ihboot4:       bne             .L_istackfree                           /* Nope... */
        !           938: 
        !           939: /* We're already on the interrupt stack, get back the old
        !           940:  * stack pointer and make room for a frame
        !           941:  */
        !           942: 
        !           943:                        subi    r1,r9,FM_REDZONE                        /* Back up beyond the red zone */
        !           944:                        b               ihsetback                                       /* Go  set up the back chain... */
        !           945:        
        !           946: .L_istackfree:
        !           947:                        lwz             r10,SAVflags(r4)                        
        !           948:                        stw             r0,PP_ISTACKPTR(r25)            /* Mark the stack in use */
        !           949:                        oris    r10,r10,HIGH_ADDR(SAVrststk)    /* Indicate we reset stack when we return from this one */
        !           950:                        stw             r10,SAVflags(r4)                        /* Stick it back */             
        !           951:        
        !           952:        /*
        !           953:         * To summarise, when we reach here, the state has been saved and
        !           954:         * the stack is marked as busy. We now generate a small
        !           955:         * stack frame with backpointers to follow the calling
        !           956:         * conventions. We set up the backpointers to the trapped
        !           957:         * routine allowing us to backtrace.
        !           958:         */
        !           959:        
        !           960: ihsetback:     subi    r1,r1,FM_SIZE                           /* Make a new frame */
        !           961:                        stw             r9,FM_BACKPTR(r1)                       /* point back to previous stackptr */
        !           962:                
        !           963: #if VERIFYSAVE
        !           964:                        bl              versave                                         ; (TEST/DEBUG)
        !           965: #endif
        !           966: 
        !           967: #if    DEBUG
        !           968: /* If debugging, we need two frames, the first being a dummy
        !           969:  * which links back to the trapped routine. The second is
        !           970:  * that which the C routine below will need
        !           971:  */
        !           972:                        lwz             r5,savesrr0(r4)                         /* Get interrupt address */
        !           973:                        stw             r5,FM_LR_SAVE(r1)                       /* save old instr ptr as LR value */
        !           974:                        stwu    r1,-FM_SIZE(r1)                         /* Make another new frame for C routine */
        !           975: #endif /* DEBUG */
        !           976: 
        !           977:                        lwz             r5,savedsisr(r4)                        /* Get the DSISR */
        !           978:                        lwz             r6,savedar(r4)                          /* Get the DAR */
        !           979:                        
        !           980:                        bl      EXT(interrupt)
        !           981: 
        !           982: 
        !           983: /* interrupt() returns a pointer to the saved state in r3
        !           984:  *
        !           985:  * Ok, back from C. Disable interrupts while we restore things
        !           986:  */
        !           987:                        .globl EXT(ihandler_ret)
        !           988: 
        !           989: LEXT(ihandler_ret)                                                             /* Marks our return point from debugger entry */
        !           990: 
        !           991:                        mfmsr   r0                                                      /* Get our MSR */
        !           992:                        rlwinm  r0,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1       /* Flip off the interrupt enabled bit */
        !           993:                        mtmsr   r0                                                      /* Make sure interrupts are disabled */
        !           994:                        mfsprg  r10,0                                           /* Get the per_proc block */
        !           995:                
        !           996:                        lwz             r8,PP_CPU_DATA(r10)                     /* Get the CPU data area */
        !           997:                        lwz             r7,SAVflags(r3)                         /* Pick up the flags */
        !           998:                        lwz             r8,CPU_ACTIVE_THREAD(r8)        /* and the active thread */
        !           999:                        lwz             r9,SAVprev(r3)                          /* Get previous save area */
        !          1000:                        cmplwi  cr1,r8,0                                        /* Are we still initializing? */
        !          1001:                        lwz             r12,savesrr1(r3)                        /* Get the MSR we will load on return */
        !          1002:                        beq-    cr1,ihboot2                                     /* Skip if we are still in init... */
        !          1003:                        lwz             r8,THREAD_TOP_ACT(r8)           /* Pick up the active thread */
        !          1004: 
        !          1005: ihboot2:       andis.  r11,r7,HIGH_ADDR(SAVrststk)     /* Is this the first on the stack? */
        !          1006:                        beq-    cr1,ihboot3                                     /* Skip if we are still in init... */
        !          1007:                        stw             r9,ACT_MACT_PCB(r8)                     /* Point to previous context savearea */
        !          1008: 
        !          1009: ihboot3:       mr              r4,r3                                           /* Move the savearea pointer */
        !          1010:                        beq             .L_no_int_ast2                          /* Get going if not the top o' stack... */
        !          1011: 
        !          1012: 
        !          1013: /* We're the last frame on the stack. Restore istackptr to empty state.
        !          1014:  *
        !          1015:  * Check for ASTs if one of the below is true: 
        !          1016:  *    returning to user mode
        !          1017:  *    returning to a kloaded server
        !          1018:  */
        !          1019:                        lwz             r9,PP_INTSTACK_TOP_SS(r10)      /* Get the empty stack value */
        !          1020:                        andc    r7,r7,r11                                       /* Remove the stack reset bit in case we pass this one */
        !          1021:                        stw             r9,PP_ISTACKPTR(r25)            /* Save that saved state ptr */
        !          1022:                        andi.   r6,r12,MASK(MSR_PR)                     /* Are we going to problem state? (Sorry, ancient IBM term for non-privileged) */
        !          1023:                        stw             r7,SAVflags(r4)                         /* Save the flags */
        !          1024:                        beq-    .L_no_int_ast                           ; In kernel space, no AST check...
        !          1025: 
        !          1026:                        lwz             r11,PP_NEED_AST(r10)            /* Get the AST request address */
        !          1027:                        lwz             r11,0(r11)                                      /* Get the request */
        !          1028:                        li              r3,T_AST                                        /* Assume the worst */
        !          1029:                        mr.             r11,r11                                         /* Are there any pending? */
        !          1030:                        beq             .L_no_int_ast                           /* Nope... */
        !          1031: 
        !          1032: /*
        !          1033:  * There is a pending AST. Massage things to make it look like
        !          1034:  * we took a trap and jump into the trap handler.  To do this
        !          1035:  * we essentially pretend to return from the interrupt but
        !          1036:  * at the last minute jump into the trap handler with an AST
        !          1037:  * trap instead of performing an rfi.
        !          1038:  */
        !          1039: 
        !          1040:                        stw             r3,saveexception(r4)            /* Set the exception code to T_AST */
        !          1041:                        b               EXT(thandler)                           /* hyperspace into AST trap */
        !          1042: 
        !          1043: .L_no_int_ast: 
        !          1044:                        mr              r3,r4                                           ; Get into the right register for common code
        !          1045: .L_no_int_ast2:        
        !          1046:                        rlwinm  r7,r7,0,15,13                           /* Clear the syscall bit */
        !          1047:                        li              r4,0                                            ; Assume for a moment that we are in init
        !          1048:                        stw             r7,SAVflags(r3)                         /* Set the flags */
        !          1049:                        beq-    cr1,chkfac                                      ; Jump away if we are in init...
        !          1050:                        lwz             r4,ACT_MACT_PCB(r8)                     ; Get the new level marker
        !          1051: 
        !          1052: 
        !          1053: ;
        !          1054: ;                      This section is common to all exception exits.  It throws away vector
        !          1055: ;                      and floating point saveareas as the exception level of a thread is
        !          1056: ;                      exited.  
        !          1057: ;
        !          1058: ;                      It also enables the facility if its context is live
        !          1059: ;                      Requires:
        !          1060: ;                              R3  = Savearea to be released (virtual)
        !          1061: ;                              R4  = New top of savearea stack (could be 0)
        !          1062: ;                              R8  = pointer to activation
        !          1063: ;                              R10 = per_proc block
        !          1064: ;
        !          1065: chkfac:                mr.             r8,r8                                           ; Are we still in boot?
        !          1066:                        beq-    chkenax                                         ; Yeah, skip it all...
        !          1067:                        
        !          1068:                        lwz             r20,ACT_MACT_FPUlvl(r8)         ; Get the FPU level
        !          1069:                        lwz             r12,savesrr1(r3)                        ; Get the current MSR
        !          1070:                        cmplw   r20,r3                                          ; Are we returning from the active level?
        !          1071:                        lwz             r23,PP_FPU_THREAD(r10)          ; Get floating point owner
        !          1072:                        rlwinm  r12,r12,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Turn off floating point for now
        !          1073:                        cmplw   cr1,r23,r8                                      ; Are we the facility owner?
        !          1074:                        lhz             r26,PP_CPU_NUMBER(r10)          ; Get the current CPU number
        !          1075:                        beq-    chkfpfree                                       ; Leaving active level, can not possibly enable...
        !          1076:                        bne-    cr1,chkvec                                      ; Not our facility, nothing to do here...
        !          1077: 
        !          1078: #if FPVECDBG
        !          1079:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1080:                        li              r2,0x3301                                       ; (TEST/DEBUG)
        !          1081:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1082:                        sc                                                                      ; (TEST/DEBUG)
        !          1083: #endif 
        !          1084: 
        !          1085:                        lwz             r24,ACT_MACT_FPUcpu(r8)         ; Get the CPU this context was enabled on last
        !          1086:                        cmplw   r4,r20                                          ; Are we going to be in the right level?
        !          1087:                        cmplw   cr1,r24,r26                                     ; Are we on the right CPU?
        !          1088:                        li              r0,0                                            ; Get a constant 0
        !          1089:                        beq+    cr1,chkfpnlvl                           ; Right CPU...
        !          1090:                        
        !          1091:                        stw             r0,PP_FPU_THREAD(r10)           ; Show facility unowned so we do not get back here
        !          1092:                        b               chkvec                                          ; Go check out the vector facility...
        !          1093:                        
        !          1094: chkfpnlvl:     bne-    chkvec                                          ; Different level, can not enable...
        !          1095:                        lwz             r24,ACT_MACT_FPU(r8)            ; Get the floating point save area
        !          1096:                        ori             r12,r12,lo16(MASK(MSR_FP))      ; Enable facility
        !          1097:                        mr.             r24,r24                                         ; Does the savearea exist?
        !          1098:                        li              r0,1                                            ; Get set to invalidate
        !          1099:                        beq-    chkvec                                          ; Nothing to invalidate...
        !          1100:                        lwz             r25,SAVlvlfp(r24)                       ; Get the level of top savearea
        !          1101:                        cmplw   r4,r25                                          ; Is the top one ours?
        !          1102:                        bne+    chkvec                                          ; Not ours...
        !          1103:                        stw             r0,SAVlvlfp(r24)                        ; Invalidate the first one
        !          1104: 
        !          1105: #if 0
        !          1106:                        mfmsr   r0                                              ; (TEST/DEBUG)
        !          1107:                        ori             r0,r0,0x2000                    ; (TEST/DEBUG)
        !          1108:                        mtmsr   r0                                              ; (TEST/DEBUG)
        !          1109:                        isync                                                   ; (TEST/DEBUG)
        !          1110:                        
        !          1111:                        stfd    f0,savevr0(r3)                  ; (TEST/DEBUG)
        !          1112:                        stfd    f1,savevr0+8(r3)                ; (TEST/DEBUG)
        !          1113:                        stfd    f2,savevr0+0x10(r3)             ; (TEST/DEBUG)
        !          1114:                        stfd    f3,savevr0+0x18(r3)             ; (TEST/DEBUG)
        !          1115:                        stfd    f4,savevr0+0x20(r3)             ; (TEST/DEBUG)
        !          1116:                        stfd    f5,savevr0+0x28(r3)             ; (TEST/DEBUG)
        !          1117:                        stfd    f6,savevr0+0x30(r3)             ; (TEST/DEBUG)
        !          1118:                        stfd    f7,savevr0+0x38(r3)             ; (TEST/DEBUG)
        !          1119:                        stfd    f8,savevr0+0x40(r3)             ; (TEST/DEBUG)
        !          1120:                        stfd    f9,savevr0+0x48(r3)             ; (TEST/DEBUG)
        !          1121:                        stfd    f10,savevr0+0x50(r3)    ; (TEST/DEBUG)
        !          1122:                        stfd    f11,savevr0+0x58(r3)    ; (TEST/DEBUG)
        !          1123:                        stfd    f12,savevr0+0x60(r3)    ; (TEST/DEBUG)
        !          1124:                        stfd    f13,savevr0+0x68(r3)    ; (TEST/DEBUG)
        !          1125:                        stfd    f14,savevr0+0x70(r3)    ; (TEST/DEBUG)
        !          1126:                        stfd    f15,savevr0+0x78(r3)    ; (TEST/DEBUG)
        !          1127:                        stfd    f16,savevr0+0x80(r3)    ; (TEST/DEBUG)
        !          1128:                        stfd    f17,savevr0+0x88(r3             ; (TEST/DEBUG)
        !          1129:                        stfd    f18,savevr0+0x90(r3)    ; (TEST/DEBUG)
        !          1130:                        stfd    f19,savevr0+0x98(r3)    ; (TEST/DEBUG)
        !          1131:                        stfd    f20,savevr0+0xA0(r3)    ; (TEST/DEBUG)
        !          1132:                        stfd    f21,savevr0+0xA8(r3)    ; (TEST/DEBUG)
        !          1133:                        stfd    f22,savevr0+0xB0(r3)    ; (TEST/DEBUG)
        !          1134:                        stfd    f23,savevr0+0xB8(r3)    ; (TEST/DEBUG)
        !          1135:                        stfd    f24,savevr0+0xC0(r3)    ; (TEST/DEBUG)
        !          1136:                        stfd    f25,savevr0+0xC8(r3)    ; (TEST/DEBUG)
        !          1137:                        stfd    f26,savevr0+0xD0(r3)    ; (TEST/DEBUG)
        !          1138:                        stfd    f27,savevr0+0xD8(r3)    ; (TEST/DEBUG)
        !          1139:                        stfd    f28,savevr0+0xE0(r3)    ; (TEST/DEBUG)
        !          1140:                        stfd    f29,savevr0+0xE8(r3)    ; (TEST/DEBUG)
        !          1141:                        stfd    f30,savevr0+0xF0(r3)    ; (TEST/DEBUG)
        !          1142:                        stfd    f31,savevr0+0xF8(r3)    ; (TEST/DEBUG)
        !          1143: 
        !          1144:                        li              r2,64                                   ; (TEST/DEBUG)
        !          1145:                        la              r20,savevr0(r3)                 ; (TEST/DEBUG)
        !          1146:                        la              r21,savefp0(r24)                ; (TEST/DEBUG)
        !          1147:                        
        !          1148: ckmurderdeath2:
        !          1149:                        lwz             r22,0(r20)                              ; (TEST/DEBUG)
        !          1150:                        subic.  r2,r2,1                                 ; (TEST/DEBUG)
        !          1151:                        lwz             r23,0(r21)                              ; (TEST/DEBUG)
        !          1152:                        addi    r20,r20,4                               ; (TEST/DEBUG)
        !          1153:                        cmplw   cr1,r22,r23                             ; (TEST/DEBUG)
        !          1154:                        addi    r21,r21,4                               ; (TEST/DEBUG)
        !          1155:                        bne-    cr1,diekilldead2                ; (TEST/DEBUG)
        !          1156:                        bne+    ckmurderdeath2                  ; (TEST/DEBUG)
        !          1157:                        b               dontdiekilldead2                ; (TEST/DEBUG)
        !          1158:                        
        !          1159: diekilldead2:                                                          ; (TEST/DEBUG)
        !          1160:                        mr              r4,r24                                  ; (TEST/DEBUG)
        !          1161:                        BREAKPOINT_TRAP                                 ; (TEST/DEBUG)
        !          1162:                        
        !          1163: dontdiekilldead2:
        !          1164:                        lfd             f0,savevr0(r3)                  ; (TEST/DEBUG)
        !          1165:                        lfd             f1,savevr0+8(r3)                ; (TEST/DEBUG)
        !          1166: #endif
        !          1167: 
        !          1168: 
        !          1169: 
        !          1170:                        b               chkvec                                          ; Go check out the vector facility...
        !          1171: 
        !          1172: chkfpfree:     li              r0,0                                            ; Clear a register
        !          1173:                        lwz             r24,ACT_MACT_FPU(r8)            ; Get the floating point save area
        !          1174:                        
        !          1175:                        bne-    cr1,chkfpnfr                            ; Not our facility, do not clear...
        !          1176:                        stw             r0,PP_FPU_THREAD(r10)           ; Clear floating point owner
        !          1177: chkfpnfr:
        !          1178: 
        !          1179: #if FPVECDBG
        !          1180:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1181:                        li              r2,0x3302                                       ; (TEST/DEBUG)
        !          1182:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1183:                        sc                                                                      ; (TEST/DEBUG)
        !          1184: #endif 
        !          1185: 
        !          1186:                        mr.             r24,r24                                         ; Do we even have a savearea?
        !          1187:                        beq+    chkvec                                          ; Nope...
        !          1188:                        
        !          1189: #if FPVECDBG
        !          1190:                        rlwinm. r0,r24,0,0,15                           ; (TEST/DEBUG)
        !          1191:                        bne+    notbadxxx1                                      ; (TEST/DEBUG)
        !          1192:                        BREAKPOINT_TRAP                                         ; (TEST/DEBUG)
        !          1193: notbadxxx1:                                                                            ; (TEST/DEBUG)                  
        !          1194:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1195:                        li              r2,0x3303                                       ; (TEST/DEBUG)
        !          1196:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1197:                        sc                                                                      ; (TEST/DEBUG)
        !          1198: #endif 
        !          1199: 
        !          1200:                        lwz             r25,SAVlvlfp(r24)                       ; Get the level of top savearea
        !          1201:                        cmplwi  r25,1                                           ; Is the top area invalid?
        !          1202:                        cmplw   cr1,r25,r3                                      ; Is it for the returned from context?
        !          1203:                        beq             fptoss                                          ; It is invalid...
        !          1204:                        bne             cr1,chkvec                                      ; Not for the returned context...
        !          1205:                        
        !          1206: fptoss:                lwz             r25,SAVprefp(r24)                       ; Get previous savearea
        !          1207: #if FPVECDBG
        !          1208:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1209:                        li              r2,0x3304                                       ; (TEST/DEBUG)
        !          1210:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1211:                        mr              r5,r25                                          ; (TEST/DEBUG)
        !          1212:                        sc                                                                      ; (TEST/DEBUG)
        !          1213: #endif 
        !          1214:                        mr.             r25,r25                                         ; Is there one?
        !          1215:                        stw             r25,ACT_MACT_FPU(r8)            ; Set the new pointer
        !          1216:                        beq             fptoplvl                                        ; Nope, we are at the top...
        !          1217: #if FPVECDBG           
        !          1218:                        rlwinm. r0,r25,0,0,15                           ; (TEST/DEBUG)
        !          1219:                        bne+    notbadxxx2                                      ; (TEST/DEBUG)
        !          1220:                        BREAKPOINT_TRAP                                         ; (TEST/DEBUG)
        !          1221: notbadxxx2:                                                                            ; (TEST/DEBUG)                  
        !          1222: #endif         
        !          1223:                        lwz             r25,SAVlvlfp(r25)                       ; Get the new level
        !          1224: 
        !          1225: fptoplvl:      lwz             r19,SAVflags(r24)                       ; Get the savearea flags
        !          1226: #if FPVECDBG
        !          1227:                        rlwinm. r0,r19,0,1,1                            ; (TEST/DEBUG)
        !          1228:                        bne+    donotdie3                                       ; (TEST/DEBUG)
        !          1229:                        BREAKPOINT_TRAP                                         ; (TEST/DEBUG)
        !          1230: donotdie3:                                                                             ; (TEST/DEBUG)
        !          1231: #endif
        !          1232: 
        !          1233: #if FPVECDBG
        !          1234:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1235:                        li              r2,0x3305                                       ; (TEST/DEBUG)
        !          1236:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1237:                        sc                                                                      ; (TEST/DEBUG)
        !          1238: #endif 
        !          1239:                        rlwinm  r22,r24,0,0,19                          ; Round down to the base savearea block
        !          1240:                        rlwinm  r19,r19,0,2,0                           ; Remove the floating point in use flag
        !          1241:                        stw             r25,ACT_MACT_FPUlvl(r8)         ; Set the new top level
        !          1242:                        andis.  r0,r19,hi16(SAVinuse)           ; Still in use?
        !          1243:                        stw             r19,SAVflags(r24)                       ; Set the savearea flags
        !          1244:                        bne-    chkvec                                          ; Yes, go check out vector...
        !          1245: #if FPVECDBG
        !          1246:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1247:                        li              r2,0x3306                                       ; (TEST/DEBUG)
        !          1248:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1249:                        sc                                                                      ; (TEST/DEBUG)
        !          1250: #endif 
        !          1251: #if FPVECDBG           
        !          1252:                        rlwinm. r0,r24,0,0,15                           ; (TEST/DEBUG)
        !          1253:                        bne+    notbadxxx3                                      ; (TEST/DEBUG)
        !          1254:                        BREAKPOINT_TRAP                                         ; (TEST/DEBUG)
        !          1255: notbadxxx3:                                                                            ; (TEST/DEBUG)                  
        !          1256: #endif         
        !          1257:                        lwz             r23,SACvrswap(r22)                      ; Get the conversion from virtual to real
        !          1258:                        lwz             r20,PP_QUICKFRET(r10)           ; Get the old quick fret head
        !          1259:                        xor             r23,r24,r23                                     ; Convert to physical
        !          1260:                        stw             r20,SAVqfret(r24)                       ; Back chain the quick release queue
        !          1261:                        stw             r23,PP_QUICKFRET(r10)           ; Anchor it
        !          1262: 
        !          1263: ;
        !          1264: ;                      Check out vector stuff (and translate savearea to physical for exit)
        !          1265: ;
        !          1266: chkvec:                
        !          1267:                        lwz             r20,ACT_MACT_VMXlvl(r8)         ; Get the vector level
        !          1268:                        lwz             r23,PP_VMX_THREAD(r10)          ; Get vector owner
        !          1269:                        cmplw   r20,r3                                          ; Are we returning from the active level?
        !          1270:                        rlwinm  r12,r12,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Turn off vector for now
        !          1271:                        cmplw   cr1,r23,r8                                      ; Are we the facility owner?
        !          1272:                        beq-    chkvecfree                                      ; Leaving active level, can not possibly enable...
        !          1273:                        bne-    cr1,setena                                      ; Not our facility, nothing to do here...
        !          1274: 
        !          1275: #if FPVECDBG
        !          1276:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1277:                        li              r2,0x3401                                       ; (TEST/DEBUG)
        !          1278:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1279:                        sc                                                                      ; (TEST/DEBUG)
        !          1280: #endif 
        !          1281: 
        !          1282:                        lwz             r24,ACT_MACT_VMXcpu(r8)         ; Get the CPU this context was enabled on last
        !          1283:                        cmplw   r4,r20                                          ; Are we going to be in the right level?
        !          1284:                        cmplw   cr1,r24,r26                                     ; Are we on the right CPU?
        !          1285:                        li              r0,0                                            ; Get a constant 0
        !          1286:                        beq+    cr1,chkvecnlvl                          ; Right CPU...
        !          1287:                        
        !          1288:                        stw             r0,PP_VMX_THREAD(r10)           ; Show facility unowned so we do not get back here
        !          1289:                        b               setena                                          ; Go actually exit...
        !          1290:                        
        !          1291: chkvecnlvl:    bne-    setena                                          ; Different level, can not enable...
        !          1292:                        lwz             r24,ACT_MACT_VMX(r8)            ; Get the vector save area
        !          1293:                        oris    r12,r12,hi16(MASK(MSR_VEC))     ; Enable facility
        !          1294:                        mr.             r24,r24                                         ; Does the savearea exist?
        !          1295:                        li              r0,1                                            ; Get set to invalidate
        !          1296:                        beq-    setena                                          ; Nothing to invalidate...
        !          1297:                        lwz             r25,SAVlvlvec(r24)                      ; Get the level of top savearea
        !          1298:                        cmplw   r4,r25                                          ; Is the top one ours?
        !          1299:                        bne+    setena                                          ; Not ours...
        !          1300:                        stw             r0,SAVlvlvec(r24)                       ; Invalidate the first one
        !          1301:                        b               setena                                          ; Actually exit...
        !          1302: 
        !          1303: chkvecfree:    li              r0,0                                            ; Clear a register
        !          1304:                        lwz             r24,ACT_MACT_VMX(r8)            ; Get the vector save area
        !          1305:                        bne-    cr1,chkvecnfr                           ; Not our facility, do not clear...
        !          1306:                        stw             r0,PP_VMX_THREAD(r10)           ; Clear vector owner
        !          1307: chkvecnfr:
        !          1308:                        
        !          1309: #if FPVECDBG
        !          1310:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1311:                        li              r2,0x3402                                       ; (TEST/DEBUG)
        !          1312:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1313:                        sc                                                                      ; (TEST/DEBUG)
        !          1314: #endif 
        !          1315: 
        !          1316:                        mr.             r24,r24                                         ; Do we even have a savearea?
        !          1317:                        beq+    setena                                          ; Nope...
        !          1318:                        
        !          1319: #if FPVECDBG
        !          1320:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1321:                        li              r2,0x3403                                       ; (TEST/DEBUG)
        !          1322:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1323:                        sc                                                                      ; (TEST/DEBUG)
        !          1324: #endif 
        !          1325:                        lwz             r25,SAVlvlvec(r24)                      ; Get the level
        !          1326:                        cmplwi  r25,1                                           ; Is the top area invalid?
        !          1327:                        cmplw   cr1,r25,r3                                      ; Is it for the returned from context?
        !          1328:                        beq             vectoss                                         ; It is invalid...
        !          1329:                        bne             cr1,setena                                      ; Not for the returned context...
        !          1330:                        
        !          1331: vectoss:       lwz             r25,SAVprevec(r24)                      ; Get previous savearea
        !          1332: #if FPVECDBG
        !          1333:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1334:                        li              r2,0x3504                                       ; (TEST/DEBUG)
        !          1335:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1336:                        mr              r5,r25                                          ; (TEST/DEBUG)
        !          1337:                        sc                                                                      ; (TEST/DEBUG)
        !          1338: #endif 
        !          1339:                        mr.             r25,r25                                         ; Is there one?
        !          1340:                        stw             r25,ACT_MACT_VMX(r8)            ; Set the new pointer
        !          1341:                        beq             vectoplvl                                       ; Nope, we are at the top...
        !          1342:                        lwz             r25,SAVlvlvec(r25)                      ; Get the new level
        !          1343: 
        !          1344: vectoplvl:     lwz             r19,SAVflags(r24)                       ; Get the savearea flags
        !          1345: 
        !          1346: #if FPVECDBG
        !          1347:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1348:                        li              r2,0x3405                                       ; (TEST/DEBUG)
        !          1349:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1350:                        sc                                                                      ; (TEST/DEBUG)
        !          1351: #endif 
        !          1352:                        rlwinm  r22,r24,0,0,19                          ; Round down to the base savearea block
        !          1353:                        rlwinm  r19,r19,0,3,1                           ; Remove the vector in use flag
        !          1354:                        stw             r25,ACT_MACT_VMXlvl(r8)         ; Set the new top level
        !          1355:                        andis.  r0,r19,hi16(SAVinuse)           ; Still in use?
        !          1356:                        stw             r19,SAVflags(r24)                       ; Set the savearea flags
        !          1357:                        bne-    setena                                          ; Yes, all done...
        !          1358: #if FPVECDBG
        !          1359:                        lis             r0,HIGH_ADDR(CutTrace)          ; (TEST/DEBUG)
        !          1360:                        li              r2,0x3406                                       ; (TEST/DEBUG)
        !          1361:                        oris    r0,r0,LOW_ADDR(CutTrace)        ; (TEST/DEBUG)
        !          1362:                        sc                                                                      ; (TEST/DEBUG)
        !          1363: #endif                 
        !          1364:                        lwz             r23,SACvrswap(r22)                      ; Get the conversion from virtual to real
        !          1365:                        lwz             r20,PP_QUICKFRET(r10)           ; Get the old quick fret head
        !          1366:                        xor             r23,r24,r23                                     ; Convert to physical
        !          1367:                        stw             r20,SAVqfret(r24)                       ; Back chain the quick release queue
        !          1368:                        stw             r23,PP_QUICKFRET(r10)           ; Anchor it
        !          1369: 
        !          1370: setena:                stw             r12,savesrr1(r3)                        ; Turn facility on or off
        !          1371:        
        !          1372: chkenax:       lwz             r6,SAVflags(r3)                         ; Pick up the flags of the old savearea
        !          1373: 
        !          1374:        
        !          1375: #if DEBUG
        !          1376:                        lwz             r20,SAVact(r3)                          ; (TEST/DEBUG) Make sure our restore
        !          1377:                        lwz             r21,PP_CPU_DATA(r10)            ; (TEST/DEBUG)         context is associated
        !          1378:                        lwz             r21,CPU_ACTIVE_THREAD(r21)      ; (TEST/DEBUG)         with the current act.
        !          1379:                        cmpwi   r21,0                                           ; (TEST/DEBUG)
        !          1380:                        beq-    yeswereok                                       ; (TEST/DEBUG)
        !          1381:                        lwz             r21,THREAD_TOP_ACT(r21)         ; (TEST/DEBUG)
        !          1382:                        cmplw   r21,r20                                         ; (TEST/DEBUG)
        !          1383:                        beq+    yeswereok                                       ; (TEST/DEBUG)
        !          1384:                        BREAKPOINT_TRAP                                         ; (TEST/DEBUG)
        !          1385: 
        !          1386: yeswereok:
        !          1387: #endif
        !          1388:        
        !          1389:                        rlwinm  r5,r3,0,0,19                            ; Round savearea down to page bndry
        !          1390:                        rlwinm  r6,r6,0,1,31                            ; Mark savearea free
        !          1391:                        lwz             r5,SACvrswap(r5)                        ; Get the conversion from virtual to real
        !          1392:                        stw             r6,SAVflags(r3)                         ; Set savearea flags
        !          1393:                        xor             r3,r3,r5                                        ; Flip to physical address
        !          1394:                        b               EXT(exception_exit)                     ; We are all done now...
        !          1395: 
        !          1396: 
        !          1397: 
        !          1398: /*
        !          1399:  *                     Here's where we handle the fastpath stuff
        !          1400:  *                     We'll do what we can here because registers are already
        !          1401:  *                     loaded and it will be less confusing that moving them around.
        !          1402:  *                     If we need to though, we'll branch off somewhere's else.
        !          1403:  *
        !          1404:  *                     Registers when we get here:
        !          1405:  *
        !          1406:  *                             r0  = syscall number
        !          1407:  *                             r4  = savearea/pcb
        !          1408:  *                             r13 = activation
        !          1409:  *                             r14 = previous savearea (if any)
        !          1410:  *                             r16 = thread
        !          1411:  *                             r25 = per_proc
        !          1412:  */
        !          1413: 
        !          1414: fastpath:      cmplwi  cr3,r0,0x7FF1                           ; Is it CthreadSetSelfNumber?   
        !          1415:                        bnelr-  cr3                                                     ; Not a fast path...
        !          1416: 
        !          1417: /*
        !          1418:  * void cthread_set_self(cproc_t p)
        !          1419:  *
        !          1420:  * set's thread state "user_value"
        !          1421:  *
        !          1422:  * This op is invoked as follows:
        !          1423:  *     li r0, CthreadSetSelfNumber     // load the fast-trap number
        !          1424:  *     sc                              // invoke fast-trap
        !          1425:  *     blr
        !          1426:  *
        !          1427:  */
        !          1428: 
        !          1429: CthreadSetSelfNumber:
        !          1430: 
        !          1431:                        lwz             r5,saver3(r4)                           /* Retrieve the self number */
        !          1432:                        stw             r5,CTHREAD_SELF(r13)            /* Remember it */
        !          1433:                        stw             r5,UAW(r25)                                     /* Prime the per_proc_info with it */
        !          1434: 
        !          1435: 
        !          1436:                        .globl  EXT(fastexit)
        !          1437: EXT(fastexit):
        !          1438:                        lwz             r8,SAVflags(r4)                         /* Pick up the flags */
        !          1439:                        rlwinm  r9,r4,0,0,19                            /* Round down to the base savearea block */
        !          1440:                        rlwinm  r8,r8,0,1,31                            /* Clear the attached bit */
        !          1441:                        lwz             r9,SACvrswap(r9)                        /* Get the conversion from virtual to real */
        !          1442:                        stw             r8,SAVflags(r4)                         /* Set the flags */
        !          1443:                        xor             r3,r4,r9                                        /* Switch savearea to physical addressing */
        !          1444:                        b               EXT(exception_exit)                     /* Go back to the caller... */
        !          1445: 
        !          1446: 
        !          1447: /*
        !          1448:  *                     Here's where we check for a hit on the Blue Box Assist
        !          1449:  *                     Most registers are non-volatile, so be careful here. If we don't 
        !          1450:  *                     recognize the trap instruction we go back for regular processing.
        !          1451:  *                     Otherwise we transfer to the assist code.
        !          1452:  */
        !          1453:  
        !          1454: checkassist:
        !          1455:                        lwz             r23,savesrr1(r4)                        /* Get the interrupted MSR */
        !          1456:                        lwz             r24,ACT_MACT_BTS(r9)            /* Get the table start */
        !          1457:                        rlwinm. r23,r23,0,MSR_PR_BIT,MSR_PR_BIT /* Are we in userland? */
        !          1458:                        lwz             r27,savesrr0(r4)                        /* Get trapped address */
        !          1459:                        beqlr-                                                          /* No assist in kernel mode... */
        !          1460: 
        !          1461: checkassistBP:                                                                 /* Safe place to breakpoint */
        !          1462: 
        !          1463:                        sub             r24,r27,r24                                     /* See how far into it we are */
        !          1464:                        rlwinm  r24,r24,PKTDSHIFT,0,27          /* Get displacement to control block */
        !          1465:                        cmplwi  r24,BBMAXTRAP*PKTDSIZE          /* Do we fit in the list? */
        !          1466:                        bgtlr-                                                          /* Nope, it's a regular trap... */
        !          1467:                        b               EXT(atomic_switch_trap)         /* Go to the assist... */
        !          1468: 
        !          1469: #if    MACH_KDB
        !          1470: /*
        !          1471:  *                     Here's where we jump into the debugger.  This is called from
        !          1472:  *                     either an MP signal from another processor, or a command-power NMI
        !          1473:  *                     on the main processor.
        !          1474:  *
        !          1475:  *                     Note that somewhere in our stack should be a return into the interrupt
        !          1476:  *                     handler.  If there isn't, we'll crash off the end of the stack, actually,
        !          1477:  *                     it'll just quietly return. hahahahaha.
        !          1478:  */
        !          1479: 
        !          1480: ENTRY(kdb_kintr, TAG_NO_FRAME_USED)
        !          1481:        
        !          1482:                        lis             r9,HIGH_ADDR(EXT(ihandler_ret)) /* Top part of interrupt return */
        !          1483:                        lis             r10,HIGH_ADDR(EXT(intercept_ret))       /* Top part of intercept return */
        !          1484:                        ori             r9,r9,LOW_ADDR(EXT(ihandler_ret))       /* Bottom part of interrupt return */
        !          1485:                        ori             r10,r10,LOW_ADDR(EXT(intercept_ret))    /* Bottom part of intercept return */
        !          1486:                        
        !          1487:                        lwz             r8,0(r1)                                /* Get our caller's stack frame */
        !          1488: 
        !          1489: srchrets:      mr.             r8,r8                                   /* Have we reached the end of our rope? */
        !          1490:                        beqlr-                                                  /* Yeah, just bail... */
        !          1491:                        lwz             r7,FM_LR_SAVE(r8)               /* The whoever called them */
        !          1492:                        cmplw   cr0,r9,r7                               /* Was it the interrupt handler? */
        !          1493:                        beq             srchfnd                                 /* Yeah... */
        !          1494:                        lwz             r8,0(r8)                                /* Chain back to the previous frame */
        !          1495:                        b               srchrets                                /* Ok, check again... */
        !          1496:                        
        !          1497: srchfnd:       stw             r10,FM_LR_SAVE(r8)              /* Modify return to come to us instead */
        !          1498:                        blr                                                             /* Finish up and get back here... */
        !          1499:                        
        !          1500: /*
        !          1501:  *                     We come here when we've returned all the way to the interrupt handler.
        !          1502:  *                     That way we can enter the debugger with the registers and stack which
        !          1503:  *                     existed at the point of interruption.
        !          1504:  *
        !          1505:  *                     R3 points to the saved state at entry
        !          1506:  */
        !          1507:  
        !          1508:  ENTRY(intercept_ret, TAG_NO_FRAME_USED)
        !          1509: 
        !          1510:                        lis             r6,HIGH_ADDR(EXT(kdb_trap))     /* Get the top part of the KDB enter routine */
        !          1511:                        mr              r5,r3                                   /* Move saved state to the correct parameter */
        !          1512:                        ori             r6,r6,LOW_ADDR(EXT(kdb_trap))   /* Get the last part of the KDB enter routine */
        !          1513:                        li              r4,0                                    /* Set a code of 0 */
        !          1514:                        mr              r13,r3                                  /* Save the saved state pointer in a non-volatile */
        !          1515:                        mtlr    r6                                              /* Set the routine address */
        !          1516:                        li              r3,-1                                   /* Show we had an interrupt type */
        !          1517:        
        !          1518:                        blrl                                                    /* Go enter KDB */
        !          1519: 
        !          1520:                        mr              r3,r13                                  /* Put the saved state where expected */
        !          1521:                        b               EXT(ihandler_ret)               /* Go return from the interruption... */
        !          1522: 
        !          1523: #endif                 
        !          1524: 
        !          1525: #if VERIFYSAVE                 
        !          1526: ;
        !          1527: ;                      Savearea chain verification
        !          1528: ;
        !          1529:                
        !          1530: versave:       
        !          1531: 
        !          1532: #if 0
        !          1533: ;
        !          1534: ;                      Make sure that only the top FPU savearea is marked invalid
        !          1535: ;
        !          1536: 
        !          1537:                        lis             r28,hi16(EXT(default_pset))             ; (TEST/DEBUG)
        !          1538:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1539:                        ori             r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG)
        !          1540:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1541:                        li              r20,0                                                   ; (TEST/DEBUG)
        !          1542:                        lwz             r26,0(r27)                                              ; (TEST/DEBUG)
        !          1543:                        lwz             r27,psthreadcnt(r28)                    ; (TEST/DEBUG)
        !          1544:                        mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1545:                        lwz             r28,psthreads(r28)                              ; (TEST/DEBUG)
        !          1546:                        bnelr-                                                                  ; (TEST/DEBUG)
        !          1547:                        
        !          1548: fcknxtth:      mr.             r27,r27                                                 ; (TEST/DEBUG)
        !          1549:                        beqlr-                                                                  ; (TEST/DEBUG)
        !          1550:                        
        !          1551:                        lwz             r26,THREAD_TOP_ACT(r28)                 ; (TEST/DEBUG)
        !          1552: 
        !          1553: fckact:                mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1554:                        bne+    fckact2                                                 ; (TEST/DEBUG)
        !          1555:                        
        !          1556:                        lwz             r28,THREAD_PSTHRN(r28)                  ; (TEST/DEBUG) Next in line
        !          1557:                        subi    r27,r27,1                                               ; (TEST/DEBUG)
        !          1558:                        b               fcknxtth                                                ; (TEST/DEBUG) 
        !          1559:        
        !          1560: fckact2:       lwz             r20,ACT_MACT_FPU(r26)                   ; (TEST/DEBUG) Get FPU chain
        !          1561:                        mr.             r20,r20                                                 ; (TEST/DEBUG) Are there any?
        !          1562:                        beq+    fcknact                                                 ; (TEST/DEBUG) No...
        !          1563:                        
        !          1564: fckact3:       lwz             r20,SAVprefp(r20)                               ; (TEST/DEBUG) Get next in list
        !          1565:                        mr.             r20,r20                                                 ; (TEST/DEBUG) Check next savearea
        !          1566:                        beq+    fcknact                                                 ; (TEST/DEBUG) No...
        !          1567:                        
        !          1568:                        lwz             r29,SAVlvlfp(r20)                               ; (TEST/DEBUG) Get the level
        !          1569: 
        !          1570:                        cmplwi  r29,1                                                   ; (TEST/DEBUG) Is it invalid??
        !          1571:                        bne+    fckact3                                                 ; (TEST/DEBUG) Nope...
        !          1572:                        
        !          1573:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1574:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1575:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1576:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG)
        !          1577: 
        !          1578: fcknact:       lwz             r26,ACT_LOWER(r26)                              ; (TEST/DEBUG) Next activation
        !          1579:                        b               fckact                                                  ; (TEST/DEBUG)
        !          1580: #endif
        !          1581: 
        !          1582: #if 1
        !          1583: ;
        !          1584: ;                      Make sure there are no circular links in the float chain
        !          1585: ;                      And that FP is marked busy in it.
        !          1586: ;                      And the only the top is marked invalid.
        !          1587: ;                      And that the owning PCB is correct.
        !          1588: ;
        !          1589: 
        !          1590:                        lis             r28,hi16(EXT(default_pset))             ; (TEST/DEBUG)
        !          1591:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1592:                        ori             r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG)
        !          1593:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1594:                        li              r20,0                                                   ; (TEST/DEBUG)
        !          1595:                        lwz             r26,0(r27)                                              ; (TEST/DEBUG)
        !          1596:                        lwz             r27,psthreadcnt(r28)                    ; (TEST/DEBUG)
        !          1597:                        mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1598:                        lwz             r28,psthreads(r28)                              ; (TEST/DEBUG)
        !          1599:                        bnelr-                                                                  ; (TEST/DEBUG)
        !          1600:                        
        !          1601: fcknxtth:      mr.             r27,r27                                                 ; (TEST/DEBUG)
        !          1602:                        beqlr-                                                                  ; (TEST/DEBUG)
        !          1603:                        
        !          1604:                        lwz             r26,THREAD_TOP_ACT(r28)                 ; (TEST/DEBUG)
        !          1605: 
        !          1606: fckact:                mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1607:                        bne+    fckact2                                                 ; (TEST/DEBUG)
        !          1608:                        
        !          1609:                        lwz             r28,THREAD_PSTHRN(r28)                  ; (TEST/DEBUG) Next in line
        !          1610:                        subi    r27,r27,1                                               ; (TEST/DEBUG)
        !          1611:                        b               fcknxtth                                                ; (TEST/DEBUG) 
        !          1612:        
        !          1613: fckact2:       lwz             r20,ACT_MACT_FPU(r26)                   ; (TEST/DEBUG) Get FPU chain
        !          1614:                        li              r29,1                                                   ; (TEST/DEBUG)
        !          1615:                        li              r22,0                                                   ; (TEST/DEBUG)
        !          1616: 
        !          1617: fckact3:       mr.             r20,r20                                                 ; (TEST/DEBUG) Are there any?
        !          1618:                        beq+    fckact5                                                 ; (TEST/DEBUG) No...
        !          1619:                        
        !          1620:                        addi    r22,r22,1                                               ; (TEST/DEBUG) Count chain depth
        !          1621:                        
        !          1622:                        lwz             r21,SAVflags(r20)                               ; (TEST/DEBUG) Get the flags
        !          1623:                        rlwinm. r21,r21,0,1,1                                   ; (TEST/DEBUG) FP busy?
        !          1624:                        bne+    fckact3a                                                ; (TEST/DEBUG) Yeah...
        !          1625:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1626:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1627:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1628:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG) Die
        !          1629:                        
        !          1630: fckact3a:      cmplwi  r22,1                                                   ; (TEST/DEBUG) At first SA?
        !          1631:                        beq+    fckact3b                                                ; (TEST/DEBUG) Yeah, invalid is ok...
        !          1632:                        lwz             r21,SAVlvlfp(r20)                               ; (TEST/DEBUG) Get level
        !          1633:                        cmplwi  r21,1                                                   ; (TEST/DEBUG) Is it invalid?
        !          1634:                        bne+    fckact3b                                                ; (TEST/DEBUG) Nope, it is ok...
        !          1635:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1636:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1637:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1638:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG) Die
        !          1639:                        
        !          1640: fckact3b:      lwz             r21,SAVact(r20)                                 ; (TEST/DEBUG) Get the owner
        !          1641:                        cmplw   r21,r26                                                 ; (TEST/DEBUG) Correct activation?
        !          1642:                        beq+    fckact3c                                                ; (TEST/DEBUG) Yup...
        !          1643:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1644:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1645:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1646:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG) Die
        !          1647: 
        !          1648: fckact3c:                                                                                      ; (TEST/DEBUG)
        !          1649:                        lbz             r21,SAVflags+3(r20)                             ; (TEST/DEBUG) Pick up the test byte
        !          1650:                        mr.             r21,r21                                                 ; (TEST/DEBUG) marked?
        !          1651:                        beq+    fckact4                                                 ; (TEST/DEBUG) No, good...
        !          1652:                        
        !          1653:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1654:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1655:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1656:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG)
        !          1657:                        
        !          1658: fckact4:       stb             r29,SAVflags+3(r20)                             ; (TEST/DEBUG) Set the test byte
        !          1659:                        lwz             r20,SAVprefp(r20)                               ; (TEST/DEBUG) Next in list
        !          1660:                        b               fckact3                                                 ; (TEST/DEBUG) Try it...
        !          1661: 
        !          1662: fckact5:       lwz             r20,ACT_MACT_FPU(r26)                   ; (TEST/DEBUG) Get FPU chain
        !          1663:                        li              r29,0                                                   ; (TEST/DEBUG)
        !          1664: 
        !          1665: fckact6:       mr.             r20,r20                                                 ; (TEST/DEBUG) Are there any?
        !          1666:                        beq+    fcknact                                                 ; (TEST/DEBUG) No...
        !          1667:                        
        !          1668:                        stb             r29,SAVflags+3(r20)                             ; (TEST/DEBUG) Clear the test byte
        !          1669:                        lwz             r20,SAVprefp(r20)                               ; (TEST/DEBUG) Next in list
        !          1670:                        b               fckact6                                                 ; (TEST/DEBUG) Try it...
        !          1671:                        
        !          1672: fcknact:       lwz             r26,ACT_LOWER(r26)                              ; (TEST/DEBUG) Next activation
        !          1673:                        b               fckact                                                  ; (TEST/DEBUG)
        !          1674: #endif
        !          1675: 
        !          1676: 
        !          1677: #if 0
        !          1678: ;
        !          1679: ;                      Make sure in use count matches found savearea.  This is
        !          1680: ;                      not always accurate.  There is a variable "fuzz" factor in count.
        !          1681: 
        !          1682:                        lis             r28,hi16(EXT(default_pset))             ; (TEST/DEBUG)
        !          1683:                        lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1684:                        ori             r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG)
        !          1685:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1686:                        li              r20,0                                                   ; (TEST/DEBUG)
        !          1687:                        lwz             r26,0(r27)                                              ; (TEST/DEBUG)
        !          1688:                        lwz             r27,psthreadcnt(r28)                    ; (TEST/DEBUG)
        !          1689:                        mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1690:                        lwz             r28,psthreads(r28)                              ; (TEST/DEBUG)
        !          1691:                        bnelr-                                                                  ; (TEST/DEBUG)
        !          1692:                        
        !          1693: cknxtth:       mr.             r27,r27                                                 ; (TEST/DEBUG)
        !          1694:                        beq-    cktotal                                                 ; (TEST/DEBUG)
        !          1695:                        
        !          1696:                        lwz             r26,THREAD_TOP_ACT(r28)                 ; (TEST/DEBUG)
        !          1697: 
        !          1698: ckact:         mr.             r26,r26                                                 ; (TEST/DEBUG)
        !          1699:                        bne+    ckact2                                                  ; (TEST/DEBUG)
        !          1700:                        
        !          1701:                        lwz             r28,THREAD_PSTHRN(r28)                  ; (TEST/DEBUG) Next in line
        !          1702:                        subi    r27,r27,1                                               ; (TEST/DEBUG)
        !          1703:                        b               cknxtth                                                 ; (TEST/DEBUG) 
        !          1704:                        
        !          1705: ckact2:                lwz             r29,ACT_MACT_PCB(r26)                   ; (TEST/DEBUG)
        !          1706:                        
        !          1707: cknorm:                mr.             r29,r29                                                 ; (TEST/DEBUG)
        !          1708:                        beq-    cknormd                                                 ; (TEST/DEBUG)
        !          1709:                        
        !          1710:                        addi    r20,r20,1                                               ; (TEST/DEBUG) Count normal savearea
        !          1711:                        
        !          1712:                        lwz             r29,SAVprev(r29)                                ; (TEST/DEBUG)
        !          1713:                        b               cknorm                                                  ; (TEST/DEBUG)
        !          1714:                        
        !          1715: cknormd:       lwz             r29,ACT_MACT_FPU(r26)                   ; (TEST/DEBUG)
        !          1716: 
        !          1717: ckfpu:         mr.             r29,r29                                                 ; (TEST/DEBUG)
        !          1718:                        beq-    ckfpud                                                  ; (TEST/DEBUG)
        !          1719:                        
        !          1720:                        lwz             r21,SAVflags(r29)                               ; (TEST/DEBUG)
        !          1721:                        rlwinm. r21,r21,0,0,0                                   ; (TEST/DEBUG) See if already counted
        !          1722:                        bne-    cknfpu                                                  ; (TEST/DEBUG)
        !          1723:                        
        !          1724:                        addi    r20,r20,1                                               ; (TEST/DEBUG) Count fpu savearea
        !          1725:                        
        !          1726: cknfpu:                lwz             r29,SAVprefp(r29)                               ; (TEST/DEBUG)
        !          1727:                        b               ckfpu                                                   ; (TEST/DEBUG)
        !          1728:                        
        !          1729: ckfpud:                lwz             r29,ACT_MACT_VMX(r26)                   ; (TEST/DEBUG)
        !          1730: 
        !          1731: ckvmx:         mr.             r29,r29                                                 ; (TEST/DEBUG)
        !          1732:                        beq-    ckvmxd                                                  ; (TEST/DEBUG)
        !          1733:                        
        !          1734:                        lwz             r21,SAVflags(r29)                               ; (TEST/DEBUG)
        !          1735:                        rlwinm. r21,r21,0,0,1                                   ; (TEST/DEBUG) See if already counted
        !          1736:                        bne-    cknvmx                                                  ; (TEST/DEBUG)
        !          1737:                        
        !          1738:                        addi    r20,r20,1                                               ; (TEST/DEBUG) Count vector savearea
        !          1739:                        
        !          1740: cknvmx:                lwz             r29,SAVprevec(r29)                              ; (TEST/DEBUG)
        !          1741:                        b               ckvmx                                                   ; (TEST/DEBUG)
        !          1742:                        
        !          1743: ckvmxd:                lwz             r26,ACT_LOWER(r26)                              ; (TEST/DEBUG) Next activation
        !          1744:                        b               ckact                                                   ; (TEST/DEBUG)
        !          1745: 
        !          1746: cktotal:       lis             r28,hi16(EXT(saveanchor))               ; (TEST/DEBUG)
        !          1747:                        lis             r27,hi16(EXT(real_ncpus))               ; (TEST/DEBUG)
        !          1748:                        ori             r28,r28,lo16(EXT(saveanchor))   ; (TEST/DEBUG)
        !          1749:                        ori             r27,r27,lo16(EXT(real_ncpus))   ; (TEST/DEBUG)
        !          1750: 
        !          1751:                        lwz             r21,SVinuse(r28)                                ; (TEST/DEBUG)
        !          1752:                        lwz             r27,0(r27)                                              ; (TEST/DEBUG) Get the number of CPUs
        !          1753:                        sub.    r29,r21,r20                                             ; (TEST/DEBUG) Get number accounted for
        !          1754:                        blt-    badsave                                                 ; (TEST/DEBUG) Have too many in use...
        !          1755:                        sub             r26,r29,r27                                             ; (TEST/DEBUG) Should be 1 unaccounted for for each processor
        !          1756:                        cmpwi   r26,10                                                  ; (TEST/DEBUG) Allow a 10 area slop factor
        !          1757:                        bltlr+                                                                  ; (TEST/DEBUG)
        !          1758:                        
        !          1759: badsave:       lis             r27,hi16(EXT(DebugWork))                ; (TEST/DEBUG)
        !          1760:                        ori             r27,r27,lo16(EXT(DebugWork))    ; (TEST/DEBUG)
        !          1761:                        stw             r27,0(r27)                                              ; (TEST/DEBUG)
        !          1762:                        BREAKPOINT_TRAP                                                 ; (TEST/DEBUG)
        !          1763: #endif
        !          1764: #endif 

unix.superglobalmegacorp.com

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