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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: 
                     26: /* 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.