*/
; 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
mr r4,r3 ; Save the old value
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
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)
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
-
-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
- 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:
-
;
; 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
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)
+ 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
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?
tlbsync ; Sync all TLBs
sync
+ isync
cinoSMP: stw r2,0(r5) ; Unlock TLBIE lock
;
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
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
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:
;
mr r10,r3 ; 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
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
-
+
+ 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
bne+ ciinvdl3b ; Assume so...
sync
+ bf pfL3pdetb, ciinvdl3nopdet
mfspr r3,l3pdet ; ?
rlwimi r3,r3,28,0,23 ; ?
oris r3,r3,0xF000 ; ?
mtspr l3pdet,r3 ; ?
isync
+ciinvdl3nopdet:
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
; 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
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