|
|
xnu-68.4-1.1
/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ /* * Low-memory exception vector code for PowerPC MACH * * These are the only routines that are ever run with * VM instruction translation switched off. * * The PowerPC is quite strange in that rather than having a set * of exception vectors, the exception handlers are installed * in well-known addresses in low memory. This code must be loaded * at ZERO in physical memory. The simplest way of doing this is * to load the kernel at zero, and specify this as the first file * on the linker command line. * * When this code is loaded into place, it is loaded at virtual * address KERNELBASE, which is mapped to zero (physical). * * This code handles all powerpc exceptions and is always entered * in supervisor mode with translation off. It saves the minimum * processor state before switching back on translation and * jumping to the approprate routine. * * Vectors from 0x100 to 0x3fff occupy 0x100 bytes each (64 instructions) * * We use some of this space to decide which stack to use, and where to * save the context etc, before jumping to a generic handler. */ #include <assym.s> #include <debug.h> #include <cpus.h> #include <db_machine_commands.h> #include <mach_rt.h> #include <mach_debug.h> #include <ppc/asm.h> #include <ppc/proc_reg.h> #include <ppc/exception.h> #include <ppc/Performance.h> #include <mach/ppc/vm_param.h> #include <ppc/POWERMAC/mp/MPPlugIn.h> #define RUPTTRC 0 #define CHECKSAVE 0 #define PERFTIMES 0 #define ESPDEBUG 0 #define VECTOR_SEGMENT .section __VECTORS, __interrupts VECTOR_SEGMENT .globl EXT(ExceptionVectorsStart) EXT(ExceptionVectorsStart): /* Used if relocating the exception vectors */ baseR: /* Used so we have more readable code */ /* * System reset - call debugger */ . = 0xf0 .globl EXT(ResetHandler) EXT(ResetHandler): .long 0x0 .long 0x0 .long 0x0 . = 0x100 .L_handler100: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ lwz r13,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Get reset type mfcr r11 cmpi cr0,r13,RESET_HANDLER_START bne resetexc li r11,RESET_HANDLER_NULL stw r11,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_TYPE)(br0) ; Clear reset type lwz r4,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_CALL)(br0) lwz r3,lo16(EXT(ResetHandler)-EXT(ExceptionVectorsStart)+RESETHANDLER_ARG)(br0) mtlr r4 blr resetexc: mtcr r11 mfsprg r13,1 /* Get the exception save area */ li r11,T_RESET /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * This is the data used by the exception trace code */ . = 0x180 .L_TraceData: .globl traceMask traceMask: /* Allowable trace types indexed by vector >> 8 */ #if DEBUG /* .long 0x02000000 */ /* Only alignment exceptions enabled */ .long 0xFFFFFFFF /* All enabled */ /* .long 0xFBBFFFFF */ /* EXT and DEC disabled */ /* .long 0xFFBFFFFF */ /* DEC disabled */ #else .long 0x00000000 ; All disabled on non-debug systems #endif .globl EXT(traceCurr) EXT(traceCurr): .long traceTableBeg-EXT(ExceptionVectorsStart) /* The next trace entry to use */ .globl EXT(traceStart) EXT(traceStart): .long traceTableBeg-EXT(ExceptionVectorsStart) /* Start of the trace table */ .globl EXT(traceEnd) EXT(traceEnd): .long traceTableEnd-EXT(ExceptionVectorsStart) /* End (wrap point) of the trace */ .globl traceMsnd traceMsnd: .long 0 /* Saved mask while in debugger */ /* * Machine check (physical bus error) - call debugger */ . = 0x200 .L_handler200: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_MACHINE_CHECK /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Data access - page fault, invalid memory rights for operation */ . = 0x300 .L_handler300: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_DATA_ACCESS /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Instruction access - as for data access */ . = 0x400 .L_handler400: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_INSTRUCTION_ACCESS /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * External interrupt */ . = 0x500 .L_handler500: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_INTERRUPT /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Alignment - many reasons */ . = 0x600 .L_handler600: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_ALIGNMENT /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Program - floating point exception, illegal inst, priv inst, user trap */ . = 0x700 .L_handler700: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_PROGRAM /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Floating point disabled */ . = 0x800 .L_handler800: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_FP_UNAVAILABLE /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Decrementer - DEC register has passed zero. */ . = 0x900 .L_handler900: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_DECREMENTER /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * I/O controller interface error - MACH does not use this */ . = 0xA00 .L_handlerA00: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_IO_ERROR /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Reserved */ . = 0xB00 .L_handlerB00: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_RESERVED /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * System call - generated by the sc instruction */ . = 0xC00 .L_handlerC00: cmplwi r0,0x7FF2 ; Ultra fast path cthread info call? blt+ notufp ; Not ultra fast... cmplwi r0,0x7FF3 ; Ultra fast path fp/vec facility state? bgt+ notufp ; Not ultra fast... mfsprg r3,0 ; Get the per_proc_area beq- isvecfp ; This is the facility stat call lwz r3,UAW(r3) ; Get the assist word rfi ; All done, scream back... (no need to restore CR or R11, they are volatile) ; isvecfp: lwz r3,spcFlags(r3) ; Get the facility status rfi ; Bail back... ; .align 5 notufp: mtsprg 3,r11 /* Save R11 */ mtsprg 2,r13 /* Save R13 */ li r11,T_SYSTEM_CALL /* Set 'rupt code */ mfsprg r13,1 /* Get the exception save area */ b .L_exception_entry /* Join common... */ /* * Trace - generated by single stepping */ . = 0xD00 .L_handlerD00: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_TRACE /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Floating point assist */ . = 0xe00 .L_handlerE00: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_FP_ASSIST /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Performance monitor interruption */ . = 0xF00 PMIhandler: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_PERF_MON /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * VMX exception */ . = 0xF20 VMXhandler: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_VMX /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * Instruction translation miss - we inline this code. * Upon entry (done for us by the machine): * srr0 : addr of instruction that missed * srr1 : bits 0-3 = saved CR0 * 4 = lru way bit * 16-31 = saved msr * msr[tgpr] = 1 (so gpr0-3 become our temporary variables) * imiss: ea that missed * icmp : the compare value for the va that missed * hash1: pointer to first hash pteg * hash2: pointer to 2nd hash pteg * * Register usage: * tmp0: saved counter * tmp1: junk * tmp2: pointer to pteg * tmp3: current compare value * * This code is taken from the 603e User's Manual with * some bugfixes and minor improvements to save bytes and cycles */ . = 0x1000 .L_handler1000: mfspr tmp2, hash1 mfctr tmp0 /* use tmp0 to save ctr */ mfspr tmp3, icmp .L_imiss_find_pte_in_pteg: li tmp1, 8 /* count */ subi tmp2, tmp2, 8 /* offset for lwzu */ mtctr tmp1 /* count... */ .L_imiss_pteg_loop: lwz tmp1, 8(tmp2) /* check pte0 for match... */ addi tmp2, tmp2, 8 cmpw cr0, tmp1, tmp3 #if 0 bdnzf+ cr0, .L_imiss_pteg_loop #else bc 0,2, .L_imiss_pteg_loop #endif beq+ cr0, .L_imiss_found_pte /* Not found in PTEG, we must scan 2nd then give up */ andi. tmp1, tmp3, MASK(PTE0_HASH_ID) bne- .L_imiss_do_no_hash_exception /* give up */ mfspr tmp2, hash2 ori tmp3, tmp3, MASK(PTE0_HASH_ID) b .L_imiss_find_pte_in_pteg .L_imiss_found_pte: lwz tmp1, 4(tmp2) /* get pte1_t */ andi. tmp3, tmp1, MASK(PTE1_WIMG_GUARD) /* Fault? */ bne- .L_imiss_do_prot_exception /* Guarded - illegal */ /* Ok, we've found what we need to, restore and rfi! */ mtctr tmp0 /* restore ctr */ mfsrr1 tmp3 mfspr tmp0, imiss mtcrf 0x80, tmp3 /* Restore CR0 */ mtspr rpa, tmp1 /* set the pte */ ori tmp1, tmp1, MASK(PTE1_REFERENCED) /* set referenced */ tlbli tmp0 sth tmp1, 6(tmp2) rfi .L_imiss_do_prot_exception: /* set up srr1 to indicate protection exception... */ mfsrr1 tmp3 andi. tmp2, tmp3, 0xffff addis tmp2, tmp2, MASK(SRR1_TRANS_PROT) >> 16 b .L_imiss_do_exception .L_imiss_do_no_hash_exception: /* clean up registers for protection exception... */ mfsrr1 tmp3 andi. tmp2, tmp3, 0xffff addis tmp2, tmp2, MASK(SRR1_TRANS_HASH) >> 16 /* And the entry into the usual instruction fault handler ... */ .L_imiss_do_exception: mtctr tmp0 /* Restore ctr */ mtsrr1 tmp2 /* Set up srr1 */ mfmsr tmp0 xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */ mtcrf 0x80, tmp3 /* Restore CR0 */ mtmsr tmp0 /* reset MSR[TGPR] */ b .L_handler400 /* Instr Access */ /* * Data load translation miss * * Upon entry (done for us by the machine): * srr0 : addr of instruction that missed * srr1 : bits 0-3 = saved CR0 * 4 = lru way bit * 5 = 1 if store * 16-31 = saved msr * msr[tgpr] = 1 (so gpr0-3 become our temporary variables) * dmiss: ea that missed * dcmp : the compare value for the va that missed * hash1: pointer to first hash pteg * hash2: pointer to 2nd hash pteg * * Register usage: * tmp0: saved counter * tmp1: junk * tmp2: pointer to pteg * tmp3: current compare value * * This code is taken from the 603e User's Manual with * some bugfixes and minor improvements to save bytes and cycles */ . = 0x1100 .L_handler1100: mfspr tmp2, hash1 mfctr tmp0 /* use tmp0 to save ctr */ mfspr tmp3, dcmp .L_dlmiss_find_pte_in_pteg: li tmp1, 8 /* count */ subi tmp2, tmp2, 8 /* offset for lwzu */ mtctr tmp1 /* count... */ .L_dlmiss_pteg_loop: lwz tmp1, 8(tmp2) /* check pte0 for match... */ addi tmp2, tmp2, 8 cmpw cr0, tmp1, tmp3 #if 0 /* How to write this correctly? */ bdnzf+ cr0, .L_dlmiss_pteg_loop #else bc 0,2, .L_dlmiss_pteg_loop #endif beq+ cr0, .L_dmiss_found_pte /* Not found in PTEG, we must scan 2nd then give up */ andi. tmp1, tmp3, MASK(PTE0_HASH_ID) /* already at 2nd? */ bne- .L_dmiss_do_no_hash_exception /* give up */ mfspr tmp2, hash2 ori tmp3, tmp3, MASK(PTE0_HASH_ID) b .L_dlmiss_find_pte_in_pteg .L_dmiss_found_pte: lwz tmp1, 4(tmp2) /* get pte1_t */ /* Ok, we've found what we need to, restore and rfi! */ mtctr tmp0 /* restore ctr */ mfsrr1 tmp3 mfspr tmp0, dmiss mtcrf 0x80, tmp3 /* Restore CR0 */ mtspr rpa, tmp1 /* set the pte */ ori tmp1, tmp1, MASK(PTE1_REFERENCED) /* set referenced */ tlbld tmp0 /* load up tlb */ sth tmp1, 6(tmp2) /* sth is faster? */ rfi /* This code is shared with data store translation miss */ .L_dmiss_do_no_hash_exception: /* clean up registers for protection exception... */ mfsrr1 tmp3 /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */ rlwinm tmp1, tmp3, 9, 6, 6 addis tmp1, tmp1, MASK(DSISR_HASH) >> 16 /* And the entry into the usual data fault handler ... */ mtctr tmp0 /* Restore ctr */ andi. tmp2, tmp3, 0xffff /* Clean up srr1 */ mtsrr1 tmp2 /* Set srr1 */ mtdsisr tmp1 mfspr tmp2, dmiss mtdar tmp2 mfmsr tmp0 xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */ mtcrf 0x80, tmp3 /* Restore CR0 */ sync /* Needed on some */ mtmsr tmp0 /* reset MSR[TGPR] */ b .L_handler300 /* Data Access */ /* * Data store translation miss (similar to data load) * * Upon entry (done for us by the machine): * srr0 : addr of instruction that missed * srr1 : bits 0-3 = saved CR0 * 4 = lru way bit * 5 = 1 if store * 16-31 = saved msr * msr[tgpr] = 1 (so gpr0-3 become our temporary variables) * dmiss: ea that missed * dcmp : the compare value for the va that missed * hash1: pointer to first hash pteg * hash2: pointer to 2nd hash pteg * * Register usage: * tmp0: saved counter * tmp1: junk * tmp2: pointer to pteg * tmp3: current compare value * * This code is taken from the 603e User's Manual with * some bugfixes and minor improvements to save bytes and cycles */ . = 0x1200 .L_handler1200: mfspr tmp2, hash1 mfctr tmp0 /* use tmp0 to save ctr */ mfspr tmp3, dcmp .L_dsmiss_find_pte_in_pteg: li tmp1, 8 /* count */ subi tmp2, tmp2, 8 /* offset for lwzu */ mtctr tmp1 /* count... */ .L_dsmiss_pteg_loop: lwz tmp1, 8(tmp2) /* check pte0 for match... */ addi tmp2, tmp2, 8 cmpw cr0, tmp1, tmp3 #if 0 /* I don't know how to write this properly */ bdnzf+ cr0, .L_dsmiss_pteg_loop #else bc 0,2, .L_dsmiss_pteg_loop #endif beq+ cr0, .L_dsmiss_found_pte /* Not found in PTEG, we must scan 2nd then give up */ andi. tmp1, tmp3, MASK(PTE0_HASH_ID) /* already at 2nd? */ bne- .L_dmiss_do_no_hash_exception /* give up */ mfspr tmp2, hash2 ori tmp3, tmp3, MASK(PTE0_HASH_ID) b .L_dsmiss_find_pte_in_pteg .L_dsmiss_found_pte: lwz tmp1, 4(tmp2) /* get pte1_t */ andi. tmp3, tmp1, MASK(PTE1_CHANGED) /* unchanged, check? */ beq- .L_dsmiss_check_prot /* yes, check prot */ .L_dsmiss_resolved: /* Ok, we've found what we need to, restore and rfi! */ mtctr tmp0 /* restore ctr */ mfsrr1 tmp3 mfspr tmp0, dmiss mtcrf 0x80, tmp3 /* Restore CR0 */ mtspr rpa, tmp1 /* set the pte */ tlbld tmp0 /* load up tlb */ rfi .L_dsmiss_check_prot: /* PTE is unchanged, we must check that we can write */ rlwinm. tmp3, tmp1, 30, 0, 1 /* check PP[1] */ bge- .L_dsmiss_check_prot_user_kern andi. tmp3, tmp1, 1 /* check PP[0] */ beq+ .L_dsmiss_check_prot_ok .L_dmiss_do_prot_exception: /* clean up registers for protection exception... */ mfsrr1 tmp3 /* prepare to set DSISR_WRITE_BIT correctly from srr1 info */ rlwinm tmp1, tmp3, 9, 6, 6 addis tmp1, tmp1, MASK(DSISR_PROT) >> 16 /* And the entry into the usual data fault handler ... */ mtctr tmp0 /* Restore ctr */ andi. tmp2, tmp3, 0xffff /* Clean up srr1 */ mtsrr1 tmp2 /* Set srr1 */ mtdsisr tmp1 mfspr tmp2, dmiss mtdar tmp2 mfmsr tmp0 xoris tmp0, tmp0, MASK(MSR_TGPR)>>16 /* no TGPR */ mtcrf 0x80, tmp3 /* Restore CR0 */ sync /* Needed on some */ mtmsr tmp0 /* reset MSR[TGPR] */ b .L_handler300 /* Data Access */ /* NB - if we knew we were on a 603e we could test just the MSR_KEY bit */ .L_dsmiss_check_prot_user_kern: mfsrr1 tmp3 andi. tmp3, tmp3, MASK(MSR_PR) beq+ .L_dsmiss_check_prot_kern mfspr tmp3, dmiss /* check user privs */ mfsrin tmp3, tmp3 /* get excepting SR */ andis. tmp3, tmp3, 0x2000 /* Test SR ku bit */ beq+ .L_dsmiss_check_prot_ok b .L_dmiss_do_prot_exception .L_dsmiss_check_prot_kern: mfspr tmp3, dmiss /* check kern privs */ mfsrin tmp3, tmp3 andis. tmp3, tmp3, 0x4000 /* Test SR Ks bit */ bne- .L_dmiss_do_prot_exception .L_dsmiss_check_prot_ok: /* Ok, mark as referenced and changed before resolving the fault */ ori tmp1, tmp1, (MASK(PTE1_REFERENCED)|MASK(PTE1_CHANGED)) sth tmp1, 6(tmp2) b .L_dsmiss_resolved /* * Instruction address breakpoint */ . = 0x1300 .L_handler1300: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_INSTRUCTION_BKPT /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * System management interrupt */ . = 0x1400 .L_handler1400: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_SYSTEM_MANAGEMENT /* Set 'rupt code */ b .L_exception_entry /* Join common... */ ; ; Altivec Java Mode Assist interrupt ; . = 0x1600 .L_handler1600: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_ALTIVEC_ASSIST /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * There is now a large gap of reserved traps */ /* * Run mode/ trace exception - single stepping on 601 processors */ . = 0x2000 .L_handler2000: mtsprg 2,r13 /* Save R13 */ mtsprg 3,r11 /* Save R11 */ mfsprg r13,1 /* Get the exception save area */ li r11,T_RUNMODE_TRACE /* Set 'rupt code */ b .L_exception_entry /* Join common... */ /* * .L_exception_entry(type) * * This is the common exception handling routine called by any * type of system exception. * * ENTRY: via a system exception handler, thus interrupts off, VM off. * r3 has been saved in sprg3 and now contains a number * representing the exception's origins * */ .data .align ALIGN #ifdef __ELF__ .type EXT(exception_entry),@object .size EXT(exception_entry), 4 #endif .globl EXT(exception_entry) EXT(exception_entry): .long .L_exception_entry-EXT(ExceptionVectorsStart) /* phys addr of fn */ VECTOR_SEGMENT .align 2 .L_exception_entry: /* * * Here we will save off a mess of registers, the special ones and R0-R12. We use the DCBZ * instruction to clear and allcoate a line in the cache. This way we won't take any cache * misses, so these stores won't take all that long. * * */ dcbz 0,r13 /* Allocate the first line of the savearea in the cache */ stw r1,saver1(r13) /* Save this one */ li r1,32 /* Point to the second line */ stw r0,saver0(r13) /* Save this one */ dcbz r1,r13 /* Reserve our line in cache */ #if PERFTIMES && DEBUG mftb r1 ; Get the time of interruption stw r1,0x17C(br0) ; Save the time of interruption #endif stw r2,saver2(r13) /* Save this one */ stw r3,saver3(r13) /* Save this one */ stw r6,saver6(r13) /* Save this one */ stw r4,saver4(r13) /* Save this one */ stw r8,saver8(r13) /* Save this one */ mfsrr0 r6 /* Get the interruption SRR0 */ stw r7,saver7(r13) /* Save this one */ mfsrr1 r7 /* Get the interrupt SRR1 */ stw r6,savesrr0(r13) /* Save the SRR0 */ stw r5,saver5(r13) /* Save this one */ mfsprg r6,2 /* Get interrupt time R13 */ stw r7,savesrr1(r13) /* Save SRR1 */ mfsprg r8,3 /* Get 'rupt time R11 */ stw r6,saver13(r13) /* Save 'rupt R1 */ la r6,saver14(r13) /* Point to the next cache line */ stw r8,saver11(r13) /* Save 'rupt time R11 */ dcbz 0,r6 /* Allocate in cache */ stw r9,saver9(r13) /* Save this one */ mfcr r7 /* Get the CR */ #if 0 cmplwi r13,0x1000 ; (TEST/DEBUG) bgt+ notpage0yy ; (TEST/DEBUG) li r9,1 ; (TEST/DEBUG) lwz r9,0(br0) ; (TEST/DEBUG) dcbst br0,r9 ; (TEST/DEBUG) notpage0aa: b notpage0aa ; (TEST/DEBUG) notpage0yy: lwz r9,0(br0) ; (TEST/DEBUG) mr. r9,r9 ; (TEST/DEBUG) notpage0bb: bne- notpage0bb ; (TEST/DEBUG) #endif la r9,saver30(r13) /* Point to the trailing end */ stw r10,saver10(r13) /* Save this one */ mflr r8 /* Get the LR */ stw r12,saver12(r13) /* Save this one */ dcbz 0,r9 /* Allocate the last in the area */ stw r14,saver14(r13) /* Save this one */ la r10,saver22(r13) /* Point to the next block to save into */ stw r15,saver15(r13) /* Save this one */ stw r7,savecr(r13) /* Save 'rupt CR */ mfctr r6 /* Get the CTR */ stw r16,saver16(r13) /* Save this one */ stw r8,savelr(r13) /* Save 'rupt LR */ dcbz 0,r10 /* Allocate next save area line */ stw r17,saver17(r13) /* Save this one */ stw r18,saver18(r13) /* Save this one */ stw r6,savectr(r13) /* Save 'rupt CTR */ mfxer r7 /* Get the XER */ stw r19,saver19(r13) /* Save this one */ lis r12,HIGH_ADDR(KERNEL_SEG_REG0_VALUE) /* Get the high half of the kernel SR0 value */ mfdar r6 /* Get the 'rupt DAR */ stw r20,saver20(r13) /* Save this one */ #if 0 mfsr r10,sr0 ; (TEST/DEBUG) mfsr r20,sr1 ; (TEST/DEBUG) stw r10,savesr0(r13) ; (TEST/DEBUG) mfsr r10,sr2 ; (TEST/DEBUG) mfsr r19,sr3 ; (TEST/DEBUG) stw r20,savesr1(r13) ; (TEST/DEBUG) mfsr r14,sr4 ; (TEST/DEBUG) mfsr r15,sr5 ; (TEST/DEBUG) stw r10,savesr2(r13) ; (TEST/DEBUG) mfsr r16,sr6 ; (TEST/DEBUG) mfsr r17,sr7 ; (TEST/DEBUG) stw r19,savesr3(r13) ; (TEST/DEBUG) mfsr r10,sr8 ; (TEST/DEBUG) mfsr r20,sr9 ; (TEST/DEBUG) stw r14,savesr4(r13) ; (TEST/DEBUG) mfsr r14,sr10 ; (TEST/DEBUG) mfsr r19,sr11 ; (TEST/DEBUG) stw r15,savesr5(r13) ; (TEST/DEBUG) mfsr r15,sr13 ; (TEST/DEBUG) stw r16,savesr6(r13) ; (TEST/DEBUG) mfsr r16,sr14 ; (TEST/DEBUG) stw r17,savesr7(r13) ; (TEST/DEBUG) mfsr r17,sr15 ; (TEST/DEBUG) stw r10,savesr8(r13) ; (TEST/DEBUG) stw r20,savesr9(r13) ; (TEST/DEBUG) stw r14,savesr10(r13) ; (TEST/DEBUG) stw r19,savesr11(r13) ; (TEST/DEBUG) stw r15,savesr13(r13) ; (TEST/DEBUG) stw r16,savesr14(r13) ; (TEST/DEBUG) stw r17,savesr15(r13) ; (TEST/DEBUG) #endif mtsr sr0,r12 /* Set the kernel SR0 */ stw r21,saver21(r13) /* Save this one */ addis r12,r12,0x0010 ; Point to the second segment of kernel stw r7,savexer(r13) /* Save the 'rupt XER */ mtsr sr1,r12 /* Set the kernel SR1 */ stw r30,saver30(r13) /* Save this one */ addis r12,r12,0x0010 ; Point to the third segment of kernel stw r31,saver31(r13) /* Save this one */ mtsr sr2,r12 /* Set the kernel SR2 */ stw r22,saver22(r13) /* Save this one */ addis r12,r12,0x0010 ; Point to the third segment of kernel la r10,savedar(r13) /* Point to exception info block */ stw r23,saver23(r13) /* Save this one */ mtsr sr3,r12 /* Set the kernel SR3 */ stw r24,saver24(r13) /* Save this one */ stw r25,saver25(r13) /* Save this one */ mfdsisr r7 /* Get the 'rupt DSISR */ stw r26,saver26(r13) /* Save this one */ dcbz 0,r10 /* Allocate exception info line */ stw r27,saver27(r13) /* Save this one */ stw r28,saver28(r13) /* Save this one */ stw r29,saver29(r13) /* Save this one */ mfsr r14,sr14 ; Get the copyin/out segment register stw r6,savedar(r13) /* Save the 'rupt DAR */ stw r7,savedsisr(r13) /* Save the 'rupt code DSISR */ stw r11,saveexception(r13) /* Save the exception code */ stw r14,savesr14(r13) ; Save copyin/copyout lis r8,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ mfpvr r20 /* Get the PVR */ ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ li r21,0x3612 /* Mask of processors with a PIR */ rlwinm r20,r20,16,16,31 /* Isolate the CPU type */ srw r21,r21,r20 /* Isolate the PIR valid bit */ cmplwi cr1,r20,PROCESSOR_VERSION_Max ; Do we have Altivec? rlwinm r21,r21,0,31,31 /* Isolate the PIR valid */ li r19,0 ; Assume no Altivec blt cr1,noavec ; No possible AltiVec here... mfspr r19,vrsave ; Get the VRSAVE register noavec: cmplwi cr6,r21,1 /* Check if PIR is valid */ stw r19,savevrsave(r13) ; Save the vector register usage flags #if 0 lwz r14,savesrr0(r13) /* (TEST/DEBUG) */ cmplw cr7,r5,r5 /* (TEST/DEBUG) */ rlwinm. r14,r14,0,0,15 /* (TEST/DEBUG) */ cmplwi cr2,r11,T_INTERRUPT /* (TEST/DEBUG) */ beq- noeattrace2 /* (TEST/DEBUG) */ cmplwi r11,T_SYSTEM_CALL /* (TEST/DEBUG) */ rlwinm r14,r0,1,0,31 /* (TEST/DEBUG) */ beq cr2,eatatjoes /* (TEST/DEBUG) */ bne+ noeattrace2 /* (TEST/DEBUG) */ cmplwi r14,0x001B /* (TEST/DEBUG) */ bne+ noeattrace2 /* (TEST/DEBUG) */ eatatjoes: cmplwi cr7,r13,0 /* (TEST/DEBUG) */ noeattrace2: #else cmplw cr7,r13,r13 /* (TEST/DEBUG) */ #endif #if RUPTTRC lwz r9,0(br0) /* (TEST/DEBUG) */ lis r14,0x7FFF /* (TEST/DEBUG) */ mr. r9,r9 /* (TEST/DEBUG) */ beq+ nono1 /* (TEST/DEBUG) */ bne cr7,nono1 /* (TEST/DEBUG) */ mfdec r9 /* (TEST/DEBUG) */ or r14,r14,r9 /* (TEST/DEBUG) */ mtdec r14 /* (TEST/DEBUG) */ li r14,0x20 /* (TEST/DEBUG) */ lwarx r15,0,r14 ; ? mpwait0: lwarx r15,0,r14 /* (TEST/DEBUG) */ mr. r15,r15 /* (TEST/DEBUG) */ bne- mpwait0 /* (TEST/DEBUG) */ stwcx. r14,0,r14 /* (TEST/DEBUG) */ bne- mpwait0 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr6,nopir0 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir0 /* (TEST/DEBUG) */ nopir0: li r4,0 /* (TEST/DEBUG) */ gotpir0: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ rlwimi r4,r11,30,8,31 /* (TEST/DEBUG) */ mfsrr0 r5 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3030 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir1 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir1 /* (TEST/DEBUG) */ nopir1: li r4,0 /* (TEST/DEBUG) */ gotpir1: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ lwz r5,savelr(r13) /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3130 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir2 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir2 /* (TEST/DEBUG) */ nopir2: li r4,0 /* (TEST/DEBUG) */ gotpir2: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r13 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3131 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r15,0 /* (TEST/DEBUG) */ stw r15,0x20(br0) /* (TEST/DEBUG) */ mtdec r9 /* (TEST/DEBUG) */ nono1: #endif /* * Everything is saved at this point, except for FPRs, and VMX registers * * Time for a new save area. Allocate the trace table entry now also * Note that we haven't touched R0-R5 yet. Except for R1, that's in the save */ #if 0 mfsrr1 r20 ; (TEST/DEBUG) mfsrr0 r7 ; (TEST/DEBUG) lis r9,0x8000 ; (TEST/DEBUG) mfmsr r25 ; (TEST/DEBUG) ori r15,r25,0x10 ; (TEST/DEBUG) mtmsr r15 ; (TEST/DEBUG) isync ; (TEST/DEBUG) ori r9,r9,lo16(0x870C) ; (TEST/DEBUG) stw r11,0(r9) ; (TEST/DEBUG) stw r7,0(r9) ; (TEST/DEBUG) mtmsr r25 ; (TEST/DEBUG) isync ; (TEST/DEBUG) mtsrr1 r20 ; (TEST/DEBUG) mtsrr0 r7 ; (TEST/DEBUG) #endif lwarx r9,0,r8 ; ? lllck: lwarx r9,0,r8 /* Grab the lock value */ li r7,1 /* Use part of the delay time */ mr. r9,r9 /* Is it locked? */ bne- lllcks /* Yeah, wait for it to clear... */ stwcx. r7,0,r8 /* Try to seize that there durn lock */ beq+ lllckd /* Got it... */ b lllck /* Collision, try again... */ lllcks: lwz r9,SVlock(r8) /* Get that lock in here */ mr. r9,r9 /* Is it free yet? */ beq+ lllck /* Yeah, try for it again... */ b lllcks /* Sniff away... */ lllckd: isync /* Purge any speculative executions here */ rlwinm r7,r11,30,0,31 /* Save 'rupt code shifted right 2 */ #if 1 lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) /* Get the trace mask */ #else li r14,-1 /* (TEST/DEBUG) */ #endif addi r7,r7,10 /* Adjust for CR5_EQ position */ lwz r15,SVfree(r8) /* Get the head of the save area list */ lwz r25,SVinuse(r8) /* Get the in use count */ rlwnm r7,r14,r7,22,22 /* Set CR5_EQ bit position to 0 if tracing allowed */ lwz r20,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) /* Pick up the current trace entry */ mtcrf 0x04,r7 /* Set CR5 to show trace or not */ lwz r14,SACalloc(r15) /* Pick up the allocation bits */ addi r25,r25,1 /* Bump up the in use count for the new savearea */ lwz r21,LOW_ADDR(EXT(traceEnd)-EXT(ExceptionVectorsStart))(br0) /* Grab up the end of it all */ mr. r14,r14 /* Can we use the first one? */ blt use1st /* Yeah... */ andis. r14,r14,0x8000 /* Show we used the second and remember if it was the last */ addi r10,r15,0x0800 /* Point to the first one */ b gotsave /* We have the area now... */ use1st: andis. r14,r14,0x4000 /* Mark first gone and remember if empty */ mr r10,r15 /* Set the save area */ gotsave: stw r14,SACalloc(r15) /* Put back the allocation bits */ bne nodqsave /* There's still an empty slot, don't dequeue... */ lwz r16,SACnext(r15) /* Get the next in line */ stw r16,SVfree(r8) /* Dequeue our now empty save area block */ nodqsave: addi r22,r20,LTR_size /* Point to the next trace entry */ stw r25,SVinuse(r8) /* Set the in use count */ li r17,0 /* Clear this for the lock */ cmplw r22,r21 /* Do we need to wrap the trace table? */ stw r17,SAVprev(r10) /* Clear back pointer for the newly allocated guy */ mtsprg 1,r10 /* Get set for the next 'rupt */ bne+ gotTrcEnt /* We got a trace entry... */ lwz r22,LOW_ADDR(EXT(traceStart)-EXT(ExceptionVectorsStart))(br0) /* Wrap back to the top */ gotTrcEnt: bne- cr5,skipTrace1 /* Don't want to trace this kind... */ stw r22,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) /* Set the next entry for the next guy */ #if ESPDEBUG li r22,0x180 ; (TEST/DEBUG) dcbst br0,r22 ; (TEST/DEBUG) sync ; (TEST/DEBUG) #endif dcbz 0,r20 /* Allocate cache for the entry */ skipTrace1: sync /* Make sure all stores are done */ stw r17,SVlock(r8) /* Unlock both save and trace areas */ #if RUPTTRC lis r14,0x7FFF /* (TEST/DEBUG) */ mfdec r17 /* (TEST/DEBUG) */ or r14,r14,r17 /* (TEST/DEBUG) */ mtdec r14 /* (TEST/DEBUG) */ li r14,0x20 /* (TEST/DEBUG) */ lwarx r16,0,r14 ; ? mpwait1: lwarx r16,0,r14 /* (TEST/DEBUG) */ mr. r16,r16 /* (TEST/DEBUG) */ bne- mpwait1 /* (TEST/DEBUG) */ stwcx. r14,0,r14 /* (TEST/DEBUG) */ bne- mpwait1 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono2 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono2 /* (TEST/DEBUG) */ bne cr6,nopir3 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir3 /* (TEST/DEBUG) */ nopir3: li r4,0 /* (TEST/DEBUG) */ gotpir3: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r10 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3230 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nono2: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r16,0 /* (TEST/DEBUG) */ stw r16,0x20(br0) /* (TEST/DEBUG) */ mtdec r17 /* (TEST/DEBUG) */ #endif /* * At this point, we can take another exception and lose nothing. * * We still have the current savearea pointed to by R13, the next by R10 and * sprg1. R20 contains the pointer to a trace entry and CR5_eq says * to do the trace or not. * * Note that R13 was chosen as the save area pointer because the SIGP, * firmware, and DSI/ISI handlers aren't supposed to touch anything * over R12. But, actually, the DSI/ISI stuff does. * * * Let's cut that trace entry now. */ bne- cr5,skipTrace2 /* Don't want to trace this kind... */ li r14,32 /* Second line of entry */ getTB: mftbu r16 /* Get the upper timebase */ mftb r17 /* Get the lower timebase */ mftbu r18 /* Get the upper one again */ cmplw r16,r18 /* Did the top tick? */ bne- getTB /* Yeah, need to get it again... */ dcbz r14,r20 /* Zap the second half */ stw r16,LTR_timeHi(r20) /* Set the upper part of TB */ bne cr6,nopir4 /* Is there a processor ID number on this guy? */ mfspr r19,pir /* Get the processor address */ b gotpir4 /* Got it... */ nopir4: li r19,0 /* Assume processor 0 for those underprivileged folks */ gotpir4: lwz r1,saver1(r13) /* Get back interrupt time R1 */ stw r17,LTR_timeLo(r20) /* Set the lower part of TB */ rlwinm r19,r19,0,27,31 /* Cut the junk */ stw r0,LTR_r0(r20) /* Save off register 0 */ sth r19,LTR_cpu(r20) /* Stash the cpu address */ stw r1,LTR_r1(r20) /* Save off register 1 */ stw r2,LTR_r2(r20) /* Save off register 2 */ stw r3,LTR_r3(r20) /* Save off register 3 */ lwz r16,savecr(r13) /* We don't remember the CR anymore, get it */ stw r4,LTR_r4(r20) /* Save off register 4 */ mfsrr0 r17 /* Get this back, it's still good */ stw r5,LTR_r5(r20) /* Save off register 5 */ mfsrr1 r18 /* This is still good in here also */ stw r16,LTR_cr(r20) /* Save the CR (or dec) */ stw r17,LTR_srr0(r20) /* Save the SSR0 */ stw r18,LTR_srr1(r20) /* Save the SRR1 */ mfdar r17 /* Get this back */ mflr r16 /* Get the LR */ stw r17,LTR_dar(r20) /* Save the DAR */ mfctr r17 /* Get the CTR */ stw r16,LTR_lr(r20) /* Save the LR */ #if 0 lis r17,HIGH_ADDR(EXT(saveanchor)) ; (TEST/DEBUG) ori r17,r17,LOW_ADDR(EXT(saveanchor)) ; (TEST/DEBUG) lwz r16,SVcount(r17) ; (TEST/DEBUG) lwz r17,SVinuse(r17) ; (TEST/DEBUG) rlwimi r17,r16,16,0,15 ; (TEST/DEBUG) #endif stw r17,LTR_ctr(r20) /* Save off the CTR */ stw r13,LTR_save(r20) /* Save the savearea */ sth r11,LTR_excpt(r20) /* Save the exception type */ #if ESPDEBUG addi r17,r20,32 ; (TEST/DEBUG) dcbst br0,r20 ; (TEST/DEBUG) dcbst br0,r17 ; (TEST/DEBUG) sync ; (TEST/DEBUG) #endif /* * We're done with the trace, except for maybe modifying the exception * code later on. So, that means that we need to save R20 and CR5, but * R0 to R5 are clear now. * * So, let's finish setting up the kernel registers now. */ skipTrace2: #if PERFTIMES && DEBUG li r3,68 ; Indicate interrupt mr r4,r11 ; Get code to log mr r5,r13 ; Get savearea to log mr r8,r0 ; Save R0 bl EXT(dbgLog2) ; Cut log entry mr r0,r8 ; Restore R0 #endif mfsprg r2,0 /* Get the per processor block */ #if 0 lis r19,0xF300 /* (TEST/DEBUG) */ ori r19,r19,0x0020 /* (TEST/DEBUG) */ dcbi 0,r19 /* (TEST/DEBUG) */ sync /* (TEST/DEBUG) */ eieio /* (TEST/DEBUG) */ lwz r18,0x000C(r19) /* (TEST/DEBUG) */ eieio /* (TEST/DEBUG) */ dcbi 0,r19 /* (TEST/DEBUG) */ rlwinm. r4,r18,0,19,19 /* (TEST/DEBUG) */ rlwinm r18,r18,0,20,18 /* (TEST/DEBUG) */ sync /* (TEST/DEBUG) */ eieio /* (TEST/DEBUG) */ beq+ nonmi /* (TEST/DEBUG) */ stw r18,0x0008(r19) /* (TEST/DEBUG) */ dcbi 0,r19 /* (TEST/DEBUG) */ sync /* (TEST/DEBUG) */ eieio /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ nonmi: /* (TEST/DEBUG) */ #endif #if 0 lis r4,hi16(EXT(hash_table_base)) ; (TEST/DEBUG) ori r4,r4,lo16(EXT(hash_table_base)) ; (TEST/DEBUG) lwz r8,0(r4) ; (TEST/DEBUG) lwz r4,4(r4) ; (TEST/DEBUG) add r8,r4,r8 ; (TEST/DEBUG) yyyck: lwz r12,4(r8) ; (TEST/DEBUG) rlwimn. r12,r12,0,24,31 ; (TEST/DEBUG) bne+ yyyok ; (TEST/DEBUG) BREAKPOINT_TRAP ; (TEST/DEBUG) yyyok: addi r8,r8,0x40 ; (TEST/DEBUG) subic r4,r4,0x40 ; (TEST/DEBUG) bgt+ yyyck ; (TEST/DEBUG) #endif #if CHECKSAVE lis r4,0x7FFF /* (TEST/DEBUG) */ mfdec r12 /* (TEST/DEBUG) */ or r4,r4,r12 /* (TEST/DEBUG) */ mtdec r4 /* (TEST/DEBUG) */ li r4,0x20 /* (TEST/DEBUG) */ lwarx r8,0,r4 ; ? mpwait2: lwarx r8,0,r4 /* (TEST/DEBUG) */ mr. r8,r8 /* (TEST/DEBUG) */ bne- mpwait2 /* (TEST/DEBUG) */ stwcx. r4,0,r4 /* (TEST/DEBUG) */ bne- mpwait2 /* (TEST/DEBUG) */ isync /* (TEST/DEBUG) */ lwz r4,0xD80(br0) /* (TEST/DEBUG) */ mr. r4,r4 /* (TEST/DEBUG) */ li r4,1 /* (TEST/DEBUG) */ bne- doncheksv /* (TEST/DEBUG) */ lis r8,HIGH_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */ ori r8,r8,LOW_ADDR(EXT(saveanchor)) /* (TEST/DEBUG) */ stw r4,0xD80(br0) /* (TEST/DEBUG) */ lwarx r4,0,r8 ; ? mpwait2x: lwarx r4,0,r8 /* (TEST/DEBUG) */ mr. r4,r4 /* (TEST/DEBUG) */ bne- mpwait2x /* (TEST/DEBUG) */ stwcx. r8,0,r8 /* (TEST/DEBUG) */ bne- mpwait2x /* (TEST/DEBUG) */ isync /* (TEST/DEBUG) */ #if 0 rlwinm r4,r13,0,0,19 /* (TEST/DEBUG) */ lwz r21,SACflags(r4) /* (TEST/DEBUG) */ rlwinm r22,r21,24,24,31 /* (TEST/DEBUG) */ cmplwi r22,0x00EE /* (TEST/DEBUG) */ lwz r22,SACvrswap(r4) /* (TEST/DEBUG) */ bne- currbad /* (TEST/DEBUG) */ andis. r21,r21,hi16(sac_perm) /* (TEST/DEBUG) */ bne- currnotbad /* (TEST/DEBUG) */ mr. r22,r22 /* (TEST/DEBUG) */ bne+ currnotbad /* (TEST/DEBUG) */ currbad: lis r23,hi16(EXT(debugbackpocket)) /* (TEST/DEBUG) */ ori r23,r23,lo16(EXT(debugbackpocket)) /* (TEST/DEBUG) */ stw r23,SVfree(r8) /* (TEST/DEBUG) */ mfsprg r25,1 /* (TEST/DEBUG) */ mtsprg 1,r23 /* (TEST/DEBUG) */ lwz r26,SACalloc(r23) /* (TEST/DEBUG) */ rlwinm r26,r26,0,1,31 /* (TEST/DEBUG) */ stw r26,SACalloc(r23) /* (TEST/DEBUG) */ sync /* (TEST/DEBUG) */ li r28,0 /* (TEST/DEBUG) */ stw r28,0x20(br0) /* (TEST/DEBUG) */ stw r28,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ currnotbad: #endif lwz r28,SVcount(r8) /* (TEST/DEBUG) */ #if RUPTTRC stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono90 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono90 /* (TEST/DEBUG) */ bne cr6,nopir5 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir0 /* (TEST/DEBUG) */ nopir5: li r4,0 /* (TEST/DEBUG) */ gotpir5: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r28 /* (TEST/DEBUG) */ oris r4,r4,0x3036 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3636 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nono90: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ #endif lwz r21,SVinuse(r8) /* (TEST/DEBUG) */ lwz r23,SVmin(r8) /* (TEST/DEBUG) */ sub r22,r28,r21 /* (TEST/DEBUG) */ cmpw r22,r23 /* (TEST/DEBUG) */ bge+ cksave0 /* (TEST/DEBUG) */ li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave0: lwz r28,SVfree(r8) /* (TEST/DEBUG) */ li r24,0 /* (TEST/DEBUG) */ li r29,1 /* (TEST/SAVE) */ cksave0a: mr. r28,r28 /* (TEST/DEBUG) */ beq- cksave3 /* (TEST/DEBUG) */ rlwinm. r21,r28,0,4,19 /* (TEST/DEBUG) */ bne+ cksave1 /* (TEST/DEBUG) */ li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave1: rlwinm. r21,r28,0,21,3 /* (TEST/DEBUG) */ beq+ cksave2 /* (TEST/DEBUG) */ li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave2: lwz r25,SACalloc(r28) /* (TEST/DEBUG) */ lbz r26,SACflags+2(r28) /* (TEST/DEBUG) */ lbz r21,SACflags+3(r28) /* (TEST/DEBUG) */ cmplwi r26,0x00EE /* (TEST/DEBUG) */ stb r29,SACflags+3(r28) /* (TEST/DEBUG) */ beq+ cksave2z li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave2z: mr. r21,r21 /* (TEST/DEBUG) */ beq+ cksave2a /* (TEST/DEBUG) */ li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave2a: rlwinm r26,r25,1,31,31 /* (TEST/DEBUG) */ rlwinm r27,r25,2,31,31 /* (TEST/DEBUG) */ add r24,r24,r26 /* (TEST/DEBUG) */ add r24,r24,r27 /* (TEST/DEBUG) */ lwz r28,SACnext(r28) /* (TEST/DEBUG) */ b cksave0a /* (TEST/DEBUG) */ cksave3: cmplw r24,r22 /* (TEST/DEBUG) */ beq+ cksave4 /* (TEST/DEBUG) */ li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ BREAKPOINT_TRAP /* (TEST/DEBUG) */ cksave4: lwz r28,SVfree(r8) /* (TEST/DEBUG) */ li r24,0 /* (TEST/DEBUG) */ cksave5: mr. r28,r28 /* (TEST/DEBUG) */ beq- cksave6 /* (TEST/DEBUG) */ stb r24,SACflags+3(r28) /* (TEST/DEBUG) */ lwz r28,SACnext(r28) /* (TEST/DEBUG) */ b cksave5 /* (TEST/DEBUG) */ cksave6: li r4,0 /* (TEST/DEBUG) */ stw r4,0xD80(br0) /* (TEST/DEBUG) */ stw r4,0(r8) /* (TEST/DEBUG) */ doncheksv: li r4,0 /* (TEST/DEBUG) */ stw r4,0x20(br0) /* (TEST/DEBUG) */ mtdec r12 /* (TEST/DEBUG) */ #endif #if 0 lhz r4,0x980(br0) ; (TEST/DEBUG) xoris r4,r4,lo16(0xFFF8) ; (TEST/DEBUG) mr. r4,r4 ; (TEST/DEBUG) beq- dontkillmedead ; (TEST/DEBUG) mfmsr r12 ; (TEST/DEBUG) ori r4,r12,0x2000 ; (TEST/DEBUG) mtmsr r4 ; (TEST/DEBUG) isync ; (TEST/DEBUG) stfd f13,0x980(br0) ; (TEST/DEBUG) mtmsr r12 ; (TEST/DEBUG) isync ; (TEST/DEBUG) lhz r4,0x980(br0) ; (TEST/DEBUG) xoris r4,r4,lo16(0xFFF8) ; (TEST/DEBUG) mr. r4,r4 ; (TEST/DEBUG) bne+ dontkillmedead ; (TEST/DEBUG) BREAKPOINT_TRAP ; (TEST/DEBUG) dontkillmedead: ; (TEST/DEBUG) #endif lis r4,HIGH_ADDR(EXT(MPspec)) /* Get the MP control block */ dcbt 0,r2 /* We'll need the per_proc in a sec */ cmplwi cr0,r11,T_INTERRUPT /* Do we have an external interrupt? */ ori r4,r4,LOW_ADDR(EXT(MPspec)) /* Get the bottom half of the MP control block */ bne+ notracex /* Not an external... */ /* * Here we check to see if there was a interprocessor signal */ lwz r4,MPSSIGPhandler(r4) /* Get the address of the SIGP interrupt filter */ lhz r3,PP_CPU_FLAGS(r2) /* Get the CPU flags */ cmplwi cr1,r4,0 /* Check if signal filter is initialized yet */ andi. r3,r3,LOW_ADDR(SIGPactive) /* See if this processor has started up */ mtlr r4 /* Load up filter address */ beq- cr1,notracex /* We don't have a filter yet... */ beq- notracex /* This processor hasn't started filtering yet... */ blrl /* Filter the interrupt */ mfsprg r2,0 /* Make sure we have the per processor block */ cmplwi cr0,r3,kMPIOInterruptPending /* See what the filter says */ li r11,T_INTERRUPT /* Assume we have a regular external 'rupt */ beq+ modRupt /* Yeah, we figured it would be... */ li r11,T_SIGP /* Assume we had a signal processor interrupt */ bgt+ modRupt /* Yeah, at this point we would assume so... */ li r11,T_IN_VAIN /* Nothing there actually, so eat it */ modRupt: stw r11,PP_SAVE_EXCEPTION_TYPE(r2) /* Set that it was either in vain or a SIGP */ stw r11,saveexception(r13) /* Save the exception code here also */ bne- cr5,notracex /* Jump if no tracing... */ sth r11,LTR_excpt(r20) /* Save the exception type */ notracex: #if 0 bne cr6,nopir6 /* (TEST/DEBUG) */ mfspr r7,pir /* (TEST/DEBUG) */ b gotpir6 /* (TEST/DEBUG) */ nopir6: li r7,0 /* (TEST/DEBUG) */ gotpir6: /* (TEST/DEBUG) */ lis r6,HIGH_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */ rlwinm r7,r7,8,23,23 /* (TEST/DEBUG) */ lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ rlwimi r7,r7,1,22,22 /* (TEST/DEBUG) */ ori r6,r6,LOW_ADDR(EXT(RuptCtrs)) /* (TEST/DEBUG) */ rlwinm r1,r11,2,0,29 /* (TEST/DEBUG) */ add r6,r6,r7 /* (TEST/DEBUG) */ ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ lwz r21,(47*16)+8(r6) /* (TEST/DEBUG) */ lwz r22,(47*16)+12(r6) /* (TEST/DEBUG) */ add r1,r1,r6 /* (TEST/DEBUG) */ mftb r24 /* (TEST/DEBUG) */ sub r22,r24,r22 /* (TEST/DEBUG) */ lwz r4,4(r6) /* (TEST/DEBUG) */ cmplw cr2,r22,r21 /* (TEST/DEBUG) */ lwz r7,4(r1) /* (TEST/DEBUG) */ lwz r21,8(r6) /* (TEST/DEBUG) */ blt+ cr2,nottime /* (TEST/DEBUG) */ stw r24,(47*16)+12(r6) /* (TEST/DEBUG) */ nottime: addi r4,r4,1 /* (TEST/DEBUG) */ lwz r22,8(r1) /* (TEST/DEBUG) */ addi r7,r7,1 /* (TEST/DEBUG) */ stw r4,4(r6) /* (TEST/DEBUG) */ lwz r3,0(r6) /* (TEST/DEBUG) */ mr. r21,r21 /* (TEST/DEBUG) */ stw r7,4(r1) /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ lwz r1,0(r1) /* (TEST/DEBUG) */ beq- nottimed1 /* (TEST/DEBUG) */ blt+ cr2,isnttime1 /* (TEST/DEBUG) */ nottimed1: mr. r3,r3 /* (TEST/DEBUG) */ bgelrl+ /* (TEST/DEBUG) */ isnttime1: mr. r22,r22 /* (TEST/DEBUG) */ beq- nottimed2 /* (TEST/DEBUG) */ blt+ cr2,isnttime2 /* (TEST/DEBUG) */ nottimed2: mr. r3,r1 /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ mr r4,r7 /* (TEST/DEBUG) */ bgelrl+ /* (TEST/DEBUG) */ mr r3,r11 /* (TEST/DEBUG) */ isnttime2: cmplwi r11,T_DATA_ACCESS /* (TEST/DEBUG) */ lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ bne+ nodsidisp /* (TEST/DEBUG) */ mr. r22,r22 /* (TEST/DEBUG) */ beq- nottimed3 /* (TEST/DEBUG) */ blt+ cr2,nodsidisp /* (TEST/DEBUG) */ nottimed3: li r3,5 /* (TEST/DEBUG) */ ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ lwz r4,savesrr0(r13) /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ lis r3,9 /* (TEST/DEBUG) */ ori r3,r3,5 /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ lwz r4,savedar(r13) /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nodsidisp: cmplwi r11,T_INSTRUCTION_ACCESS /* (TEST/DEBUG) */ lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ bne+ noisidisp /* (TEST/DEBUG) */ mr. r22,r22 /* (TEST/DEBUG) */ beq- nottimed4 /* (TEST/DEBUG) */ blt+ cr2,noisidisp /* (TEST/DEBUG) */ nottimed4: li r3,6 /* (TEST/DEBUG) */ ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ lwz r4,savesrr0(r13) /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ noisidisp: mr r3,r11 /* (TEST/DEBUG) */ #endif #if 0 cmplwi r11,T_PROGRAM /* (TEST/DEBUG) */ lis r12,HIGH_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ bne+ nopgmdisp /* (TEST/DEBUG) */ li r3,7 /* (TEST/DEBUG) */ ori r12,r12,LOW_ADDR(EXT(GratefulDeb)) /* (TEST/DEBUG) */ lwz r4,savesrr0(r13) /* (TEST/DEBUG) */ mtlr r12 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nopgmdisp: mr r3,r11 /* (TEST/DEBUG) */ #endif #if RUPTTRC lis r6,0x7FFF /* (TEST/DEBUG) */ mfdec r7 /* (TEST/DEBUG) */ or r6,r6,r7 /* (TEST/DEBUG) */ mtdec r6 /* (TEST/DEBUG) */ li r6,0x20 /* (TEST/DEBUG) */ lwarx r1,0,r6 ; ? mpwait3: lwarx r1,0,r6 /* (TEST/DEBUG) */ mr. r1,r1 /* (TEST/DEBUG) */ bne- mpwait3 /* (TEST/DEBUG) */ stwcx. r6,0,r6 /* (TEST/DEBUG) */ bne- mpwait3 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono3 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono3 /* (TEST/DEBUG) */ bne cr6,nopir7 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir7 /* (TEST/DEBUG) */ nopir7: li r4,0 /* (TEST/DEBUG) */ gotpir7: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r11 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3330 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir8 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir8 /* (TEST/DEBUG) */ nopir8: li r4,0 /* (TEST/DEBUG) */ gotpir8: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ lwz r5,0x280(br0) /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3430 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nono3: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r6,0 /* (TEST/DEBUG) */ stw r6,0x20(br0) /* (TEST/DEBUG) */ mtdec r7 /* (TEST/DEBUG) */ #endif li r21,0 ; Assume no processor register for now lis r12,hi16(EXT(hw_counts)) ; Get the high part of the interrupt counters bne- cr6,nopirhere ; Jump if this processor does not have a PIR... mfspr r21,pir ; Get the PIR nopirhere: ori r12,r12,lo16(EXT(hw_counts)) ; Get the low part of the interrupt counters rlwinm r21,r21,8,20,23 ; Get index to processor counts mtcrf 0x80,r0 /* Set our CR0 to the high nybble of the request code */ rlwinm r6,r0,1,0,31 /* Move sign bit to the end */ cmplwi cr1,r11,T_SYSTEM_CALL /* Did we get a system call? */ crandc cr0_lt,cr0_lt,cr0_gt /* See if we have R0 equal to 0b10xx...x */ add r12,r12,r21 ; Point to the processor count area cmplwi cr3,r11,T_IN_VAIN /* Was this all in vain? All for nothing? */ lwzx r22,r12,r11 ; Get the old value cmplwi cr2,r6,1 /* See if original R0 had the CutTrace request code in it */ addi r22,r22,1 ; Count this one cmplwi cr4,r11,T_SIGP /* Indicate if we had a SIGP 'rupt */ stwx r22,r12,r11 ; Store it back beq- cr3,EatRupt /* Interrupt was all for nothing... */ cmplwi cr3,r11,T_MACHINE_CHECK ; Did we get a machine check? bne+ cr1,noCutT /* Not a system call... */ bnl+ cr0,noCutT /* R0 not 0b10xxx...x, can't be any kind of magical system call... */ beq- cr2,isCutTrace /* This is a CutTrace system call */ /* * Here's where we call the firmware. If it returns T_IN_VAIN, that means * that it has handled the interruption. Remember: thou shalt not trash R13 * or R20 while you are away. Anything else is ok. */ lis r1,HIGH_ADDR(EXT(FirmwareCall)) /* Top half of firmware call handler */ ori r1,r1,LOW_ADDR(EXT(FirmwareCall)) /* Bottom half of it */ lwz r3,saver3(r13) /* Restore the first parameter, the rest are ok already */ mtlr r1 /* Get it in the link register */ blrl /* Call the handler */ #if RUPTTRC lis r7,0x7FFF /* (TEST/DEBUG) */ mfdec r6 /* (TEST/DEBUG) */ or r7,r7,r6 /* (TEST/DEBUG) */ mtdec r7 /* (TEST/DEBUG) */ li r7,0x20 /* (TEST/DEBUG) */ lwarx r1,0,r7 ; ? mpwait4: lwarx r1,0,r7 /* (TEST/DEBUG) */ mr. r1,r1 /* (TEST/DEBUG) */ bne- mpwait4 /* (TEST/DEBUG) */ stwcx. r7,0,r7 /* (TEST/DEBUG) */ bne- mpwait4 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono4 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono4 /* (TEST/DEBUG) */ bne cr6,nopir9 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir9 /* (TEST/DEBUG) */ nopir9: li r4,0 /* (TEST/DEBUG) */ gotpir9: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ mr r5,r3 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3530 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ mtdec r25 /* (TEST/DEBUG) */ nono4: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r7,0 /* (TEST/DEBUG) */ stw r7,0x20(br0) /* (TEST/DEBUG) */ mtdec r6 /* (TEST/DEBUG) */ #endif cmplwi r3,T_IN_VAIN /* Was it handled? */ mfsprg r2,0 /* Restore the per_processor area */ beq+ EatRupt /* Interrupt was handled... */ mr r11,r3 /* Put the 'rupt code in the right register */ b noSIGP /* Go to the normal system call handler */ isCutTrace: li r7,-32768 /* Get a 0x8000 for the exception code */ bne- cr5,EatRupt /* Tracing is disabled... */ sth r7,LTR_excpt(r20) /* Modify the exception type to a CutTrace */ b EatRupt /* Time to go home... */ /* We are here 'cause we didn't have a CutTrace system call */ noCutT: beq- cr3,MachineCheck ; Whoa... Machine check... bne+ cr4,noSIGP /* Skip away if we didn't get a SIGP... */ lis r6,HIGH_ADDR(EXT(MPsignalFW)) /* Top half of SIGP handler */ ori r6,r6,LOW_ADDR(EXT(MPsignalFW)) /* Bottom half of it */ mtlr r6 /* Get it in the link register */ blrl /* Call the handler - we'll only come back if this is an AST, */ /* 'cause FW can't handle that */ mfsprg r2,0 /* Restore the per_processor area */ ; ; The following interrupts are the only ones that can be redriven ; by the higher level code or emulation routines. ; Redrive: cmplwi cr0,r3,T_IN_VAIN /* Did the signal handler eat the signal? */ mr r11,r3 /* Move it to the right place */ beq+ cr0,EatRupt /* Bail now if the signal handler processed the signal... */ /* * Here's where we check for the other fast-path exceptions: translation exceptions, * emulated instructions, etc. */ noSIGP: cmplwi cr3,r11,T_ALTIVEC_ASSIST ; Check for an Altivec denorm assist cmplwi cr1,r11,T_PROGRAM /* See if we got a program exception */ cmplwi cr2,r11,T_INSTRUCTION_ACCESS /* Check on an ISI */ bne+ cr3,noAltivecAssist ; It is not an assist... b EXT(AltivecAssist) ; It is an assist... noAltivecAssist: bne+ cr1,noEmulate ; No emulation here... b EXT(Emulate) ; Go try to emulate... noEmulate: cmplwi cr3,r11,T_CSWITCH /* Are we context switching */ cmplwi r11,T_DATA_ACCESS /* Check on a DSI */ beq- cr2,DSIorISI /* It's a PTE fault... */ beq- cr3,conswtch /* It's a context switch... */ bne+ PassUp /* It's not a PTE fault... */ /* * This call will either handle the fault, in which case it will not * return, or return to pass the fault up the line. */ DSIorISI: lis r7,HIGH_ADDR(EXT(handlePF)) /* Top half of DSI handler */ ori r7,r7,LOW_ADDR(EXT(handlePF)) /* Bottom half of it */ mtlr r7 /* Get it in the link register */ mr r3,r11 /* Move the 'rupt code */ blrl /* See if we can handle this fault */ #if RUPTTRC bne cr7,nononono2 /* (TEST/DEBUG) */ lwz r7,0(br0) /* (TEST/DEBUG) */ mr. r7,r7 /* (TEST/DEBUG) */ beq+ nononono2 /* (TEST/DEBUG) */ #if 0 lis r7,0x7FFF /* (TEST/DEBUG) */ mfdec r2 /* (TEST/DEBUG) */ or r7,r7,r2 /* (TEST/DEBUG) */ mtdec r7 /* (TEST/DEBUG) */ li r7,0x20 /* (TEST/DEBUG) */ lwarx r0,0,r7 ; ? yesyesyes2: lwarx r0,0,r7 /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ li r0,1 /* (TEST/DEBUG) */ bne- yesyesyes2 /* (TEST/DEBUG) */ stwcx. r0,0,r7 /* (TEST/DEBUG) */ bne- yesyesyes2 /* (TEST/DEBUG) */ #endif stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ mr r20,r3 bne cr6,nopir10 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir10 /* (TEST/DEBUG) */ nopir10: li r4,0 /* (TEST/DEBUG) */ gotpir10: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ or r4,r4,r20 /* (TEST/DEBUG) */ lwz r5,savedar(r13) /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3630 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ #if 0 lis r31,HIGH_ADDR(EXT(dbgRegs)) /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgRegs)) /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ #endif lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r0,0 /* (TEST/DEBUG) */ stw r0,0x20(br0) /* (TEST/DEBUG) */ mtdec r2 /* (TEST/DEBUG) */ nononono2: /* (TEST/DEBUG) */ #endif lwz r0,savesrr1(r13) ; Get the MSR in use at exception time mfsprg r2, 0 /* Get back per_proc */ cmplwi cr1,r3,T_IN_VAIN ; Was it handled? andi. r4,r0,lo16(MASK(MSR_RI)) ; See if the recover bit is on mr r11,r3 /* Make sure we can find this later */ beq+ cr1,EatRupt ; Yeah, just blast back to the user... andc r0,r0,r4 ; Remove the recover bit beq+ PassUp ; Not on, normal case... lwz r4,savesrr0(r13) ; Get the failing instruction address lwz r5,savecr(r13) ; Get the condition register stw r0,savesrr1(r13) ; Save the result MSR addi r4,r4,4 ; Skip failing instruction rlwinm r5,r5,0,3,1 ; Clear CR0_EQ to let emulation code know we failed stw r4,savesrr0(r13) ; Save instruction address stw r4,savecr(r13) ; And the resume CR b EatRupt ; Resume emulated code /* * Here is where we handle the context switch firmware call. The old * context has been saved, and the new savearea in in saver3. We'll just * muck around with the savearea pointers, and then join the exit routine */ conswtch: lwz r28,SAVflags(r13) /* The the flags of the current */ mr r29,r13 /* Save the save */ rlwinm r30,r13,0,0,19 /* Get the start of the savearea block */ lwz r5,saver3(r13) /* Switch to the new savearea */ oris r28,r28,HIGH_ADDR(SAVattach) /* Turn on the attached flag */ lwz r30,SACvrswap(r30) /* get real to virtual translation */ mr r13,r5 /* Switch saveareas */ xor r27,r29,r30 /* Flip to virtual */ stw r28,SAVflags(r29) /* Stash it back */ stw r27,saver3(r5) /* Push the new savearea to the switch to routine */ b EatRupt /* Start 'er up... */ ; ; Handle machine check here. ; ; ? ; MachineCheck: lwz r27,savesrr1(r13) ; ? rlwinm. r11,r27,0,dcmck,dcmck ; ? beq+ notDCache ; ? mfspr r11,msscr0 ; ? dssall ; ? sync lwz r27,savesrr1(r13) ; ? hiccup: cmplw r27,r27 ; ? bne- hiccup ; ? isync ; ? oris r11,r11,hi16(dl1hwfm) ; ? mtspr msscr0,r11 ; ? rstbsy: mfspr r11,msscr0 ; ? rlwinm. r11,r11,0,dl1hwf,dl1hwf ; ? bne rstbsy ; ? sync ; ? li r11,T_IN_VAIN ; ? b EatRupt ; ? notDCache: ; ; Check if the failure was in ; ml_probe_read. If so, this is expected, so modify the PC to ; ml_proble_read_mck and then eat the exception. ; lwz r30,savesrr0(r13) ; Get the failing PC lis r28,hi16(EXT(ml_probe_read_mck)) ; High order part lis r27,hi16(EXT(ml_probe_read)) ; High order part ori r28,r28,lo16(EXT(ml_probe_read_mck)) ; Get the low part ori r27,r27,lo16(EXT(ml_probe_read)) ; Get the low part cmplw r30,r28 ; Check highest possible cmplw cr1,r30,r27 ; Check lowest bge- PassUp ; Outside of range blt- cr1,PassUp ; Outside of range ; ; We need to fix up the BATs here because the probe ; routine messed them all up... As long as we are at it, ; fix up to return directly to caller of probe. ; lwz r30,saver5(r13) ; Get proper DBAT values lwz r28,saver6(r13) lwz r27,saver7(r13) lwz r11,saver8(r13) lwz r18,saver9(r13) sync mtdbatu 0,r30 ; Restore DBAT 0 high mtdbatl 0,r28 ; Restore DBAT 0 low mtdbatu 1,r27 ; Restore DBAT 1 high mtdbatu 2,r11 ; Restore DBAT 2 high mtdbatu 3,r18 ; Restore DBAT 3 high sync lwz r28,savelr(r13) ; Get return point lwz r27,saver0(r13) ; Get the saved MSR li r30,0 ; Get a failure RC stw r28,savesrr0(r13) ; Set the return point stw r27,savesrr1(r13) ; Set the continued MSR stw r30,saver3(r13) ; Set return code li r11,T_IN_VAIN ; Set new interrupt code b EatRupt ; Yum, yum, eat it all up... /* * Here's where we come back from some instruction emulator. If we come back with * T_IN_VAIN, the emulation is done and we should just reload state and directly * go back to the interrupted code. Otherwise, we'll check to see if * we need to redrive with a different interrupt, i.e., DSI. */ .align 5 .globl EXT(EmulExit) LEXT(EmulExit) cmplwi r11,T_IN_VAIN /* Was it emulated? */ lis r1,hi16(SAVredrive) ; Get redrive request mfsprg r2,0 ; Restore the per_proc area beq+ EatRupt /* Yeah, just blast back to the user... */ lwz r4,SAVflags(r13) ; Pick up the flags and. r0,r4,r1 ; Check if redrive requested andc r4,r4,r1 ; Clear redrive beq+ PassUp ; No redrive, just keep on going... lwz r3,saveexception(r13) ; Restore exception code stw r4,SAVflags(r13) ; Set the flags b Redrive ; Redrive the exception... /* Jump into main handler code switching on VM at the same time */ /* We assume kernel data is mapped contiguously in physical * memory, otherwise we'd need to switch on (at least) virtual data. * SRs are already set up. */ PassUp: lwz r2,PP_PHYS_EXCEPTION_HANDLERS(r2) /* Pick up the exception handler base */ lwzx r6,r2,r11 /* Get the actual exception handler address */ PassUpDeb: lwz r8,SAVflags(r13) /* Get the flags */ mtsrr0 r6 /* Set up the handler address */ oris r8,r8,HIGH_ADDR(SAVattach) /* Since we're passing it up, attach it */ rlwinm r5,r13,0,0,19 /* Back off to the start of savearea block */ mfmsr r3 /* Get our MSR */ stw r8,SAVflags(r13) /* Pass up the flags */ rlwinm r3,r3,0,MSR_BE_BIT+1,MSR_SE_BIT-1 /* Clear all but the trace bits */ li r2,MSR_SUPERVISOR_INT_OFF /* Get our normal MSR value */ lwz r5,SACvrswap(r5) /* Get real to virtual conversion */ or r2,r2,r3 /* Keep the trace bits if they're on */ mr r3,r11 /* Pass the exception code in the paramter reg */ mtsrr1 r2 /* Set up our normal MSR value */ xor r4,r13,r5 /* Pass up the virtual address of context savearea */ #if RUPTTRC lis r20,0x7FFF /* (TEST/DEBUG) */ mfdec r25 /* (TEST/DEBUG) */ or r20,r20,r25 /* (TEST/DEBUG) */ mtdec r20 /* (TEST/DEBUG) */ li r20,0x20 /* (TEST/DEBUG) */ lwarx r21,0,r20 ; ? mpwait5: lwarx r21,0,r20 /* (TEST/DEBUG) */ mr. r21,r21 /* (TEST/DEBUG) */ bne- mpwait5 /* (TEST/DEBUG) */ stwcx. r20,0,r20 /* (TEST/DEBUG) */ bne- mpwait5 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono9 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono9 /* (TEST/DEBUG) */ mr r30,r4 /* (TEST/DEBUG) */ mr r24,r5 /* (TEST/DEBUG) */ bne cr6,nopir11 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir11 /* (TEST/DEBUG) */ nopir11: li r4,0 /* (TEST/DEBUG) */ gotpir11: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r6 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3930 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir12 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir12 /* (TEST/DEBUG) */ nopir12: li r4,0 /* (TEST/DEBUG) */ gotpir12: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r30 /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3130 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir13 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir13 /* (TEST/DEBUG) */ nopir13: li r4,0 /* (TEST/DEBUG) */ gotpir13: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ xor r5,r30,r24 /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3131 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir14 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir14 /* (TEST/DEBUG) */ nopir14: li r4,0 /* (TEST/DEBUG) */ gotpir14: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mr r5,r25 /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3132 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir15 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir15 /* (TEST/DEBUG) */ nopir15: li r4,0 /* (TEST/DEBUG) */ gotpir15: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mfsrr0 r5 /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3133 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nono9: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r20,0 /* (TEST/DEBUG) */ stw r20,0x20(br0) /* (TEST/DEBUG) */ mtdec r25 /* (TEST/DEBUG) */ #endif rfi /* Launch the exception handler */ .long 0 /* Leave these here gol durn it! */ .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 /* * This routine is the only place where we return from an interruption. * Anyplace else is wrong. Even if I write the code, it's still wrong * Feel free to come by and slap me if I do do it. Even though I may * have had a good reason to do it. * * All we need to remember here is that R13 must point to the savearea * that has the context we need to load up. Translation and interruptions * must be disabled. * * This code always loads the context in the savearea pointed to * by R13. In the process, it throws away the savearea. If there * is any tomfoolery with savearea stacks, it must be taken care of * before we get here. */ EatRupt: mr r31,r13 /* Move the savearea pointer to the far end of the register set */ EatRupt2: mfsprg r2,0 /* Get the per_proc block */ /* * First we see if we are able to free the new savearea. * If it is not attached to anything, put it on the free list. * This is real dangerous, we haven't restored context yet... * So, the free savearea chain lock must stay until the bitter end! */ #if RUPTTRC lis r18,0x7FFF /* (TEST/DEBUG) */ mfdec r25 /* (TEST/DEBUG) */ or r18,r18,r25 /* (TEST/DEBUG) */ mtdec r18 /* (TEST/DEBUG) */ li r18,0x20 /* (TEST/DEBUG) */ lwarx r19,0,r18 ; ? mpwait6: lwarx r19,0,r18 /* (TEST/DEBUG) */ mr. r19,r19 /* (TEST/DEBUG) */ bne- mpwait6 /* (TEST/DEBUG) */ stwcx. r18,0,r18 /* (TEST/DEBUG) */ bne- mpwait6 /* (TEST/DEBUG) */ stw r0,0x280(br0) /* (TEST/DEBUG) */ stmw r1,0x284(br0) /* (TEST/DEBUG) */ bne cr7,nono5 /* (TEST/DEBUG) */ lwz r0,0(br0) /* (TEST/DEBUG) */ mr. r0,r0 /* (TEST/DEBUG) */ beq+ nono5 /* (TEST/DEBUG) */ bne cr6,nopir16 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir16 /* (TEST/DEBUG) */ nopir16: li r4,0 /* (TEST/DEBUG) */ gotpir16: /* (TEST/DEBUG) */ rlwinm r24,r31,0,0,19 /* (TEST/DEBUG) */ mr r5,r31 /* (TEST/DEBUG) */ mr r30,r31 /* (TEST/DEBUG) */ lwz r24,SACvrswap(r24) /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3730 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir17 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir17 /* (TEST/DEBUG) */ nopir17: li r4,0 /* (TEST/DEBUG) */ gotpir17: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ xor r5,r30,r24 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3731 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir18 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir18 /* (TEST/DEBUG) */ nopir18: li r4,0 /* (TEST/DEBUG) */ gotpir18: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ mfsprg r5,1 /* (TEST/DEBUG) */ oris r4,r4,0x3030 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3830 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir19 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir19 /* (TEST/DEBUG) */ nopir19: li r4,0 /* (TEST/DEBUG) */ gotpir19: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ lwz r5,savesrr0(r30) /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3130 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir20 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir20 /* (TEST/DEBUG) */ nopir20: li r4,0 /* (TEST/DEBUG) */ gotpir20: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ lwz r5,savesrr1(r30) /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3131 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ bne cr6,nopir21 /* (TEST/DEBUG) */ mfspr r4,pir /* (TEST/DEBUG) */ b gotpir21 /* (TEST/DEBUG) */ nopir21: li r4,0 /* (TEST/DEBUG) */ gotpir21: /* (TEST/DEBUG) */ lis r31,HIGH_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ rlwinm r4,r4,24,4,7 /* (TEST/DEBUG) */ li r3,0 /* (TEST/DEBUG) */ lwz r5,savelr(r30) /* (TEST/DEBUG) */ oris r4,r4,0x3031 /* (TEST/DEBUG) */ ori r31,r31,LOW_ADDR(EXT(dbgDispLL)) /* (TEST/DEBUG) */ ori r4,r4,0x3132 /* (TEST/DEBUG) */ mtlr r31 /* (TEST/DEBUG) */ blrl /* (TEST/DEBUG) */ nono5: lmw r1,0x284(br0) /* (TEST/DEBUG) */ lwz r0,0x280(br0) /* (TEST/DEBUG) */ li r19,0 /* (TEST/DEBUG) */ stw r19,0x20(br0) /* (TEST/DEBUG) */ mtdec r25 /* (TEST/DEBUG) */ #endif /* * It's dangerous here. We haven't restored anything from the current savearea yet. * And, we mark it the active one. So, if we get an exception in here, it is * unrecoverable. Unless we mess up, we can't get any kind of exception. So, * it is important to assay this code as only the purest of gold. * * But first, see if there is a savearea hanging off of quickfret. If so, * we release that one first and then come back for the other. We should rarely * see one, they appear when FPU or VMX context is discarded by either returning * to a higher exception level, or explicitly. * * A word about QUICKFRET: Multiple saveareas may be queued for release. It is * the responsibility of the queuer to insure that the savearea is not multiply * queued and that the appropriate inuse bits are reset. */ #define TRCSAVE 0 #if TRCSAVE lwz r30,saver0(r31) ; (TEST/DEBUG) Get users R0 lwz r20,saveexception(r31) ; (TEST/DEBUG) Returning from trace? xor r30,r20,r30 ; (TEST/DEBUG) Make code rlwinm r30,r30,1,0,31 ; (TEST/DEBUG) Make an easy test cmplwi cr5,r30,0x61 ; (TEST/DEBUG) See if this is a trace #endif mr r18,r31 /* Save the savearea pointer */ lwz r19,PP_QUICKFRET(r2) /* Get the quick release savearea */ la r20,savesrr0(r18) /* Point to the first thing we look at */ li r0,0 /* Get a zero */ dcbt 0,r20 /* Touch in the first thing in the real savearea */ la r21,savesr0(r18) /* Point to the first thing we restore */ lis r30,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ stw r0,PP_QUICKFRET(r2) /* Clear quickfret pointer */ ori r30,r30,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ dcbt 0,r21 /* Touch in the first thing */ #if TRCSAVE beq- cr5,trkill0 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill0 ; (TEST/DEBUG) yes... bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea trkill0: #endif lwarx r22,0,r30 ; ? rtlck: lwarx r22,0,r30 /* Grab the lock value */ li r23,1 /* Use part of the delay time */ mr. r22,r22 /* Is it locked? */ bne- rtlcks /* Yeah, wait for it to clear... */ stwcx. r23,0,r30 /* Try to seize that there durn lock */ beq+ fretagain ; Got it... b rtlck /* Collision, try again... */ rtlcks: lwz r22,SVlock(r30) /* Get that lock in here */ mr. r22,r22 /* Is it free yet? */ beq+ rtlck /* Yeah, try for it again... */ b rtlcks /* Sniff away... */ ; ; Lock gotten, toss the saveareas ; fretagain: #if TRCSAVE beq- cr5,trkill1 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill1 ; (TEST/DEBUG) yes... li r0,1 ; (TEST/DEBUG) ID number bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) Quickfret savearea trkill1: #endif mr. r18,r18 ; Are we actually done here? beq- donefret ; Yeah... mr. r31,r19 ; Is there a quickfret to do? beq+ noqfrt ; Nope... lwz r19,SAVqfret(r19) ; Yes, get the next in line #if TRCSAVE beq- cr5,trkill2 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill2 ; (TEST/DEBUG) yes... li r0,2 ; (TEST/DEBUG) ID number bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss trkill2: #endif b doqfrt ; Go do it... noqfrt: mr r31,r18 ; Set the area to release li r18,0 ; Show we have done it #if TRCSAVE beq- cr5,trkill3 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill3 ; (TEST/DEBUG) yes... li r0,3 ; (TEST/DEBUG) ID number bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss trkill3: #endif doqfrt: li r0,0 ; Get a constant 0 lis r26,0x8000 /* Build a bit mask and assume first savearea */ stw r0,SAVqfret(r31) ; Make sure back chain is unlinked lwz r28,SAVflags(r31) ; Get the flags for the old active one #if TRCSAVE beq- cr5,trkill4 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill4 ; (TEST/DEBUG) yes... li r0,4 ; (TEST/DEBUG) ID number bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) next quickfret savearea stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss stw r28,LTR_r4(r20) ; (TEST/DEBUG) Save current flags trkill4: #endif rlwinm r25,r31,21,31,31 /* Get position of savearea in block */ andis. r28,r28,HIGH_ADDR(SAVinuse) /* See if we need to free it */ srw r26,r26,r25 /* Get bit position to deallocate */ rlwinm r29,r31,0,0,19 /* Round savearea pointer to even page address */ bne- fretagain /* Still in use, we can't free this one... */ lwz r23,SACalloc(r29) /* Get the allocation for this block */ lwz r24,SVinuse(r30) /* Get the in use count */ mr r28,r23 ; (TEST/DEBUG) save for trace or r23,r23,r26 /* Turn on our bit */ subi r24,r24,1 /* Show that this one is free */ cmplw r23,r26 /* Is our's the only one free? */ stw r23,SACalloc(r29) /* Save it out */ bne+ rstrest /* Nope, then the block is already on the free list */ lwz r22,SVfree(r30) /* Get the old head of the free list */ stw r29,SVfree(r30) /* Point the head at us now */ stw r22,SACnext(r29) ; Point us to the old last rstrest: stw r24,SVinuse(r30) /* Set the in use count */ #if TRCSAVE beq- cr5,trkill5 ; (TEST/DEBUG) Do not trace this type lwz r14,LOW_ADDR(traceMask-EXT(ExceptionVectorsStart))(br0) ; (TEST/DEBUG) Get the trace mask mr. r14,r14 ; (TEST/DEBUG) Is it stopped? beq- trkill5 ; (TEST/DEBUG) yes... li r0,5 ; (TEST/DEBUG) ID number bl cte ; (TEST/DEBUG) Trace this stw r18,LTR_r1(r20) ; (TEST/DEBUG) Normal savearea stw r19,LTR_r2(r20) ; (TEST/DEBUG) Next quickfret savearea stw r31,LTR_r3(r20) ; (TEST/DEBUG) Current one to toss stw r28,LTR_srr1(r20) ; (TEST/DEBUG) Save the original allocation stw r23,LTR_dar(r20) ; (TEST/DEBUG) Save the new allocation stw r24,LTR_save(r20) ; (TEST/DEBUG) Save the new in use count stw r22,LTR_lr(r20) ; (TEST/DEBUG) Save the old top of free list stw r29,LTR_ctr(r20) ; (TEST/DEBUG) Save the new top of free list trkill5: #endif b fretagain ; Go finish up the rest... ; ; Build the SR values depending upon destination. If we are going to the kernel, ; the SRs are almost all the way set up. SR14 (or the currently used copyin/out register) ; must be set to whatever it was at the last exception because it varies. All the rest ; have been set up already. ; ; If we are going into user space, we need to check a bit more. SR0, SR1, SR2, and ; SR14 (current implementation) must be restored always. The others must be set if ; they are different that what was loaded last time (i.e., tasks have switched). ; We check the last loaded address space ID and if the same, we skip the loads. ; This is a performance gain because SR manipulations are slow. ; donefret: lwz r26,savesrr1(r31) ; Get destination state flags lwz r15,PP_USERSPACE(r2) ; Pick up the user space ID we may launch rlwinm. r17,r26,0,MSR_PR_BIT,MSR_PR_BIT ; See if we are going to user or system lwz r16,PP_LASTSPACE(r2) ; Pick up the last loaded SR value oris r13,r15,hi16(SEG_REG_PROT) ; Get the protection bits correct cmplw cr3,r15,r15 ; Set that we do not need to stop streams addis r14,r13,0x0010 ; Generate next SR value beq- gotokern ; We are going into kernel state, SRs all set up... mtsr sr0,r13 ; Set SR0 addis r13,r14,0x0010 ; Generate next SR value cmplw cr3,r15,r16 ; See if most of the SRs are already loaded mtsr sr1,r14 ; Set SR1 addis r14,r13,0x0010 ; Generate next SR value mtsr sr2,r13 ; Set SR2 addis r13,r14,0x0010 ; Generate next SR value mtsr sr3,r14 ; Set SR3 beq+ cr3,noloadsr ; SRs have not changed, no reload... addis r14,r13,0x0010 ; Generate next SR value mtsr sr4,r13 ; Set SR4 addis r13,r14,0x0010 ; Generate next SR value mtsr sr5,r14 ; Set SR5 addis r14,r13,0x0010 ; Generate next SR value mtsr sr6,r13 ; Set SR6 addis r13,r14,0x0010 ; Generate next SR value mtsr sr7,r14 ; Set SR7 addis r14,r13,0x0010 ; Generate next SR value mtsr sr8,r13 ; Set SR8 addis r13,r14,0x0010 ; Generate next SR value mtsr sr9,r14 ; Set SR9 addis r14,r13,0x0010 ; Generate next SR value mtsr sr10,r13 ; Set SR10 addis r13,r14,0x0010 ; Generate next SR value mtsr sr11,r14 ; Set SR11 addis r14,r13,0x0010 ; Generate next SR value mtsr sr12,r13 ; Set SR12 addis r13,r14,0x0010 ; Generate next SR value mtsr sr13,r14 ; Set SR13 addis r14,r13,0x0010 ; Generate next SR value mtsr sr14,r13 ; Set SR14 mtsr sr15,r14 ; Set SR15 stw r15,PP_LASTSPACE(r2) ; Set the last loaded SR value b ngotokern ; All done with user state SRs... noloadsr: oris r14,r15,hi16(SEG_REG_PROT|0x00E00000) ; Build SR14 (copyin/out) value b loadsr14 ; All done with user state SRs (except for SR14)... gotokern: lwz r14,savesr14(r31) ; Get the copyin/out register at interrupt time loadsr14: mtsr sr14,r14 ; Set SR14 ngotokern: lwz r25,savesrr0(r31) /* Get the SRR0 to use */ la r28,saver6(r31) /* Point to the next line to use */ lwz r0,saver0(r31) /* Restore */ dcbt 0,r28 /* Touch it in */ lwz r1,saver1(r31) /* Restore */ lwz r2,saver2(r31) /* Restore */ la r28,saver14(r31) /* Point to the next line to get */ lwz r3,saver3(r31) /* Restore */ mtsrr0 r25 /* Restore the SRR0 now */ lwz r4,saver4(r31) /* Restore */ lwz r5,saver5(r31) /* Restore */ mtsrr1 r26 /* Restore the SRR1 now */ lwz r6,saver6(r31) /* Restore */ dcbt 0,r28 /* Touch that next line on in */ lwz r7,saver7(r31) /* Restore */ lwz r8,saver8(r31) /* Restore */ lwz r9,saver9(r31) /* Restore */ lwz r10,saver10(r31) /* Restore */ lwz r11,saver11(r31) /* Restore */ lwz r12,saver12(r31) /* Restore */ lwz r13,saver13(r31) /* Restore */ la r28,saver22(r31) /* Point to the next line to do */ lwz r14,saver14(r31) /* Restore */ lwz r15,saver15(r31) /* Restore */ dcbt 0,r28 /* Touch in another line of context */ lwz r16,saver16(r31) /* Restore */ lwz r17,saver17(r31) /* Restore */ lwz r18,saver18(r31) /* Restore */ lwz r19,saver19(r31) /* Restore */ lwz r20,saver20(r31) /* Restore */ lwz r21,saver21(r31) /* Restore */ la r28,saver30(r31) /* Point to the final line */ lwz r22,saver22(r31) /* Restore */ dcbt 0,r28 /* Suck it in */ lwz r23,saver23(r31) /* Restore */ mfpvr r27 ; Get the processor version lwz r24,saver24(r31) /* Restore */ rlwinm r27,r27,16,16,31 ; Get the processor type lwz r25,saver25(r31) /* Restore */ cmplwi cr1,r27,PROCESSOR_VERSION_Max ; Do we have Altivec? */ lwz r26,saver26(r31) /* Restore */ lwz r27,saver27(r31) /* Restore */ dcbt 0,r28 /* Get the final line */ lwz r28,savecr(r31) /* Get CR to restore */ blt cr1,noavec4 ; No vector on this machine lwz r29,savevrsave(r31) ; Get the vrsave beq+ cr3,noavec3 ; SRs have not changed, no need to stop the streams... dssall ; Kill all data streams ; The streams should be suspended ; already, and we do a bunch of ; dependent loads and a sync later ; so we should be cool. noavec3: mtspr vrsave,r29 ; Set the vrsave noavec4: lwz r29,savexer(r31) /* Get XER to restore */ mtcr r28 /* Restore the CR */ lwz r28,savelr(r31) /* Get LR to restore */ mtxer r29 /* Restore the XER */ lwz r29,savectr(r31) /* Get the CTR to restore */ mtlr r28 /* Restore the LR */ lwz r28,saver30(r31) /* Restore */ mtctr r29 /* Restore the CTR */ lwz r29,saver31(r31) /* Restore */ mtsprg 2,r28 /* Save R30 */ lwz r28,saver28(r31) /* Restore */ mtsprg 3,r29 /* Save R31 */ lwz r29,saver29(r31) /* Restore */ #if PERFTIMES && DEBUG stmw r1,0x280(br0) ; Save all registers mfcr r20 ; Save the CR mflr r21 ; Save the LR mfsrr0 r9 ; Save SRR0 mfsrr1 r11 ; Save SRR1 mr r8,r0 ; Save R0 li r3,69 ; Indicate interrupt mr r4,r11 ; Set MSR to log mr r5,r31 ; Get savearea to log bl EXT(dbgLog2) ; Cut log entry mr r0,r8 ; Restore R0 mtsrr0 r9 ; Restore SRR0 mtsrr1 r11 ; Restore SRR1 mtlr r21 ; Restore the LR mtcr r20 ; Restore the CR lmw r1,0x280(br0) ; Restore all the rest #endif li r31,0 /* Get set to clear lock */ sync /* Make sure it's all out there */ stw r31,SVlock(r30) /* Unlock it */ mfsprg r30,2 /* Restore R30 */ mfsprg r31,3 /* Restore R31 */ rfi /* Click heels three times and think very hard that there's no place like home */ .long 0 /* For old 601 bug */ .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 .long 0 /* * exception_exit(savearea *) * * * ENTRY : IR and/or DR and/or interruptions can be on * R3 points to the physical address of a savearea */ .align 5 .globl EXT(exception_exit) nop ; Align ISYNC to last line in cache nop LEXT(exception_exit) mfmsr r30 /* Get the current MSR */ mr r31,r3 /* Get the savearea in the right register */ andi. r30,r30,0x7FCF /* Turn off externals, IR, and DR */ lis r1,hi16(SAVredrive) ; Get redrive request mtmsr r30 /* Translation and all off */ isync /* Toss prefetch */ mfsprg r2,0 ; Get the per_proc block lwz r4,SAVflags(r3) ; Pick up the flags mr r13,r3 ; Put savearea here also and. r0,r4,r1 ; Check if redrive requested andc r4,r4,r1 ; Clear redrive dcbt br0,r2 ; We will need this in just a sec beq+ EatRupt ; No redrive, just exit... lwz r3,saveexception(r13) ; Restore exception code stw r4,SAVflags(r13) ; Set the flags b Redrive ; Redrive the exception... ; ; Make trace entry for lowmem_vectors internal debug ; #if TRCSAVE cte: lwz r20,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Pick up the current trace entry lwz r16,LOW_ADDR(EXT(traceEnd)-EXT(ExceptionVectorsStart))(br0) ; Grab up the end of it all addi r17,r20,LTR_size ; Point to the next trace entry cmplw r17,r16 ; Do we need to wrap the trace table? li r15,32 ; Second line of entry bne+ ctenwrap ; We got a trace entry... lwz r17,LOW_ADDR(EXT(traceStart)-EXT(ExceptionVectorsStart))(br0) ; Wrap back to the top ctenwrap: stw r17,LOW_ADDR(EXT(traceCurr)-EXT(ExceptionVectorsStart))(br0) ; Set the next entry for the next guy dcbz 0,r20 ; Allocate cache for the entry dcbz r15,r20 ; Zap the second half ctegetTB: mftbu r16 ; Get the upper timebase mftb r17 ; Get the lower timebase mftbu r15 ; Get the upper one again cmplw r16,r15 ; Did the top tick? bne- ctegetTB ; Yeah, need to get it again... li r15,0x111 ; Get the special trace ID code stw r0,LTR_r0(r20) ; Save R0 (usually used as an ID number stw r16,LTR_timeHi(r20) ; Set the upper part of TB mflr r16 ; Get the return point stw r17,LTR_timeLo(r20) ; Set the lower part of TB sth r15,LTR_excpt(r20) ; Save the exception type stw r16,LTR_srr0(r20) ; Save the return point blr ; Leave... #endif /* * Start of the trace table */ .align 12 /* Align to 4k boundary */ traceTableBeg: /* Start of trace table */ /* .fill 2048,4,0 Make an 8k trace table for now */ .fill 13760,4,0 /* Make an .trace table for now */ /* .fill 240000,4,0 Make an .trace table for now */ traceTableEnd: /* End of trace table */ .globl EXT(ExceptionVectorsEnd) EXT(ExceptionVectorsEnd): /* Used if relocating the exception vectors */ #ifndef HACKALERTHACKALERT /* * This .long needs to be here because the linker gets confused and tries to * include the final label in a section in the next section if there is nothing * after it */ .long 0 /* (HACK/HACK/HACK) */ #endif .data .align ALIGN .globl EXT(exception_end) EXT(exception_end): .long EXT(ExceptionVectorsEnd) -EXT(ExceptionVectorsStart) /* phys fn */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.