X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..43866e378188c25dd1e2208016ab3cbeb086ae6c:/osfmk/ppc/machine_routines_asm.s diff --git a/osfmk/ppc/machine_routines_asm.s b/osfmk/ppc/machine_routines_asm.s index 48e918762..e81d931cd 100644 --- a/osfmk/ppc/machine_routines_asm.s +++ b/osfmk/ppc/machine_routines_asm.s @@ -3,19 +3,22 @@ * * @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. + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The 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. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -45,6 +48,8 @@ LEXT(ml_probe_read) mfsprg r9,2 ; Get feature flags mfmsr r0 ; Save the current MSR + rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off neg r10,r3 ; Number of bytes to end of page rlwinm r2,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions rlwinm. r10,r10,0,20,31 ; Clear excess junk and test for page bndry @@ -72,18 +77,28 @@ mprNoMSR: mr r0,r5 li r3,0 mprNoMSRx: + + mfspr r6, hid0 ; Get a copy of hid0 + + rlwinm. r5, r9, 0, pfNoMuMMCKb, pfNoMuMMCKb ; Check for NoMuMMCK + bne mprNoMuM + rlwinm r5, r6, 0, ice+1, ice-1 ; Turn off L1 I-Cache + mtspr hid0, r5 + isync ; Wait for I-Cache off + rlwinm r5, r6, 0, mum+1, mum-1 ; Turn off MuM w/ I-Cache on + mtspr hid0, r5 +mprNoMuM: + ; ; We need to insure that there is no more than 1 BAT register that ; can get a hit. There could be repercussions beyond the ken ; of mortal man. It is best not to tempt fate. ; + +; Note: we will reload these from the shadow BATs later + li r10,0 ; Clear a register - mfdbatu r5,0 ; Save DBAT 0 high - mfdbatl r6,0 ; Save DBAT 0 low - mfdbatu r7,1 ; Save DBAT 1 high - mfdbatu r8,2 ; Save DBAT 2 high - mfdbatu r9,3 ; Save DBAT 3 high sync ; Make sure all is well @@ -98,6 +113,9 @@ mprNoMSRx: mtdbatu 0,r10 ; Now the upper sync ; Just make sure + dcbf 0,r12 ; Make sure we kill the cache to avoid paradoxes + sync + ori r11,r2,lo16(MASK(MSR_DR)) ; Turn on data translation mtmsr r11 ; Do it for real isync ; Make sure of it @@ -111,6 +129,21 @@ mprNoMSRx: sync ; Get caught up yet again isync ; Do not go further till we are here + mtmsr r2 ; Turn translation back off + isync + + mtspr hid0, r6 ; Restore HID0 + isync + + lis r10,hi16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address + ori r10,r10,lo16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address + + lwz r5,0(r10) ; Pick up DBAT 0 high + lwz r6,4(r10) ; Pick up DBAT 0 low + lwz r7,8(r10) ; Pick up DBAT 1 high + lwz r8,16(r10) ; Pick up DBAT 2 high + lwz r9,24(r10) ; Pick up DBAT 3 high + mtdbatu 0,r5 ; Restore DBAT 0 high mtdbatl 0,r6 ; Restore DBAT 0 low mtdbatu 1,r7 ; Restore DBAT 1 high @@ -145,7 +178,9 @@ LEXT(ml_probe_read_mck) LEXT(ml_phys_read_byte) mfmsr r10 ; Save the current MSR - rlwinm r4,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions + rlwinm r10,r10,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r10,r10,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off + rlwinm r4,r10,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions rlwinm r4,r4,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear translation mtmsr r4 ; Translation and all off @@ -172,6 +207,8 @@ LEXT(ml_phys_read_byte) LEXT(ml_phys_read) mfmsr r0 ; Save the current MSR + rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r4,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions rlwinm r4,r4,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear translation @@ -199,6 +236,8 @@ LEXT(ml_phys_read) LEXT(ml_phys_write_byte) mfmsr r0 ; Save the current MSR + rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r5,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear translation @@ -226,6 +265,8 @@ LEXT(ml_phys_write_byte) LEXT(ml_phys_write) mfmsr r0 ; Save the current MSR + rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r5,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear interruptions rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear translation @@ -248,39 +289,61 @@ LEXT(ml_phys_write) */ ; Force a line boundry here - .align 5 - .globl EXT(set_interrupts_enabled) - -LEXT(set_interrupts_enabled) + .align 5 + .globl EXT(ml_set_interrupts_enabled) + +LEXT(ml_set_interrupts_enabled) + mfsprg r7,0 + lwz r4,PP_INTS_ENABLED(r7) + mr. r4,r4 + beq- EXT(fake_set_interrupts_enabled) mfmsr r5 ; Get the current MSR + rlwinm r5,r5,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off mr r4,r3 ; Save the old value + rlwinm r5,r5,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r3,r5,17,31,31 ; Set return value rlwimi r5,r4,15,16,16 ; Insert new EE bit - andi. r7,r5,lo16(MASK(MSR_EE)) ; Interruptions + andi. r8,r5,lo16(MASK(MSR_EE)) ; Interruptions bne CheckPreemption NoPreemption: mtmsr r5 ; Slam enablement blr CheckPreemption: - mfsprg r7,0 lwz r8,PP_NEED_AST(r7) - lwz r7,PP_CPU_DATA(r7) li r6,AST_URGENT lwz r8,0(r8) - lwz r7,CPU_PREEMPTION_LEVEL(r7) + lwz r7,PP_PREEMPT_CNT(r7) lis r0,HIGH_ADDR(DoPreemptCall) and. r8,r8,r6 ori r0,r0,LOW_ADDR(DoPreemptCall) - beq+ NoPreemption + beq+ NoPreemption cmpi cr0, r7, 0 - bne+ NoPreemption - sc - mtmsr r5 + mtmsr r5 ; Restore the MSR now, before we can preempt + bnelr+ ; Return if no premption + sc ; Preempt blr +/* Emulate a decremeter exception + * + * void machine_clock_assist(void) + * + */ + +; Force a line boundry here + .align 5 + .globl EXT(machine_clock_assist) + +LEXT(machine_clock_assist) + + mfsprg r7,0 + lwz r4,PP_INTS_ENABLED(r7) + mr. r4,r4 + beq- EXT(CreateFakeDEC) + blr + /* Set machine into idle power-saving mode. * * void machine_idle_ppc(void) @@ -299,8 +362,11 @@ CheckPreemption: LEXT(machine_idle_ppc) mfmsr r3 ; Get the current MSR + rlwinm r3,r3,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r3,r3,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r5,r3,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions mtmsr r5 ; Hold up interruptions for now + isync ; May have messed with fp/vec mfsprg r12,0 ; Get the per_proc_info mfspr r6,hid0 ; Get the current power-saving mode mfsprg r11,2 ; Get CPU specific features @@ -324,53 +390,26 @@ yesnap: mftbu r9 ; Get the upper timebase bne- yesnap ; Yeah, need to get it again... stw r8,napStamp(r12) ; Set high order time stamp stw r7,napStamp+4(r12) ; Set low order nap stamp - - bf pfL1nncb,minoflushl1 ; The L1 is coherent in nap/doze... -; -; 7450 does not keep L1 cache coherent across nap/sleep it must alwasy flush. -; It does not have a L1 flush assist, so we do not test for it here. -; -; Note that the time stamp take above is not completely accurate for 7450 -; because we are about to flush the L1 cache and that takes a bit of time. -; - cror cr0_eq,pfL1ib,pfL1db ; Check for either I- or D-cache - bf- cr0_eq,minoflushl1 ; No level 1 to flush... - rlwinm. r0,r4,0,ice,dce ; Were either of the level 1s on? - beq- minoflushl1 ; No, no need to flush... -miswdl1: lwz r0,pfl1dSize(r12) ; Get the level 1 cache size - rlwinm r2,r0,0,1,30 ; Double it - add r0,r0,r2 ; Get 3 times cache size - rlwinm r2,r5,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Turn off data translation - rlwinm r0,r0,26,6,31 ; Get 3/2 number of cache lines - lis r3,0xFFF0 ; Dead recon ROM address for now - mtctr r0 ; Number of lines to flush - mtmsr r2 ; Do it - isync + rlwinm. r7,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before nap? + beq miL2PFok -miswfldl1a: lwz r2,0(r3) ; Flush anything else - addi r3,r3,32 ; Next line - bdnz miswfldl1a ; Flush the lot... - -miinvdl1: sync ; Make sure all flushes have been committed - mtmsr r5 ; Put back data translation + mfspr r7,msscr0 ; Get currect MSSCR0 value + rlwinm r7,r7,0,0,l2pfes-1 ; Dissable L2 Prefetch + mtspr msscr0,r7 ; Updates MSSCR0 value + sync isync - mfspr r8,hid0 ; Get the HID0 bits - li r7,lo16(icem|dcem) ; Get the cache enable bits - andc r8,r8,r7 ; Clear cache enables - mtspr hid0,r8 ; and turn off L1 cache - sync ; Make sure all is done - - ori r8,r8,lo16(icfim|dcfim) ; Set the HID0 bits for invalidate - sync - isync - - mtspr hid0,r8 ; Start the invalidate - sync - -minoflushl1: - +miL2PFok: + rlwinm. r7,r11,0,pfSlowNapb,pfSlowNapb ; Should nap at slow speed? + beq minoslownap + + mfspr r7,hid1 ; Get current HID1 value + oris r7,r7,hi16(hid1psm) ; Select PLL1 + mtspr hid1,r7 ; Update HID1 value + +minoslownap: + ; ; We have to open up interruptions here because book 4 says that we should ; turn on only the POW bit and that we should have interrupts enabled @@ -433,22 +472,26 @@ LEXT(ml_ppc_sleep) mtmsr r5 ; No talking isync -; No interrupts allowed after we get the savearea - - mfsprg r6,0 ; Get the per_proc - mfsprg r7,1 ; Get the pending savearea - stw r7,savedSave(r6) ; Save the savearea for when we wake up - deadsleep: addi r3,r3,1 ; Make analyzer happy addi r3,r3,1 addi r3,r3,1 b deadsleep ; Die the death of 1000 joys... #endif - mfsprg r12,0 ; Get the per_proc_info mfspr r4,hid0 ; Get the current power-saving mode eqv r10,r10,r10 ; Get all foxes mfsprg r11,2 ; Get CPU specific features + + rlwinm. r5,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before sleep? + beq mpsL2PFok + + mfspr r5,msscr0 ; Get currect MSSCR0 value + rlwinm r5,r5,0,0,l2pfes-1 ; Dissable L2 Prefetch + mtspr msscr0,r5 ; Updates MSSCR0 value + sync + isync + +mpsL2PFok: mfmsr r5 ; Get the current MSR rlwinm r10,r10,0,1,31 ; Make 0x7FFFFFFF rlwinm r4,r4,0,sleep+1,doze-1 ; Clear all possible power-saving modes (not DPM though) @@ -489,9 +532,6 @@ mpsNoMSRx: mtmsr r5 ; Interruptions back off isync ; Toss prefetch - mfsprg r7,1 ; Get the pending savearea - stw r7,savedSave(r12) ; Save the savearea for when we wake up - ; ; We are here with translation off, interrupts off, all possible ; interruptions drained off, and a decrimenter that will not pop. @@ -537,7 +577,9 @@ LEXT(cacheInit) mfsprg r11,2 ; Get CPU specific features mfmsr r7 ; Get the current MSR rlwinm r4,r9,0,dpm+1,doze-1 ; Clear all possible power-saving modes (also disable DPM) - rlwimi r11,r11,pfL23lckb+1,31,31 ; Move pfL23lck to another position (to keep from using non-volatile CRs) + rlwinm r7,r7,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r7,r7,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off + rlwimi r11,r11,pfLClckb+1,31,31 ; Move pfLClck to another position (to keep from using non-volatile CRs) rlwinm r5,r7,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions mtcrf 0x87,r11 ; Get the feature flags @@ -565,7 +607,6 @@ cinoDSS: lis r5,hi16(EXT(tlb_system_lock)) ; Get the TLBIE lock ori r5,r5,lo16(EXT(tlb_system_lock)) ; Grab up the bottom part li r6,0 ; Start at 0 - lwarx r2,0,r5 ; ? citlbhang: lwarx r2,0,r5 ; Get the TLBIE lock mr. r2,r2 ; Is it locked? @@ -587,6 +628,7 @@ cipurgeTLB: tlbie r6 ; Purge this entry tlbsync ; Sync all TLBs sync + isync cinoSMP: stw r2,0(r5) ; Unlock TLBIE lock @@ -620,7 +662,74 @@ ciwdl1f: mfspr r8,msscr0 ; Get the control register again ; ciswdl1: lwz r0,pfl1dSize(r12) ; Get the level 1 cache size - rlwinm r2,r0,0,1,30 ; Double it + + bf 31,cisnlck ; Skip if pfLClck not set... + + mfspr r4,msscr0 ; ? + rlwinm r6,r4,0,0,l2pfes-1 ; ? + mtspr msscr0,r6 ; Set it + sync + isync + + mfspr r8,ldstcr ; Save the LDSTCR + li r2,1 ; Get a mask of 0x01 + lis r3,0xFFF0 ; Point to ROM + rlwinm r11,r0,29,3,31 ; Get the amount of memory to handle all indexes + + li r6,0 ; Start here + +cisiniflsh: dcbf r6,r3 ; Flush each line of the range we use + addi r6,r6,32 ; Bump to the next + cmplw r6,r0 ; Have we reached the end? + blt+ cisiniflsh ; Nope, continue initial flush... + + sync ; Make sure it is done + + addi r11,r11,-1 ; Get mask for index wrap + li r6,0 ; Get starting offset + +cislckit: not r5,r2 ; Lock all but 1 way + rlwimi r5,r8,0,0,23 ; Build LDSTCR + mtspr ldstcr,r5 ; Lock a way + sync ; Clear out memory accesses + isync ; Wait for all + + +cistouch: lwzx r10,r3,r6 ; Pick up some trash + addi r6,r6,32 ; Go to the next index + and. r0,r6,r11 ; See if we are about to do next index + bne+ cistouch ; Nope, do more... + + sync ; Make sure it is all done + isync + + sub r6,r6,r11 ; Back up to start + 1 + addi r6,r6,-1 ; Get it right + +cisflush: dcbf r3,r6 ; Flush everything out + addi r6,r6,32 ; Go to the next index + and. r0,r6,r11 ; See if we are about to do next index + bne+ cisflush ; Nope, do more... + + sync ; Make sure it is all done + isync + + + rlwinm. r2,r2,1,24,31 ; Shift to next way + bne+ cislckit ; Do this for all ways... + + mtspr ldstcr,r8 ; Slam back to original + sync + isync + + mtspr msscr0,r4 ; ? + sync + isync + + b cinoL1 ; Go on to level 2... + + +cisnlck: rlwinm r2,r0,0,1,30 ; Double cache size add r0,r0,r2 ; Get 3 times cache size rlwinm r0,r0,26,6,31 ; Get 3/2 number of cache lines lis r3,0xFFF0 ; Dead recon ROM address for now @@ -636,7 +745,8 @@ ciinvdl1: sync ; Make sure all flushes have been committed rlwinm r8,r8,0,dce+1,ice-1 ; Clear cache enables mtspr hid0,r8 ; and turn off L1 cache sync ; Make sure all is done - + isync + ori r8,r8,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate sync isync @@ -645,6 +755,7 @@ ciinvdl1: sync ; Make sure all flushes have been committed rlwinm r8,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits mtspr hid0,r8 ; Turn off the invalidate (needed for some older machines) sync + cinoL1: ; @@ -654,17 +765,22 @@ cinoL1: mfspr r8,l2cr ; Get the L2CR lwz r3,pfl2cr(r12) ; Get the L2CR value + rlwinm. r0,r8,0,l2e,l2e ; Was the L2 enabled? + bne ciflushl2 ; Yes, force flush + cmplwi r8, 0 ; Was the L2 all the way off? + beq ciinvdl2 ; Yes, force invalidate lis r0,hi16(l2sizm|l2clkm|l2ramm|l2ohm) ; Get confiuration bits xor r2,r8,r3 ; Get changing bits? ori r0,r0,lo16(l2slm|l2dfm|l2bypm) ; More config bits and. r0,r0,r2 ; Did any change? bne- ciinvdl2 ; Yes, just invalidate and get PLL synced... +ciflushl2: bf pfL2fab,ciswfl2 ; Flush not in hardware... - mr r10,r3 ; Take a copy now + mr r10,r8 ; Take a copy now - bf 31,cinol2lck ; Skip if pfL23lck not set... + bf 31,cinol2lck ; Skip if pfLClck not set... oris r10,r10,hi16(l2ionlym|l2donlym) ; Set both instruction- and data-only sync @@ -684,10 +800,25 @@ cihwfl2: mfspr r10,l2cr ; Get back the L2CR ciswfl2: lwz r0,pfl2Size(r12) ; Get the L2 size - oris r2,r3,hi16(l2dom) ; Set L2 to data only mode - mtspr l2cr,r2 ; Go into data only mode - sync ; Clean it up - + oris r2,r8,hi16(l2dom) ; Set L2 to data only mode + + b ciswfl2doa ; Branch to next line... + + .align 5 +ciswfl2doc: + mtspr l2cr,r2 ; Disable L2 + sync + isync + b ciswfl2dod ; It is off, go invalidate it... + +ciswfl2doa: + b ciswfl2dob ; Branch to next... + +ciswfl2dob: + sync ; Finish memory stuff + isync ; Stop speculation + b ciswfl2doc ; Jump back up and turn on data only... +ciswfl2dod: rlwinm r0,r0,27,5,31 ; Get the number of lines lis r10,0xFFF0 ; Dead recon ROM for now mtctr r0 ; Set the number of lines @@ -696,11 +827,11 @@ ciswfldl2a: lwz r0,0(r10) ; Load something to flush something addi r10,r10,32 ; Next line bdnz ciswfldl2a ; Do the lot... -ciinvdl2: rlwinm r3,r3,0,l2e+1,31 ; Clear the enable bit +ciinvdl2: rlwinm r8,r3,0,l2e+1,31 ; Use the saved L2CR and clear the enable bit b cinla ; Branch to next line... .align 5 -cinlc: mtspr l2cr,r3 ; Disable L2 +cinlc: mtspr l2cr,r8 ; Disable L2 sync isync b ciinvl2 ; It is off, go invalidate it... @@ -713,7 +844,11 @@ cinlb: sync ; Finish memory stuff ciinvl2: sync isync - oris r2,r3,hi16(l2im) ; Get the invalidate flag set + + cmplwi r3, 0 ; Should the L2 be all the way off? + beq cinol2 ; Yes, done with L2 + + oris r2,r8,hi16(l2im) ; Get the invalidate flag set mtspr l2cr,r2 ; Start the invalidate sync @@ -728,7 +863,7 @@ ciinvdl2b: rlwinm. r2,r2,0,l2ip,l2ip ; Is the invalidate still going? bne+ ciinvdl2a ; Assume so, this will take a looong time... sync - mtspr l2cr,r3 ; Turn off the invalidate request + mtspr l2cr,r8 ; Turn off the invalidate request cinol2: @@ -739,14 +874,19 @@ cinol2: mfspr r8,l3cr ; Get the L3CR lwz r3,pfl3cr(r12) ; Get the L3CR value + rlwinm. r0,r8,0,l3e,l3e ; Was the L3 enabled? + bne ciflushl3 ; Yes, force flush + cmplwi r8, 0 ; Was the L3 all the way off? + beq ciinvdl3 ; Yes, force invalidate lis r0,hi16(l3pem|l3sizm|l3dxm|l3clkm|l3spom|l3ckspm) ; Get configuration bits xor r2,r8,r3 ; Get changing bits? ori r0,r0,lo16(l3pspm|l3repm|l3rtm|l3cyam|l3dmemm|l3dmsizm) ; More config bits and. r0,r0,r2 ; Did any change? bne- ciinvdl3 ; Yes, just invalidate and get PLL synced... +ciflushl3: sync ; 7450 book says do this even though not needed - mr r10,r3 ; Take a copy now + mr r10,r8 ; Take a copy now bf 31,cinol3lck ; Skip if pfL23lck not set... @@ -766,30 +906,42 @@ cihwfl3: mfspr r10,l3cr ; Get back the L3CR rlwinm. r10,r10,0,l3hwf,l3hwf ; Is the flush over? bne+ cihwfl3 ; Nope, keep going... -ciinvdl3: rlwinm r3,r3,0,l3e+1,31 ; Clear the enable bit +ciinvdl3: rlwinm r8,r3,0,l3e+1,31 ; Use saved L3CR value and clear the enable bit sync ; Make sure of life, liberty, and justice - mtspr l3cr,r3 ; Disable L3 + mtspr l3cr,r8 ; Disable L3 sync - ori r3,r3,lo16(l3im) ; Get the invalidate flag set + cmplwi r3, 0 ; Should the L3 be all the way off? + beq cinol3 ; Yes, done with L3 + + ori r8,r8,lo16(l3im) ; Get the invalidate flag set - mtspr l3cr,r3 ; Start the invalidate + mtspr l3cr,r8 ; Start the invalidate -ciinvdl3b: mfspr r3,l3cr ; Get the L3CR - rlwinm. r3,r3,0,l3i,l3i ; Is the invalidate still going? +ciinvdl3b: mfspr r8,l3cr ; Get the L3CR + rlwinm. r8,r8,0,l3i,l3i ; Is the invalidate still going? bne+ ciinvdl3b ; Assume so... sync - mfspr r3,l3pdet ; ? - rlwimi r3,r3,28,0,23 ; ? - oris r3,r3,0xF000 ; ? - ori r3,r3,0x0080 ; ? - mtspr l3pdet,r3 ; ? + lwz r10, pfBootConfig(r12) ; ? + rlwinm. r10, r10, 24, 28, 31 ; ? + beq ciinvdl3nopdet ; ? + + mfspr r8,l3pdet ; ? + srw r2, r8, r10 ; ? + rlwimi r2, r8, 0, 24, 31 ; ? + subfic r10, r10, 32 ; ? + li r8, -1 ; ? + ori r2, r2, 0x0080 ; ? + slw r8, r8, r10 ; ? + or r8, r2, r8 ; ? + mtspr l3pdet, r8 ; ? isync - mfspr r3,l3cr ; Get the L3CR - rlwinm r3,r3,0,l3clken+1,l3clken-1 ; Clear the clock enable bit - mtspr l3cr,r3 ; Disable the clock +ciinvdl3nopdet: + mfspr r8,l3cr ; Get the L3CR + rlwinm r8,r8,0,l3clken+1,l3clken-1 ; Clear the clock enable bit + mtspr l3cr,r8 ; Disable the clock li r2,128 ; ? ciinvdl3c: addi r2,r2,-1 ; ? @@ -801,22 +953,25 @@ ciinvdl3c: addi r2,r2,-1 ; ? mtspr msssr0,r10 ; ? sync - oris r3,r3,hi16(l3em|l3clkenm) ; Turn on enable bit - mtspr l3cr,r3 ; Enable it + mtspr l3cr,r3 ; Enable it as desired sync cinol3: bf pfL2b,cinol2a ; No level 2 cache to enable lwz r3,pfl2cr(r12) ; Get the L2CR value - oris r3,r3,hi16(l2em) ; Turn on enable bit - mtspr l2cr,r3 ; Enable it + cmplwi r3, 0 ; Should the L2 be all the way off? + beq cinol2a : Yes, done with L2 + mtspr l2cr,r3 ; Enable it as desired sync ; ; Invalidate and turn on L1s ; -cinol2a: rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables +cinol2a: + bt 31,cinoexit ; Skip if pfLClck set... + + rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables mtspr hid0,r8 ; Turn off dem caches sync @@ -826,7 +981,8 @@ cinol2a: rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables isync mtspr hid0,r8 ; Start the invalidate and turn on L1 cache - mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) + +cinoexit: mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) and restore entry conditions sync mtmsr r7 ; Restore MSR to entry isync @@ -964,8 +1120,11 @@ smallenuf: rlwinm r3,r3,31-thrmsitve,thrmsitvs,thrmsitve ; Position LEXT(ml_thrm_set) mfmsr r0 ; Get the MSR + rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r6,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear EE bit mtmsr r6 + isync mfsprg r12,0 ; Get the per_proc blok @@ -1004,8 +1163,10 @@ tsetcant: mtmsr r0 ; Reenable interruptions LEXT(ml_read_temp) mfmsr r9 ; Save the MSR - rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions li r5,15 ; Starting point for ranging (start at 15 so we do not overflow) + rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off + rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions mfsprg r7,2 ; Get CPU specific features mtmsr r8 ; Do not allow interruptions mtcrf 0x40,r7 ; See if we can thermal this machine @@ -1067,9 +1228,12 @@ thrmcant: eqv r3,r3,r3 ; Return bogus temprature because we can not read i LEXT(ml_throttle) mfmsr r9 ; Save the MSR + rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions cmplwi r3,lo16(ictcfim>>1) ; See if we are going too far - mtmsr r8 ; Do not allow interruptions + mtmsr r8 ; Do not allow interruptions + isync ble+ throtok ; Throttle value is ok... li r3,lo16(ictcfim>>1) ; Set max @@ -1109,6 +1273,26 @@ loop: blr +/* + * The routine that implements cpu_number. + */ + + .align 5 + .globl EXT(cpu_number) + +LEXT(cpu_number) + + mfmsr r9 /* Save the old MSR */ + rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off + rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off + rlwinm r8,r9,0,17,15 /* Clear interruptions */ + mtmsr r8 /* Interrupts off */ + isync + mfsprg r7,0 /* Get per-proc block */ + lhz r3,PP_CPU_NUMBER(r7) /* Get CPU number */ + mtmsr r9 /* Restore interruptions to entry */ + blr /* Return... */ + /* ** ml_sense_nmi() ** @@ -1121,3 +1305,54 @@ LEXT(ml_sense_nmi) blr ; Leave... +/* +** ml_set_processor_speed() +** +*/ +; Force a line boundry here + .align 5 + .globl EXT(ml_set_processor_speed) + +LEXT(ml_set_processor_speed) + mfsprg r5, 0 ; Get the per_proc_info + + cmpli cr0, r3, 0 ; Turn off BTIC before low speed + beq sps1 + mfspr r4, hid0 ; Get the current hid0 value + rlwinm r4, r4, 0, btic+1, btic-1 ; Clear the BTIC bit + sync + mtspr hid0, r4 ; Set the new hid0 value + isync + sync + +sps1: + mfspr r4, hid1 ; Get the current PLL settings + rlwimi r4, r3, 31-hid1ps, hid1ps, hid1ps ; Copy the PLL Select bit + stw r4, pfHID1(r5) ; Save the new hid1 value + mtspr hid1, r4 ; Select desired PLL + + cmpli cr0, r3, 0 ; Restore BTIC after high speed + bne sps2 + lwz r4, pfHID0(r5) ; Load the hid0 value + sync + mtspr hid0, r4 ; Set the hid0 value + isync + sync + +sps2: + blr + +/* +** ml_set_processor_voltage() +** +*/ +; Force a line boundry here + .align 5 + .globl EXT(ml_set_processor_voltage) + +LEXT(ml_set_processor_voltage) + mfspr r4, hid2 ; Get HID2 value + rlwimi r4, r3, 31-hid2vmin, hid2vmin, hid2vmin ; Insert the voltage mode bit + mtspr hid2, r4 ; Set the voltage mode + sync ; Make sure it is done + blr