2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 #define __APPLE_API_PRIVATE
36 #include <mach_kgdb.h>
38 #include <ppc/proc_reg.h>
39 #include <ppc/spec_reg.h>
40 #include <machine/cpu_capabilities.h>
41 #include <mach/ppc/vm_param.h>
45 ; Definitions of the processor type table format, which drives this code.
46 ; The table ("processor_types") is assembled in at the end of this file.
66 ; We use cr2 for flags:
73 * Interrupt and bootup stack for initial processor
79 * All CPUs start here.
81 * This code is called from SecondaryLoader
83 * Various arguments are passed via a table:
84 * R3 = pointer to other startup parameters
88 ENTRY(resetPOR,TAG_NO_FRAME_USED)
91 stw r12,0xF0(0) ; Make sure the special flag is clear
92 mtmsrd r12 ; Make sure we are in 32-bit mode
93 isync ; Really make sure
94 lwz r3,0xF4(0) ; Get the boot_args pointer
95 b startJoin ; Join up...
98 ENTRY(_start_cpu,TAG_NO_FRAME_USED)
99 crclr bootCPU ; Set non-boot processor
100 crclr firstInit ; Set not first time init
101 lwz r30,ppe_paddr(r3) ; Set current per_proc
102 lwz r28,ppe_paddr+4(r3) ; Set current per_proc
103 rlwinm r30,r30,0,1,0 ; Copy low 32 bits to top 32
104 rlwimi r30,r28,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
105 subi r29,r3,(ACT_PER_PROC-ppe_vaddr) ; Substract mact.PerProc offset
106 mr r3,r30 ; Set current per_proc
109 ; Note that we are just trying to get close. The real TB sync will take
110 ; place later. The value we are loading is set in two places. For the
111 ; main processor, it will be the TB at the last interrupt before we went
112 ; to sleep. For the others, it will be the time just before the main
113 ; processor woke us up.
116 lwz r15,ruptStamp(r3) ; Get the timebase from the other processor
117 li r17,0 ; Clear this out
118 lwz r16,ruptStamp+4(r3) ; Get the timebase from the other processor
119 mtspr tbl,r17 ; Clear bottom so we do not tick
120 mtspr tbu,r15 ; Set top
121 mtspr tbl,r16 ; Then bottom again
124 ENTRY(_start,TAG_NO_FRAME_USED)
127 mflr r2 ; Save the return address
128 lis r28,hi16(EXT(PerProcTable)) ; Set PerProcTable
129 lis r30,hi16(EXT(BootProcInfo)) ; Set current per_proc
130 ori r28,r28,lo16(EXT(PerProcTable)) ; Set PerProcTable
131 ori r30,r30,lo16(EXT(BootProcInfo)) ; Set current per_proc
132 stw r30,ppe_paddr+4(r28) ; Set per_proc_entry
133 stw r30,ppe_vaddr(r28) ; Set per_proc_entry
134 subi r29,r28,(ACT_PER_PROC-ppe_vaddr) ; Substract mact.PerProc offset
135 crset bootCPU ; Set boot processor
137 lwz r17,pfAvailable(r30) ; Get the available bits
138 rlwinm. r0,r17,0,pfValidb,pfValidb ; Have we initialized the feature flags yet?
139 crmove firstInit,cr0_eq ; Set if we are doing first time init
140 bne allstart ; Yeah, we must be waking up from sleep...
143 ; Here is where we do any one time general low-level initialization
145 lis r20,HIGH_ADDR(fwdisplock) ; Get address of the firmware display lock
146 li r19,0 ; Zorch a register
147 ori r20,r20,LOW_ADDR(fwdisplock) ; Get address of the firmware display lock
148 stw r19,0(r20) ; Make sure the lock is free
151 mr r31,r3 ; Save away arguments
153 crand firstBoot,bootCPU,firstInit ; Indicate if we are on the initial first processor startup
155 mtsprg 0,r30 ; Set per_proc paddr
156 mtsprg 1,r29 ; Set spr1
158 li r9,0 ; Clear out a register
162 li r7,MSR_VM_OFF ; Get real mode MSR
163 mtmsr r7 ; Set the real mode SRR
166 lis r26,hi16(processor_types) ; Point to processor table
167 ori r26,r26,lo16(processor_types) ; Other half
168 mfpvr r10 ; Get the PVR
170 nextPVR: lwz r28,ptFilter(r26) ; Get the filter
171 lwz r27,ptVersion(r26) ; Get the version and revision codes
172 and r28,r10,r28 ; Throw away dont care bits
173 cmplw r27,r28 ; Is this the right set?
174 beq donePVR ; We have the right one...
175 addi r26,r26,ptSize ; Point to the next type
176 b nextPVR ; Check it out...
178 donePVR: lwz r20,ptInitRout(r26) ; Grab the special init routine
179 mtlr r20 ; Setup to call the init
181 bf firstBoot,notFirst ; Not first boot, go...
184 ; The following code just does a general initialization of the features just
185 ; after the initial first-time boot. This is not done after waking up or on
186 ; any "secondary" processor. Just after the boot-processor init, we copy the
187 ; features to any possible per_proc.
189 ; We are just setting defaults. The specific initialization code will modify these
192 lis r18,hi16(EXT(_cpu_capabilities)) ; Get the address of _cpu_capabilities
193 ori r18,r18,lo16(EXT(_cpu_capabilities))
194 lwz r17,ptCPUCap(r26) ; Get the default cpu capabilities
195 stw r17, 0(r18) ; Save the default value in _cpu_capabilities
197 lwz r17,ptFeatures(r26) ; Pick up the features
199 lwz r18,ptRptdProc(r26) ; Get the reported processor
200 sth r18,pfrptdProc(r30) ; Set the reported processor
202 lwz r13,ptPwrModes(r26) ; Get the supported power modes
203 stw r13,pfPowerModes(r30) ; Set the supported power modes
205 lwz r13,ptLineSize(r26) ; Get the cache line size
206 sth r13,pflineSize(r30) ; Save it
207 lwz r13,ptl1iSize(r26) ; Get icache size
208 stw r13,pfl1iSize(r30) ; Save it
209 lwz r13,ptl1dSize(r26) ; Get dcache size
210 stw r13,pfl1dSize(r30) ; Save it
211 lwz r13,ptPTEG(r26) ; Get PTEG size address
212 stw r13,pfPTEG(r30) ; Save it
213 lwz r13,ptMaxVAddr(r26) ; Get max virtual address
214 stw r13,pfMaxVAddr(r30) ; Save it
215 lwz r13,ptMaxPAddr(r26) ; Get max physical address
216 stw r13,pfMaxPAddr(r30) ; Save it
219 ; Go through the patch table, changing performance sensitive kernel routines based on the
220 ; processor type or other things.
222 lis r11,hi16(EXT(patch_table))
223 ori r11,r11,lo16(EXT(patch_table))
224 lwz r19,ptPatch(r26) ; Get ptPatch field
226 lwz r16,patchType(r11) ; Load the patch type
227 lwz r15,patchValue(r11) ; Load the patch value
228 cmplwi cr1,r16,PATCH_FEATURE ; Is it a patch feature entry
229 cmplwi cr7,r16,PATCH_END_OF_TABLE ; end of table?
230 and. r14,r15,r19 ; Is it set in the patch feature
231 crandc cr0_eq,cr1_eq,cr0_eq ; Do we have a match
232 beq cr7,doOurInit ; end of table, Go do processor specific initialization
233 beq patch_apply ; proc feature matches, so patch memory
234 cmplwi cr1,r16,PATCH_PROCESSOR ; Is it a patch processor entry
235 cmplw cr0,r15,r18 ; Check matching processor
236 crand cr0_eq,cr1_eq,cr0_eq ; Do we have a match
237 bne patch_skip ; No, skip patch memory
239 lwz r13,patchAddr(r11) ; Load the address to patch
240 lwz r14,patchData(r11) ; Load the patch data
241 stw r14,0(r13) ; Patch the location
242 dcbf 0,r13 ; Flush the old one
243 sync ; Make sure we see it all
244 icbi 0,r13 ; Flush the i-cache
246 sync ; Hang out some more...
248 addi r11,r11,peSize ; Point to the next patch entry
249 b patch_loop ; handle next
252 ; Additional processors join here after skipping above code.
254 notFirst: lwz r17,pfAvailable(r30) ; Get our features
256 doOurInit: mr. r20,r20 ; See if initialization routine
257 crand firstBoot,bootCPU,firstInit ; Indicate if we are on the initial first processor startup
258 bnelrl ; Do the initialization
260 ori r17,r17,lo16(pfValid) ; Set the valid bit
261 stw r17,pfAvailable(r30) ; Set the available features
263 rlwinm. r0,r17,0,pf64Bitb,pf64Bitb ; Is this a 64-bit machine?
264 mtsprg 2,r17 ; Remember the feature flags
266 bne++ start64 ; Skip following if 64-bit...
268 mfspr r6,hid0 ; Get the HID0
269 rlwinm r6,r6,0,sleep+1,doze-1 ; Remove any vestiges of sleep
270 mtspr hid0,r6 ; Set the insominac HID0
273 ; Clear the BAT registers
275 li r9,0 ; Clear out a register
278 mtdbatu 0,r9 ; Invalidate maps
279 mtdbatl 0,r9 ; Invalidate maps
280 mtdbatu 1,r9 ; Invalidate maps
281 mtdbatl 1,r9 ; Invalidate maps
282 mtdbatu 2,r9 ; Invalidate maps
283 mtdbatl 2,r9 ; Invalidate maps
284 mtdbatu 3,r9 ; Invalidate maps
285 mtdbatl 3,r9 ; Invalidate maps
288 mtibatu 0,r9 ; Invalidate maps
289 mtibatl 0,r9 ; Invalidate maps
290 mtibatu 1,r9 ; Invalidate maps
291 mtibatl 1,r9 ; Invalidate maps
292 mtibatu 2,r9 ; Invalidate maps
293 mtibatl 2,r9 ; Invalidate maps
294 mtibatu 3,r9 ; Invalidate maps
295 mtibatl 3,r9 ; Invalidate maps
298 b startcommon ; Go join up the common start routine
300 start64: lis r5,hi16(startcommon) ; Get top of address of continue point
301 mfspr r6,hid0 ; Get the HID0
302 ori r5,r5,lo16(startcommon) ; Get low of address of continue point
303 lis r9,hi16(MASK(MSR_HV)|MASK(MSR_SF)) ; ?
304 lis r20,hi16(dozem|napm|sleepm) ; Get mask of power saving features
305 ori r20,r20,lo16(1) ; Disable the attn instruction
306 li r7,MSR_VM_OFF ; Get real mode MSR
307 sldi r9,r9,32 ; Slide into position
308 sldi r20,r20,32 ; Slide power stuff into position
309 or r9,r9,r7 ; Form initial MSR
310 andc r6,r6,r20 ; Remove any vestiges of sleep
312 mtspr hid0,r6 ; Set the insominac HID0
313 mfspr r6,hid0 ; Get it
314 mfspr r6,hid0 ; Get it
315 mfspr r6,hid0 ; Get it
316 mfspr r6,hid0 ; Get it
317 mfspr r6,hid0 ; Get it
318 mfspr r6,hid0 ; Get it
320 mtsrr0 r5 ; Set the continue point
321 mtsrr1 r9 ; Set our normal disabled MSR
327 rlwinm. r0,r17,0,pfFloatb,pfFloatb ; See if there is floating point
328 beq- noFloat ; Nope, this is a really stupid machine...
330 li r0,MSR_VM_OFF|MASK(MSR_FP) ; Enable for floating point
331 mtmsr r0 /* Set the standard MSR values */
334 lis r5,HIGH_ADDR(EXT(FloatInit)) /* Get top of floating point init value */
335 ori r5,r5,LOW_ADDR(EXT(FloatInit)) /* Slam bottom */
336 lfd f0,0(r5) /* Initialize FP0 */
337 fmr f1,f0 /* Ours in not */
338 fmr f2,f0 /* to wonder why, */
339 fmr f3,f0 /* ours is but to */
340 fmr f4,f0 /* do or die! */
369 li r0, MSR_VM_OFF ; Turn off floating point
373 noFloat: rlwinm. r0,r17,0,pfAltivecb,pfAltivecb ; See if there is Altivec
374 beq- noVector ; Nope...
376 li r0,0 ; Clear out a register
378 lis r7,hi16(MSR_VEC_ON) ; Get real mode MSR + Altivec
379 ori r7,r7,lo16(MSR_VM_OFF) ; Get real mode MSR + Altivec
380 mtmsr r7 ; Set the real mode SRR */
381 isync ; Make sure it has happened
383 lis r5,hi16(EXT(QNaNbarbarian)) ; Altivec initializer
384 ori r5,r5,lo16(EXT(QNaNbarbarian)) ; Altivec initializer
386 mtspr vrsave,r0 ; Set that no VRs are used yet */
388 vspltish v1,1 ; Turn on the non-Java bit and saturate
389 vspltisw v0,1 ; Turn on the saturate bit
390 vxor v1,v1,v0 ; Turn off saturate and leave non-Java set
391 lvx v0,br0,r5 ; Initialize VR0
392 mtvscr v1 ; Clear the vector status register
393 vor v2,v0,v0 ; Copy into the next register
394 vor v1,v0,v0 ; Copy into the next register
395 vor v3,v0,v0 ; Copy into the next register
396 vor v4,v0,v0 ; Copy into the next register
397 vor v5,v0,v0 ; Copy into the next register
398 vor v6,v0,v0 ; Copy into the next register
399 vor v7,v0,v0 ; Copy into the next register
400 vor v8,v0,v0 ; Copy into the next register
401 vor v9,v0,v0 ; Copy into the next register
402 vor v10,v0,v0 ; Copy into the next register
403 vor v11,v0,v0 ; Copy into the next register
404 vor v12,v0,v0 ; Copy into the next register
405 vor v13,v0,v0 ; Copy into the next register
406 vor v14,v0,v0 ; Copy into the next register
407 vor v15,v0,v0 ; Copy into the next register
408 vor v16,v0,v0 ; Copy into the next register
409 vor v17,v0,v0 ; Copy into the next register
410 vor v18,v0,v0 ; Copy into the next register
411 vor v19,v0,v0 ; Copy into the next register
412 vor v20,v0,v0 ; Copy into the next register
413 vor v21,v0,v0 ; Copy into the next register
414 vor v22,v0,v0 ; Copy into the next register
415 vor v23,v0,v0 ; Copy into the next register
416 vor v24,v0,v0 ; Copy into the next register
417 vor v25,v0,v0 ; Copy into the next register
418 vor v26,v0,v0 ; Copy into the next register
419 vor v27,v0,v0 ; Copy into the next register
420 vor v28,v0,v0 ; Copy into the next register
421 vor v29,v0,v0 ; Copy into the next register
422 vor v30,v0,v0 ; Copy into the next register
423 vor v31,v0,v0 ; Copy into the next register
425 li r0, MSR_VM_OFF ; Turn off vectors
430 bl EXT(cacheInit) ; Initializes all caches (including the TLB)
434 mfsprg r30,0 ; Phys per proc
435 lwz r29,PP_HIBERNATE(r30)
437 beq noHashTableInit ; Skip following if not waking from from hibernate
438 bl EXT(hw_clear_maps) ; Mark all maps as absent from hash table
439 bl EXT(hw_hash_init) ; Clear hash table
440 bl EXT(save_snapshot_restore) ; Reset save area chains
442 bl EXT(hw_setup_trans) ; Set up hardware needed for translation
443 bl EXT(hw_start_trans) ; Start translating
446 rlwinm. r0,r17,0,pf64Bitb,pf64Bitb ; Is this a 64-bit machine?
447 beq++ isnot64 ; Skip following if not 64-bit...
449 mfmsr r29 ; Get the MSR
450 rldicl r29,r29,0,MSR_SF_BIT+1 ; turn 64-bit mode off
454 isnot64: bf bootCPU,callcpu
456 lis r29,HIGH_ADDR(EXT(intstack)) ; move onto interrupt stack
457 ori r29,r29,LOW_ADDR(EXT(intstack))
458 addi r29,r29,INTSTACK_SIZE-FM_SIZE
461 stw r28,FM_BACKPTR(r29) ; store a null frame backpointer
464 mr r3,r31 ; Restore any arguments we may have trashed
466 ; Note that we exit from here with translation still off
468 bl EXT(ppc_init) ; Jump into boot init code
472 mfsprg r31,1 ; Fake activation pointer
473 lwz r31,ACT_PER_PROC(r31) ; Load per_proc
474 lwz r29,PP_INTSTACK_TOP_SS(r31) ; move onto interrupt stack
477 stw r28,FM_BACKPTR(r29) ; store a null frame backpointer
479 mr r1,r29 ; move onto new stack
480 mr r3,r31 ; Restore any arguments we may have trashed
482 ; Note that we exit from here with translation on
484 bl EXT(ppc_init_cpu) ; Jump into cpu init code
485 BREAKPOINT_TRAP ; Should never return
488 ; Specific processor initialization routines
494 bf firstBoot, init750nb ; No init for wakeup....
496 mfspr r13,l2cr ; Get the L2CR
497 rlwinm. r0,r13,0,l2e,l2e ; Any L2?
498 bne+ i750hl2 ; Yes...
499 rlwinm r17,r17,0,pfL2b+1,pfL2b-1 ; No L2, turn off feature
502 lis r14,hi16(256*1024) ; Base L2 size
503 addis r15,r13,0x3000 ; Hah... Figure this one out...
504 rlwinm r15,r15,4,30,31 ; Isolate
505 rlwinm. r8,r13,0,l2siz,l2sizf ; Was size valid?
506 slw r14,r14,r15 ; Set 256KB, 512KB, or 1MB
507 beq- init750l2none ; Not a valid setting...
509 stw r13,pfl2crOriginal(r30) ; Shadow the L2CR
510 stw r13,pfl2cr(r30) ; Shadow the L2CR
511 stw r14,pfl2Size(r30) ; Set the L2 size
512 b init750l2done ; Done with L2
515 rlwinm r17,r17,0,pfL2b+1,pfL2b-1 ; No level 2 cache
518 mfspr r11,hid0 ; Get the current HID0
519 stw r11,pfHID0(r30) ; Save the HID0 value
523 lwz r11,pfHID0(r30) ; Get HID0
525 mtspr hid0,r11 ; Set the HID
533 bf firstBoot, init750 ; No init for wakeup....
534 mfspr r13,hid1 ; Get HID1
535 li r14,lo16(0xFD5F) ; Get valid
536 rlwinm r13,r13,4,28,31 ; Isolate
537 slw r14,r14,r13 ; Position
538 rlwimi r17,r14,15-pfCanNapb,pfCanNapb,pfCanNapb ; Set it
539 b init750 ; Join common...
545 bf firstBoot, init750FXnb
547 stw r11, pfHID1(r30) ; Save the HID1 value
551 lwz r13, pfHID0(r30) ; Get HID0
552 lwz r11, pfHID1(r30) ; Get HID1
554 rlwinm. r0, r11, 0, hid1ps, hid1ps ; Isolate the hid1ps bit
555 beq init750FXnb2 ; Clear BTIC if hid1ps set
556 rlwinm r13, r13, 0, btic+1, btic-1 ; Clear the BTIC bit
560 mtspr hid0, r13 ; Set the HID
564 rlwinm r12, r11, 0, hid1ps+1, hid1ps-1 ; Select PLL0
565 mtspr hid1, r12 ; Restore PLL config
566 mftb r13 ; Wait 5000 ticks (> 200 us)
573 mtspr hid1, r11 ; Select the desired PLL
576 ; 750FX vers 2.0 or later
578 bf firstBoot, init750FXV2nb ; Wake from sleep
581 stw r11, pfHID2(r30) ; Save the HID2 value
582 b init750FX ; Continue with 750FX init
585 lwz r13, pfHID2(r30) ; Get HID2
586 rlwinm r13, r13, 0, hid2vmin+1, hid2vmin-1 ; Clear the vmin bit
587 mtspr hid2, r13 ; Restore HID2 value
588 sync ; Wait for it to be done
593 init7400: bf firstBoot,i7400nb ; Do different if not initial boot...
594 mfspr r13,l2cr ; Get the L2CR
595 rlwinm. r0,r13,0,l2e,l2e ; Any L2?
596 bne+ i7400hl2 ; Yes...
597 rlwinm r17,r17,0,pfL2b+1,pfL2b-1 ; No L2, turn off feature
599 i7400hl2: lis r14,hi16(256*1024) ; Base L2 size
600 addis r15,r13,0x3000 ; Hah... Figure this one out...
601 rlwinm r15,r15,4,30,31
602 slw r14,r14,r15 ; Set 256KB, 512KB, 1MB, or 2MB
604 stw r13,pfl2crOriginal(r30) ; Shadow the L2CR
605 stw r13,pfl2cr(r30) ; Shadow the L2CR
606 stw r14,pfl2Size(r30) ; Set the L2 size
608 mfspr r11,hid0 ; Get the current HID0
609 oris r11,r11,hi16(emcpm|eiecm) ; ?
612 stw r11,pfHID0(r30) ; Save the HID0 value
614 mfspr r11,msscr0 ; Get the msscr0 register
615 stw r11,pfMSSCR0(r30) ; Save the MSSCR0 value
616 mfspr r11,msscr1 ; Get the msscr1 register
617 stw r11,pfMSSCR1(r30) ; Save the MSSCR1 value
622 mtspr l2cr,r11 ; Make sure L2CR is zero
623 lwz r11,pfHID0(r30) ; Get HID0
625 mtspr hid0,r11 ; Set the HID
628 lwz r11,pfMSSCR0(r30) ; Get MSSCR0
631 mtspr msscr0,r11 ; Set the MSSCR0
632 lwz r11,pfMSSCR1(r30) ; Get msscr1
635 mtspr msscr1,r11 ; Set the msscr1
640 ; 7400 (ver 2.0 - ver 2.7)
643 bf firstBoot, init7400
644 mfspr r13, hid0 ; Get the HID0
645 ori r13, r13, nopdstm ; ?
646 mtspr hid0, r13 ; Set the HID0
652 ; Note that this is the same as 7400 except we initialize the l2cr2 register
654 init7410: li r13,0 ; Clear
655 mtspr 1016,r13 ; Turn off direct cache
656 b init7400 ; Join up with common....
659 ; 745X - Any 7450 family processor
662 bf firstBoot,init745Xnb ; Do different if not initial boot...
664 mfspr r13,l2cr ; Get the L2CR
665 rlwinm. r0,r13,0,l2e,l2e ; Any L2?
666 bne+ init745Xhl2 ; Yes...
667 rlwinm r17,r17,0,pfL2b+1,pfL2b-1 ; No L2, turn off feature
670 mfpvr r14 ; Get processor version
671 rlwinm r14,r14,16,16,31 ; Isolate processor version
672 cmpli cr0, r14, PROCESSOR_VERSION_7457 ; Test for 7457 or
673 cmpli cr1, r14, PROCESSOR_VERSION_7447A ; 7447A
674 cror cr0_eq, cr1_eq, cr0_eq
675 lis r14,hi16(512*1024) ; 512KB L2
678 lis r14,hi16(256*1024) ; Base L2 size
679 rlwinm r15,r13,22,12,13 ; Convert to 256k, 512k, or 768k
680 add r14,r14,r15 ; Add in minimum
683 stw r13,pfl2crOriginal(r30) ; Shadow the L2CR
684 stw r13,pfl2cr(r30) ; Shadow the L2CR
685 stw r14,pfl2Size(r30) ; Set the L2 size
687 ; Take care of level 3 cache
689 mfspr r13,l3cr ; Get the L3CR
690 rlwinm. r0,r13,0,l3e,l3e ; Any L3?
691 bne+ init745Xhl3 ; Yes...
692 rlwinm r17,r17,0,pfL3b+1,pfL3b-1 ; No L3, turn off feature
694 init745Xhl3: cmplwi cr0,r13,0 ; No L3 if L3CR is zero
695 beq- init745Xnone ; Go turn off the features...
696 lis r14,hi16(1024*1024) ; Base L3 size
697 rlwinm r15,r13,4,31,31 ; Get size multiplier
698 slw r14,r14,r15 ; Set 1 or 2MB
700 stw r13,pfl3crOriginal(r30) ; Shadow the L3CR
701 stw r13,pfl3cr(r30) ; Shadow the L3CR
702 stw r14,pfl3Size(r30) ; Set the L3 size
703 b init745Xfin ; Return....
706 rlwinm r17,r17,0,pfL3fab+1,pfL3b-1 ; No 3rd level cache or assist
707 rlwinm r11,r17,pfWillNapb-pfCanNapb,pfCanNapb,pfCanNapb ; Set pfCanNap if pfWillNap is set
711 rlwinm r17,r17,0,pfWillNapb+1,pfWillNapb-1 ; Make sure pfWillNap is not set
713 mfspr r11,hid0 ; Get the current HID0
714 stw r11,pfHID0(r30) ; Save the HID0 value
715 mfspr r11,hid1 ; Get the current HID1
716 stw r11,pfHID1(r30) ; Save the HID1 value
717 mfspr r11,msscr0 ; Get the msscr0 register
718 stw r11,pfMSSCR0(r30) ; Save the MSSCR0 value
719 mfspr r11,msscr1 ; Get the msscr1 register
720 stw r11,pfMSSCR1(r30) ; Save the MSSCR1 value
721 mfspr r11,ictrl ; Get the ictrl register
722 stw r11,pfICTRL(r30) ; Save the ICTRL value
723 mfspr r11,ldstcr ; Get the ldstcr register
724 stw r11,pfLDSTCR(r30) ; Save the LDSTCR value
725 mfspr r11,ldstdb ; Get the ldstdb register
726 stw r11,pfLDSTDB(r30) ; Save the LDSTDB value
727 mfspr r11,pir ; Get the pir register
728 stw r11,pfBootConfig(r30) ; Save the BootConfig value
732 init745Xnb: lwz r11,pfHID0(r30) ; Get HID0
734 mtspr hid0,r11 ; Set the HID
736 lwz r11,pfHID1(r30) ; Get HID1
738 mtspr hid1,r11 ; Set the HID
740 lwz r11,pfMSSCR0(r30) ; Get MSSCR0
742 mtspr msscr0,r11 ; Set the MSSCR0
745 lwz r11,pfICTRL(r30) ; Get ICTRL
747 mtspr ictrl,r11 ; Set the ICTRL
750 lwz r11,pfLDSTCR(r30) ; Get LDSTCR
752 mtspr ldstcr,r11 ; Set the LDSTCR
755 lwz r11,pfLDSTDB(r30) ; Get LDSTDB
757 mtspr ldstdb,r11 ; Set the LDSTDB
765 bf firstBoot, init745X ; Not boot, use standard init
767 mfspr r13, pir ; Get BootConfig from PIR
768 rlwinm. r14, r13, 0, 20, 23 ; Is the pdet value zero
769 bne init7450done ; No, done for now
771 ori r13, r13, 0x0400 ; Force pdet value to 4
772 mtspr pir, r13 ; Write back the BootConfig
775 b init745X ; Continue with standard init
779 lis r20,8 ; Set up for 512K L2
782 mtspr hior,r0 ; Make sure that 0 is interrupt prefix
783 bf firstBoot,init970nb ; No init for wakeup or second processor....
787 ; We can not query or change the L2 size. We will just
788 ; phoney up a L2CR to make sysctl "happy" and set the
792 lis r0,0x8000 ; Synthesize a "valid" but non-existant L2CR
793 stw r0,pfl2crOriginal(r30) ; Set a dummy L2CR
794 stw r0,pfl2cr(r30) ; Set a dummy L2CR
795 stw r20,pfl2Size(r30) ; Set the L2 size
797 mfspr r11,hid0 ; Get original hid0
798 std r11,pfHID0(r30) ; Save original
799 mfspr r11,hid1 ; Get original hid1
800 std r11,pfHID1(r30) ; Save original
801 mfspr r11,hid4 ; Get original hid4
802 std r11,pfHID4(r30) ; Save original
803 mfspr r11,hid5 ; Get original hid5
804 std r11,pfHID5(r30) ; Save original
806 lis r0, hi16(dnapm) ; Create a mask for the dnap bit
807 sldi r0, r0, 32 ; Shift to the top half
808 ld r11,pfHID0(r30) ; Load the hid0 value
809 andc r11, r11, r0 ; Clear the dnap bit
811 mtspr hid0,r11 ; Stuff it
812 mfspr r11,hid0 ; Get it
813 mfspr r11,hid0 ; Get it
814 mfspr r11,hid0 ; Get it
815 mfspr r11,hid0 ; Get it
816 mfspr r11,hid0 ; Get it
817 mfspr r11,hid0 ; Get it
820 lis r0,(pcfValid|pcfLarge|pcfDedSeg)<<8 ; Set the valid bit, dedicated segment, and large page flags
821 ori r0,r0,(24<<8)|24 ; Add in the 16M page size
822 stw r0,lgpPcfg+(pcfSize*pcfLargePcfg)(0) ; Set the 16M primary large page configuration entry
827 ; Start up code for second processor or wake up from sleep
831 lis r0, hi16(dnapm) ; Create a mask for the dnap bit
832 sldi r0, r0, 32 ; Shift to the top half
833 ld r11,pfHID0(r30) ; Load the hid0 value
834 andc r11, r11, r0 ; Clear the dnap bit
836 mtspr hid0,r11 ; Stuff it
837 mfspr r11,hid0 ; Get it
838 mfspr r11,hid0 ; Get it
839 mfspr r11,hid0 ; Get it
840 mfspr r11,hid0 ; Get it
841 mfspr r11,hid0 ; Get it
842 mfspr r11,hid0 ; Get it
845 ld r20,pfHID1(r30) ; Get it
847 mtspr hid1,r20 ; Stick it
848 mtspr hid1,r20 ; Stick it again
851 ld r11,pfHID4(r30) ; Get it
853 mtspr hid4,r11 ; Stick it
856 lis r11,0xE000 ; Get the unlikeliest ESID possible
857 srdi r11,r11,1 ; Make 0x7FFFFFFFF0000000
858 slbie r11 ; Make sure the ERAT is cleared
860 ld r11,pfHID5(r30) ; Get it
861 mtspr hid5,r11 ; Set it
864 ; May have changed dcbz mode so kill icache
867 eqv r13,r13,r13 ; Get a constant -1
868 mr r14,r20 ; Save HID1
869 rldimi r14,r13,54,9 ; Set force icbi match mode
871 li r11,0 ; Set start if ICBI range
873 mtspr hid1,r14 ; Stick it
874 mtspr hid1,r14 ; Stick it again
877 inin970ki: icbi 0,r11 ; Kill I$
878 addi r11,r11,128 ; Next line
879 andis. r0,r11,1 ; Have we done them all?
880 beq++ inin970ki ; Not yet...
883 mtspr hid1,r20 ; Stick it
884 mtspr hid1,r20 ; Stick it again
891 ; Unsupported Processors
893 mtlr r2 ; Restore the return address
894 blr ; Return to the booter
898 ; Processor to feature table
900 ; .align 2 - Always on word boundary
901 ; .long ptFilter - Mask of significant bits in the Version/Revision code
902 ; - NOTE: Always order from most restrictive to least restrictive matching
903 ; .short ptVersion - Version code from PVR. Always start with 0 which is default
904 ; .short ptRevision - Revision code from PVR. A zero value denotes the generic attributes if not specific
905 ; .long ptFeatures - Available features
906 ; .long ptCPUCap - Default value for _cpu_capabilities
907 ; .long ptPwrModes - Available power management features
908 ; .long ptPatch - Patch features
909 ; .long ptInitRout - Initilization routine. Can modify any of the other attributes.
910 ; .long ptRptdProc - Processor type reported
911 ; .long ptLineSize - Level 1 cache line size
912 ; .long ptl1iSize - Level 1 instruction cache size
913 ; .long ptl1dSize - Level 1 data cache size
914 ; .long ptPTEG - Size of PTEG
915 ; .long ptMaxVAddr - Maximum effective address
916 ; .long ptMaxPAddr - Maximum physical address
925 .long 0xFFFF0F00 ; 2.x vers
926 .short PROCESSOR_VERSION_750
928 .long pfFloat | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL2
929 .long kCache32 | kHasGraphicsOps | kHasStfiwx
933 .long CPU_SUBTYPE_POWERPC_750
944 .long 0xFFFF0000 ; All revisions
945 .short PROCESSOR_VERSION_750
947 .long pfFloat | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL2
948 .long kCache32 | kHasGraphicsOps | kHasStfiwx
952 .long CPU_SUBTYPE_POWERPC_750
963 .long 0xFFFF0F00 ; 1.x vers
964 .short PROCESSOR_VERSION_750FX
966 .long pfFloat | pfCanSleep | pfCanNap | pfCanDoze | pfSlowNap | pfNoMuMMCK | pf32Byte | pfL2
967 .long kCache32 | kHasGraphicsOps | kHasStfiwx
971 .long CPU_SUBTYPE_POWERPC_750
982 .long 0xFFFF0000 ; All revisions
983 .short PROCESSOR_VERSION_750FX
985 .long pfFloat | pfCanSleep | pfCanNap | pfCanDoze | pfSlowNap | pfNoMuMMCK | pf32Byte | pfL2
986 .long kCache32 | kHasGraphicsOps | kHasStfiwx
987 .long pmDualPLL | pmDPLLVmin
990 .long CPU_SUBTYPE_POWERPC_750
998 ; 7400 (ver 2.0 - ver 2.7)
1001 .long 0xFFFFFFF8 ; ver 2.0 - 2.7
1002 .short PROCESSOR_VERSION_7400
1004 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL1fa | pfL2 | pfL2fa | pfHasDcba
1005 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1009 .long CPU_SUBTYPE_POWERPC_7400
1020 .long 0xFFFF0000 ; All revisions
1021 .short PROCESSOR_VERSION_7400
1023 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL1fa | pfL2 | pfL2fa | pfHasDcba
1024 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1028 .long CPU_SUBTYPE_POWERPC_7400
1039 .long 0xFFFFFFFF ; Exact match
1040 .short PROCESSOR_VERSION_7400
1042 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL1fa | pfL2 | pfL2fa | pfHasDcba
1043 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1047 .long CPU_SUBTYPE_POWERPC_7400
1058 .long 0xFFFF0000 ; All other revisions
1059 .short PROCESSOR_VERSION_7410
1061 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfCanDoze | pf32Byte | pfL1fa | pfL2 | pfL2fa | pfHasDcba
1062 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1066 .long CPU_SUBTYPE_POWERPC_7400
1077 .long 0xFFFFFF00 ; Just revisions 1.xx
1078 .short PROCESSOR_VERSION_7450
1080 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1081 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1085 .long CPU_SUBTYPE_POWERPC_7450
1096 .long 0xFFFFFFFF ; Just revision 2.0
1097 .short PROCESSOR_VERSION_7450
1099 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1100 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1104 .long CPU_SUBTYPE_POWERPC_7450
1115 .long 0xFFFF0000 ; All other revisions
1116 .short PROCESSOR_VERSION_7450
1118 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfWillNap | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1119 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1123 .long CPU_SUBTYPE_POWERPC_7450
1131 ; 7455 (1.xx) Just like 7450 2.0
1134 .long 0xFFFFFF00 ; Just revisions 1.xx
1135 .short PROCESSOR_VERSION_7455
1137 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1138 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1142 .long CPU_SUBTYPE_POWERPC_7450
1153 .long 0xFFFFFFFF ; Just revision 2.0
1154 .short PROCESSOR_VERSION_7455
1156 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfWillNap | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1157 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1161 .long CPU_SUBTYPE_POWERPC_7450
1172 .long 0xFFFF0000 ; All other revisions
1173 .short PROCESSOR_VERSION_7455
1175 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1176 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1180 .long CPU_SUBTYPE_POWERPC_7450
1191 .long 0xFFFF0000 ; All revisions
1192 .short PROCESSOR_VERSION_7457
1194 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1195 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1199 .long CPU_SUBTYPE_POWERPC_7450
1210 .long 0xFFFF0000 ; All revisions
1211 .short PROCESSOR_VERSION_7447A
1213 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pfNoMSRir | pfNoL2PFNap | pfLClck | pf32Byte | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa | pfHasDcba
1214 .long kHasAltivec | kCache32 | kDcbaAvailable | kDataStreamsRecommended | kDataStreamsAvailable | kHasGraphicsOps | kHasStfiwx
1218 .long CPU_SUBTYPE_POWERPC_7450
1229 .long 0xFFFF0000 ; All versions so far
1230 .short PROCESSOR_VERSION_970
1232 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pf128Byte | pf64Bit | pfL2 | pfSCOMFixUp
1233 .long kHasAltivec | k64Bit | kCache128 | kDataStreamsAvailable | kDcbtStreamsRecommended | kDcbtStreamsAvailable | kHasGraphicsOps | kHasStfiwx | kHasFsqrt
1237 .long CPU_SUBTYPE_POWERPC_970
1248 .long 0xFFFF0000 ; All versions so far
1249 .short PROCESSOR_VERSION_970FX
1251 .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfCanNap | pf128Byte | pf64Bit | pfL2
1252 .long kHasAltivec | k64Bit | kCache128 | kDataStreamsAvailable | kDcbtStreamsRecommended | kDcbtStreamsAvailable | kHasGraphicsOps | kHasStfiwx | kHasFsqrt
1256 .long CPU_SUBTYPE_POWERPC_970
1265 ; All other processors are not supported
1268 .long 0x00000000 ; Matches everything
1271 .long pfFloat | pf32Byte
1272 .long kCache32 | kHasGraphicsOps | kHasStfiwx
1275 .long initUnsupported
1276 .long CPU_SUBTYPE_POWERPC_ALL