]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/machine_routines_asm.s
xnu-517.3.7.tar.gz
[apple/xnu.git] / osfmk / ppc / machine_routines_asm.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <ppc/asm.h>
26#include <ppc/proc_reg.h>
27#include <cpus.h>
28#include <assym.s>
29#include <debug.h>
30#include <mach/ppc/vm_param.h>
31#include <ppc/exception.h>
32
55e303ae
A
33
34/*
35 * ml_set_physical() -- turn off DR and (if 64-bit) turn SF on
36 * it is assumed that pf64Bit is already in cr6
37 * ml_set_physical_get_ffs() -- turn DR off, SF on, and get feature flags
38 * ml_set_physical_disabled() -- turn DR and EE off, SF on, get feature flags
39 * ml_set_translation_off() -- turn DR, IR, and EE off, SF on, get feature flags
40 *
41 * Callable only from assembler, these return:
42 * r2 -- new MSR
43 * r11 -- old MSR
44 * r10 -- feature flags (pf64Bit etc, ie SPRG 2)
45 * cr6 -- feature flags 24-27, ie pf64Bit, pf128Byte, and pf32Byte
46 *
47 * Uses r0 and r2. ml_set_translation_off also uses r3 and cr5.
48 */
49
50 .align 4
51 .globl EXT(ml_set_translation_off)
52LEXT(ml_set_translation_off)
53 mfsprg r10,2 // get feature flags
54 li r0,0 ; Clear this
55 mtcrf 0x02,r10 // move pf64Bit etc to cr6
56 ori r0,r0,lo16(MASK(MSR_EE)+MASK(MSR_FP)+MASK(MSR_IR)+MASK(MSR_DR)) // turn off all 4
57 mfmsr r11 // get MSR
58 oris r0,r0,hi16(MASK(MSR_VEC)) // Turn off vector too
59 mtcrf 0x04,r10 // move pfNoMSRir etc to cr5
60 andc r2,r11,r0 // turn off EE, IR, and DR
61 bt++ pf64Bitb,ml_set_physical_64 // skip if 64-bit (only they take the hint)
62 bf pfNoMSRirb,ml_set_physical_32 // skip if we can load MSR directly
63 li r0,loadMSR // Get the MSR setter SC
64 mr r3,r2 // copy new MSR to r2
65 sc // Set it
66 blr
67
68 .align 4
69 .globl EXT(ml_set_physical_disabled)
70
71LEXT(ml_set_physical_disabled)
72 li r0,0 ; Clear
73 mfsprg r10,2 // get feature flags
74 ori r0,r0,lo16(MASK(MSR_EE)) // turn EE and fp off
75 mtcrf 0x02,r10 // move pf64Bit etc to cr6
76 b ml_set_physical_join
77
78 .align 5
79 .globl EXT(ml_set_physical_get_ffs)
80
81LEXT(ml_set_physical_get_ffs)
82 mfsprg r10,2 // get feature flags
83 mtcrf 0x02,r10 // move pf64Bit etc to cr6
84
85 .globl EXT(ml_set_physical)
86LEXT(ml_set_physical)
87
88 li r0,0 // do not turn off interrupts
89
90ml_set_physical_join:
91 oris r0,r0,hi16(MASK(MSR_VEC)) // Always gonna turn of vectors
92 mfmsr r11 // get MSR
93 ori r0,r0,lo16(MASK(MSR_DR)+MASK(MSR_FP)) // always turn off DR and FP bit
94 andc r2,r11,r0 // turn off DR and maybe EE
95 bt++ pf64Bitb,ml_set_physical_64 // skip if 64-bit (only they take the hint)
96ml_set_physical_32:
97 mtmsr r2 // turn off translation
98 isync
99 blr
100
101ml_set_physical_64:
102 li r0,1 // get a 1 to slam into SF
103 rldimi r2,r0,63,MSR_SF_BIT // set SF bit (bit 0)
104 mtmsrd r2 // set 64-bit mode, turn off data relocation
105 isync // synchronize
106 blr
107
108
109/*
110 * ml_restore(old_MSR)
111 *
112 * Callable only from assembler, restores the MSR in r11 saved by ml_set_physical.
113 * We assume cr6 and r11 are as set by ml_set_physical, ie:
114 * cr6 - pf64Bit flag (feature flags 24-27)
115 * r11 - old MSR
116 */
117
118 .align 5
119 .globl EXT(ml_restore)
120
121LEXT(ml_restore)
122 bt++ pf64Bitb,ml_restore_64 // handle 64-bit cpus (only they take the hint)
123 mtmsr r11 // restore a 32-bit MSR
124 isync
125 blr
126
127ml_restore_64:
128 mtmsrd r11 // restore a 64-bit MSR
129 isync
130 blr
131
132
1c79356b
A
133/* PCI config cycle probing
134 *
135 * boolean_t ml_probe_read(vm_offset_t paddr, unsigned int *val)
136 *
137 * Read the memory location at physical address paddr.
138 * This is a part of a device probe, so there is a good chance we will
139 * have a machine check here. So we have to be able to handle that.
140 * We assume that machine checks are enabled both in MSR and HIDs
141 */
142
143; Force a line boundry here
144 .align 5
145 .globl EXT(ml_probe_read)
146
147LEXT(ml_probe_read)
148
149 mfsprg r9,2 ; Get feature flags
55e303ae
A
150
151 rlwinm. r0,r9,0,pf64Bitb,pf64Bitb ; Are we on a 64-bit machine?
152 rlwinm r3,r3,0,0,31 ; Clean up for 64-bit machines
153 bne++ mpr64bit ; Go do this the 64-bit way...
154
155mpr32bit: lis r8,hi16(MASK(MSR_VEC)) ; Get the vector flag
1c79356b 156 mfmsr r0 ; Save the current MSR
55e303ae
A
157 ori r8,r8,lo16(MASK(MSR_FP)) ; Add the FP flag
158
1c79356b 159 neg r10,r3 ; Number of bytes to end of page
55e303ae 160 andc r0,r0,r8 ; Clear VEC and FP
1c79356b 161 rlwinm. r10,r10,0,20,31 ; Clear excess junk and test for page bndry
55e303ae 162 ori r8,r8,lo16(MASK(MSR_EE)|MASK(MSR_IR)|MASK(MSR_DR)) ; Drop EE, IR, and DR
1c79356b 163 mr r12,r3 ; Save the load address
55e303ae 164 andc r2,r0,r8 ; Clear VEC, FP, and EE
1c79356b
A
165 mtcrf 0x04,r9 ; Set the features
166 cmplwi cr1,r10,4 ; At least 4 bytes left in page?
1c79356b
A
167 beq- mprdoit ; We are right on the boundary...
168 li r3,0
169 bltlr- cr1 ; No, just return failure...
170
171mprdoit:
172
173 bt pfNoMSRirb,mprNoMSR ; No MSR...
174
175 mtmsr r2 ; Translation and all off
176 isync ; Toss prefetch
177 b mprNoMSRx
178
179mprNoMSR:
180 mr r5,r0
181 li r0,loadMSR ; Get the MSR setter SC
182 mr r3,r2 ; Get new MSR
183 sc ; Set it
184 mr r0,r5
185 li r3,0
186mprNoMSRx:
d52fe63f
A
187
188 mfspr r6, hid0 ; Get a copy of hid0
1c79356b 189
9bccf70c
A
190 rlwinm. r5, r9, 0, pfNoMuMMCKb, pfNoMuMMCKb ; Check for NoMuMMCK
191 bne mprNoMuM
192
193 rlwinm r5, r6, 0, ice+1, ice-1 ; Turn off L1 I-Cache
194 mtspr hid0, r5
195 isync ; Wait for I-Cache off
196 rlwinm r5, r6, 0, mum+1, mum-1 ; Turn off MuM w/ I-Cache on
197 mtspr hid0, r5
198mprNoMuM:
d52fe63f 199
1c79356b
A
200;
201; We need to insure that there is no more than 1 BAT register that
202; can get a hit. There could be repercussions beyond the ken
203; of mortal man. It is best not to tempt fate.
204;
d52fe63f
A
205
206; Note: we will reload these from the shadow BATs later
207
1c79356b 208 li r10,0 ; Clear a register
1c79356b
A
209
210 sync ; Make sure all is well
211
212 mtdbatu 1,r10 ; Invalidate DBAT 1
213 mtdbatu 2,r10 ; Invalidate DBAT 2
214 mtdbatu 3,r10 ; Invalidate DBAT 3
215
216 rlwinm r10,r12,0,0,14 ; Round down to a 128k boundary
217 ori r11,r10,0x32 ; Set uncached, coherent, R/W
218 ori r10,r10,2 ; Make the upper half (128k, valid supervisor)
219 mtdbatl 0,r11 ; Set lower BAT first
220 mtdbatu 0,r10 ; Now the upper
221 sync ; Just make sure
222
d52fe63f
A
223 dcbf 0,r12 ; Make sure we kill the cache to avoid paradoxes
224 sync
225
1c79356b
A
226 ori r11,r2,lo16(MASK(MSR_DR)) ; Turn on data translation
227 mtmsr r11 ; Do it for real
228 isync ; Make sure of it
229
230 eieio ; Make sure of all previous accesses
231 sync ; Make sure it is all caught up
232
233 lwz r11,0(r12) ; Get it and maybe machine check here
234
235 eieio ; Make sure of ordering again
236 sync ; Get caught up yet again
237 isync ; Do not go further till we are here
238
d52fe63f
A
239 mtmsr r2 ; Turn translation back off
240 isync
241
d52fe63f
A
242 lis r10,hi16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address
243 ori r10,r10,lo16(EXT(shadow_BAT)+shdDBAT) ; Get shadow address
244
245 lwz r5,0(r10) ; Pick up DBAT 0 high
246 lwz r6,4(r10) ; Pick up DBAT 0 low
247 lwz r7,8(r10) ; Pick up DBAT 1 high
248 lwz r8,16(r10) ; Pick up DBAT 2 high
249 lwz r9,24(r10) ; Pick up DBAT 3 high
250
1c79356b
A
251 mtdbatu 0,r5 ; Restore DBAT 0 high
252 mtdbatl 0,r6 ; Restore DBAT 0 low
253 mtdbatu 1,r7 ; Restore DBAT 1 high
254 mtdbatu 2,r8 ; Restore DBAT 2 high
255 mtdbatu 3,r9 ; Restore DBAT 3 high
256 sync
257
258 li r3,1 ; We made it
259
260 mtmsr r0 ; Restore translation and exceptions
261 isync ; Toss speculations
262
263 stw r11,0(r4) ; Save the loaded value
264 blr ; Return...
265
266; Force a line boundry here. This means we will be able to check addresses better
267 .align 5
268 .globl EXT(ml_probe_read_mck)
269LEXT(ml_probe_read_mck)
270
55e303ae
A
271
272/* PCI config cycle probing - 64-bit
273 *
274 * boolean_t ml_probe_read_64(addr64_t paddr, unsigned int *val)
275 *
276 * Read the memory location at physical address paddr.
277 * This is a part of a device probe, so there is a good chance we will
278 * have a machine check here. So we have to be able to handle that.
279 * We assume that machine checks are enabled both in MSR and HIDs
280 */
281
282; Force a line boundry here
283 .align 6
284 .globl EXT(ml_probe_read_64)
285
286LEXT(ml_probe_read_64)
287
288 mfsprg r9,2 ; Get feature flags
289 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
290 rlwinm. r0,r9,0,pf64Bitb,pf64Bitb ; Are we on a 64-bit machine?
291 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
292
293 mr r4,r5 ; Move result to common register
294 beq-- mpr32bit ; Go do this the 32-bit way...
295
296mpr64bit: andi. r0,r3,3 ; Check if we are on a word boundary
297 li r0,0 ; Clear the EE bit (and everything else for that matter)
298 bne-- mprFail ; Boundary not good...
299 mfmsr r11 ; Get the MSR
300 mtmsrd r0,1 ; Set the EE bit only (do not care about RI)
301 rlwinm r11,r11,0,MSR_EE_BIT,MSR_EE_BIT ; Isolate just the EE bit
302 mfmsr r10 ; Refresh our view of the MSR (VMX/FP may have changed)
303 or r12,r10,r11 ; Turn on EE if on before we turned it off
304 ori r0,r0,lo16(MASK(MSR_IR)|MASK(MSR_DR)) ; Get the IR and DR bits
305 li r2,1 ; Get a 1
306 sldi r2,r2,63 ; Get the 64-bit bit
307 andc r10,r10,r0 ; Clear IR and DR
308 or r10,r10,r2 ; Set 64-bit
309
310 li r0,1 ; Get a 1
311 mtmsrd r10 ; Translation and EE off, 64-bit on
312 isync
313
314 sldi r0,r0,32+8 ; Get the right bit to inhibit caching
315
316 mfspr r8,hid4 ; Get HID4
317 or r2,r8,r0 ; Set bit to make real accesses cache-inhibited
318 sync ; Sync up
319 mtspr hid4,r2 ; Make real accesses cache-inhibited
320 isync ; Toss prefetches
321
322 lis r7,0xE000 ; Get the unlikeliest ESID possible
323 srdi r7,r7,1 ; Make 0x7FFFFFFFF0000000
324 slbie r7 ; Make sure the ERAT is cleared
325
326 sync
327 isync
328
329 eieio ; Make sure of all previous accesses
330
331 lwz r11,0(r3) ; Get it and maybe machine check here
332
333 eieio ; Make sure of ordering again
334 sync ; Get caught up yet again
335 isync ; Do not go further till we are here
336
337 sync ; Sync up
338 mtspr hid4,r8 ; Make real accesses not cache-inhibited
339 isync ; Toss prefetches
340
341 lis r7,0xE000 ; Get the unlikeliest ESID possible
342 srdi r7,r7,1 ; Make 0x7FFFFFFFF0000000
343 slbie r7 ; Make sure the ERAT is cleared
344
345 mtmsrd r12 ; Restore entry MSR
346 isync
347
348 stw r11,0(r4) ; Pass back the result
349 li r3,1 ; Indicate success
350 blr ; Leave...
351
352mprFail: li r3,0 ; Set failure
353 blr ; Leave...
354
355; Force a line boundry here. This means we will be able to check addresses better
356 .align 6
357 .globl EXT(ml_probe_read_mck_64)
358LEXT(ml_probe_read_mck_64)
359
360
361/* Read physical address byte
1c79356b
A
362 *
363 * unsigned int ml_phys_read_byte(vm_offset_t paddr)
55e303ae 364 * unsigned int ml_phys_read_byte_64(addr64_t paddr)
1c79356b
A
365 *
366 * Read the byte at physical address paddr. Memory should not be cache inhibited.
367 */
368
369; Force a line boundry here
55e303ae 370
1c79356b 371 .align 5
55e303ae
A
372 .globl EXT(ml_phys_read_byte_64)
373
374LEXT(ml_phys_read_byte_64)
375
376 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
377 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
378 b ml_phys_read_byte_join
379
1c79356b
A
380 .globl EXT(ml_phys_read_byte)
381
382LEXT(ml_phys_read_byte)
55e303ae
A
383 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
384ml_phys_read_byte_join: ; r3 = address to read (reg64_t)
385 mflr r11 ; Save the return
386 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
387
388 lbz r3,0(r3) ; Get the byte
389 b rdwrpost ; Clean up and leave...
d7e50217 390
d7e50217 391
55e303ae
A
392/* Read physical address half word
393 *
394 * unsigned int ml_phys_read_half(vm_offset_t paddr)
395 * unsigned int ml_phys_read_half_64(addr64_t paddr)
396 *
397 * Read the half word at physical address paddr. Memory should not be cache inhibited.
398 */
1c79356b 399
55e303ae 400; Force a line boundry here
d7e50217 401
55e303ae
A
402 .align 5
403 .globl EXT(ml_phys_read_half_64)
404
405LEXT(ml_phys_read_half_64)
406
407 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
408 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
409 b ml_phys_read_half_join
d7e50217 410
55e303ae
A
411 .globl EXT(ml_phys_read_half)
412
413LEXT(ml_phys_read_half)
414 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
415ml_phys_read_half_join: ; r3 = address to read (reg64_t)
416 mflr r11 ; Save the return
417 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
418
419 lhz r3,0(r3) ; Get the half word
420 b rdwrpost ; Clean up and leave...
421
422
423/* Read physical address word
1c79356b
A
424 *
425 * unsigned int ml_phys_read(vm_offset_t paddr)
55e303ae
A
426 * unsigned int ml_phys_read_64(addr64_t paddr)
427 * unsigned int ml_phys_read_word(vm_offset_t paddr)
428 * unsigned int ml_phys_read_word_64(addr64_t paddr)
1c79356b
A
429 *
430 * Read the word at physical address paddr. Memory should not be cache inhibited.
431 */
432
433; Force a line boundry here
55e303ae 434
1c79356b 435 .align 5
55e303ae
A
436 .globl EXT(ml_phys_read_64)
437 .globl EXT(ml_phys_read_word_64)
438
439LEXT(ml_phys_read_64)
440LEXT(ml_phys_read_word_64)
441
442 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
443 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
444 b ml_phys_read_word_join
445
1c79356b 446 .globl EXT(ml_phys_read)
55e303ae 447 .globl EXT(ml_phys_read_word)
1c79356b
A
448
449LEXT(ml_phys_read)
55e303ae
A
450LEXT(ml_phys_read_word)
451 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
452ml_phys_read_word_join: ; r3 = address to read (reg64_t)
453 mflr r11 ; Save the return
454 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
455
456 lwz r3,0(r3) ; Get the word
457 b rdwrpost ; Clean up and leave...
d7e50217 458
d7e50217 459
55e303ae
A
460/* Read physical address double word
461 *
462 * unsigned long long ml_phys_read_double(vm_offset_t paddr)
463 * unsigned long long ml_phys_read_double_64(addr64_t paddr)
464 *
465 * Read the double word at physical address paddr. Memory should not be cache inhibited.
466 */
467
468; Force a line boundry here
469
470 .align 5
471 .globl EXT(ml_phys_read_double_64)
472
473LEXT(ml_phys_read_double_64)
474
475 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
476 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
477 b ml_phys_read_double_join
478
479 .globl EXT(ml_phys_read_double)
480
481LEXT(ml_phys_read_double)
482 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
483ml_phys_read_double_join: ; r3 = address to read (reg64_t)
484 mflr r11 ; Save the return
485 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
1c79356b 486
55e303ae
A
487 lwz r4,4(r3) ; Get the low word
488 lwz r3,0(r3) ; Get the high word
489 b rdwrpost ; Clean up and leave...
1c79356b 490
1c79356b
A
491
492/* Write physical address byte
493 *
494 * void ml_phys_write_byte(vm_offset_t paddr, unsigned int data)
55e303ae 495 * void ml_phys_write_byte_64(addr64_t paddr, unsigned int data)
1c79356b
A
496 *
497 * Write the byte at physical address paddr. Memory should not be cache inhibited.
498 */
499
1c79356b 500 .align 5
55e303ae
A
501 .globl EXT(ml_phys_write_byte_64)
502
503LEXT(ml_phys_write_byte_64)
504
505 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
506 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
507 mr r4,r5 ; Copy over the data
508 b ml_phys_write_byte_join
509
1c79356b
A
510 .globl EXT(ml_phys_write_byte)
511
512LEXT(ml_phys_write_byte)
55e303ae
A
513 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
514ml_phys_write_byte_join: ; r3 = address to write (reg64_t), r4 = data
515 mflr r11 ; Save the return
516 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
517
518 stb r4,0(r3) ; Set the byte
519 b rdwrpost ; Clean up and leave...
1c79356b 520
d7e50217 521
55e303ae
A
522/* Write physical address half word
523 *
524 * void ml_phys_write_half(vm_offset_t paddr, unsigned int data)
525 * void ml_phys_write_half_64(addr64_t paddr, unsigned int data)
526 *
527 * Write the half word at physical address paddr. Memory should not be cache inhibited.
528 */
529
530 .align 5
531 .globl EXT(ml_phys_write_half_64)
532
533LEXT(ml_phys_write_half_64)
534
535 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
536 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
537 mr r4,r5 ; Copy over the data
538 b ml_phys_write_half_join
539
540 .globl EXT(ml_phys_write_half)
541
542LEXT(ml_phys_write_half)
543 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
544ml_phys_write_half_join: ; r3 = address to write (reg64_t), r4 = data
545 mflr r11 ; Save the return
546 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
1c79356b 547
55e303ae
A
548 sth r4,0(r3) ; Set the half word
549 b rdwrpost ; Clean up and leave...
1c79356b 550
1c79356b 551
55e303ae 552/* Write physical address word
1c79356b
A
553 *
554 * void ml_phys_write(vm_offset_t paddr, unsigned int data)
55e303ae
A
555 * void ml_phys_write_64(addr64_t paddr, unsigned int data)
556 * void ml_phys_write_word(vm_offset_t paddr, unsigned int data)
557 * void ml_phys_write_word_64(addr64_t paddr, unsigned int data)
1c79356b
A
558 *
559 * Write the word at physical address paddr. Memory should not be cache inhibited.
560 */
561
1c79356b 562 .align 5
55e303ae
A
563 .globl EXT(ml_phys_write_64)
564 .globl EXT(ml_phys_write_word_64)
565
566LEXT(ml_phys_write_64)
567LEXT(ml_phys_write_word_64)
568
569 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
570 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
571 mr r4,r5 ; Copy over the data
572 b ml_phys_write_word_join
573
1c79356b 574 .globl EXT(ml_phys_write)
55e303ae 575 .globl EXT(ml_phys_write_word)
1c79356b
A
576
577LEXT(ml_phys_write)
55e303ae
A
578LEXT(ml_phys_write_word)
579 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
580ml_phys_write_word_join: ; r3 = address to write (reg64_t), r4 = data
581 mflr r11 ; Save the return
582 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
583
584 stw r4,0(r3) ; Set the word
585 b rdwrpost ; Clean up and leave...
d7e50217 586
d7e50217 587
55e303ae
A
588/* Write physical address double word
589 *
590 * void ml_phys_write_double(vm_offset_t paddr, unsigned long long data)
591 * void ml_phys_write_double_64(addr64_t paddr, unsigned long long data)
592 *
593 * Write the double word at physical address paddr. Memory should not be cache inhibited.
594 */
595
596 .align 5
597 .globl EXT(ml_phys_write_double_64)
598
599LEXT(ml_phys_write_double_64)
600
601 rlwinm r3,r3,0,1,0 ; Copy low 32 bits to top 32
602 rlwimi r3,r4,0,0,31 ; Insert low part of 64-bit address in bottom 32 bits
603 mr r4,r5 ; Copy over the high data
604 mr r5,r6 ; Copy over the low data
605 b ml_phys_write_double_join
606
607 .globl EXT(ml_phys_write_double)
608
609LEXT(ml_phys_write_double)
610 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
611ml_phys_write_double_join: ; r3 = address to write (reg64_t), r4,r5 = data (long long)
612 mflr r11 ; Save the return
613 bl rdwrpre ; Get set up, translation/interrupts off, 64-bit on, etc.
614
615 stw r4,0(r3) ; Set the high word
616 stw r5,4(r3) ; Set the low word
617 b rdwrpost ; Clean up and leave...
618
619
620 .align 5
621
622rdwrpre: mfsprg r12,2 ; Get feature flags
623 lis r8,hi16(MASK(MSR_VEC)) ; Get the vector flag
624 mfmsr r10 ; Save the MSR
625 ori r8,r8,lo16(MASK(MSR_FP)) ; Add the FP flag
626 mtcrf 0x02,r12 ; move pf64Bit
627 andc r10,r10,r8 ; Clear VEC and FP
628 ori r9,r8,lo16(MASK(MSR_EE)|MASK(MSR_IR)|MASK(MSR_DR)) ; Drop EE, DR, and IR
629 li r2,1 ; Prepare for 64 bit
630 andc r9,r10,r9 ; Clear VEC, FP, DR, and EE
631 bf-- pf64Bitb,rdwrpre32 ; Join 32-bit code...
632
633 srdi r7,r3,31 ; Get a 1 if address is in I/O memory
634 rldimi r9,r2,63,MSR_SF_BIT ; set SF bit (bit 0)
635 cmpldi cr7,r7,1 ; Is source in I/O memory?
636 mtmsrd r9 ; set 64-bit mode, turn off EE, DR, and IR
637 isync ; synchronize
638
639 sldi r0,r2,32+8 ; Get the right bit to turn off caching
640
641 bnelr++ cr7 ; We are not in the I/O area, all ready...
642
643 mfspr r8,hid4 ; Get HID4
644 or r2,r8,r0 ; Set bit to make real accesses cache-inhibited
645 sync ; Sync up
646 mtspr hid4,r2 ; Make real accesses cache-inhibited
647 isync ; Toss prefetches
648
649 lis r7,0xE000 ; Get the unlikeliest ESID possible
650 srdi r7,r7,1 ; Make 0x7FFFFFFFF0000000
651 slbie r7 ; Make sure the ERAT is cleared
1c79356b 652
1c79356b 653 sync
55e303ae
A
654 isync
655 blr ; Finally, all ready...
656
657 .align 5
658
659rdwrpre32: rlwimi r9,r10,0,MSR_IR_BIT,MSR_IR_BIT ; Leave the IR bit unchanged
660 mtmsr r9 ; Drop EE, DR, and leave IR unchanged
661 isync
662 blr ; All set up, leave...
663
664 .align 5
665
666rdwrpost: mtlr r11 ; Restore the return
667 bt++ pf64Bitb,rdwrpost64 ; Join 64-bit code...
668
669 mtmsr r10 ; Restore entry MSR (sans FP and VEC)
670 isync
671 blr ; Leave...
672
673rdwrpost64: bne++ cr7,rdwrpcok ; Skip enabling real mode caching if we did not change it...
1c79356b 674
55e303ae
A
675 sync ; Sync up
676 mtspr hid4,r8 ; Make real accesses not cache-inhibited
677 isync ; Toss prefetches
678
679 lis r7,0xE000 ; Get the unlikeliest ESID possible
680 srdi r7,r7,1 ; Make 0x7FFFFFFFF0000000
681 slbie r7 ; Make sure the ERAT is cleared
682
683rdwrpcok: mtmsrd r10 ; Restore entry MSR (sans FP and VEC)
1c79356b 684 isync
55e303ae 685 blr ; Leave...
1c79356b
A
686
687
688/* set interrupts enabled or disabled
689 *
690 * boolean_t set_interrupts_enabled(boolean_t enable)
691 *
692 * Set EE bit to "enable" and return old value as boolean
693 */
694
695; Force a line boundry here
0b4e3aa0
A
696 .align 5
697 .globl EXT(ml_set_interrupts_enabled)
698
699LEXT(ml_set_interrupts_enabled)
1c79356b 700
55e303ae
A
701 andi. r4,r3,1 ; Are we turning interruptions on?
702 lis r0,hi16(MASK(MSR_VEC)) ; Get vector enable
1c79356b 703 mfmsr r5 ; Get the current MSR
55e303ae 704 ori r0,r0,lo16(MASK(MSR_EE)|MASK(MSR_FP)) ; Get float enable and EE enable
1c79356b 705 rlwinm r3,r5,17,31,31 ; Set return value
55e303ae
A
706 andc r5,r5,r0 ; Force VEC and FP off
707 bne CheckPreemption ; Interrupts going on, check ASTs...
708
709 mtmsr r5 ; Slam diable (always going disabled here)
710 isync ; Need this because FP/Vec might go off
1c79356b
A
711 blr
712
55e303ae
A
713 .align 5
714
d7e50217 715CheckPreemption:
55e303ae
A
716 mfsprg r7,0
717 ori r5,r5,lo16(MASK(MSR_EE)) ; Turn on the enable
718 lwz r8,PP_NEED_AST(r7) ; Get pointer to AST flags
719 mfsprg r9,1 ; Get current activation
720 li r6,AST_URGENT ; Get the type we will preempt for
721 lwz r7,ACT_PREEMPT_CNT(r9) ; Get preemption count
722 lwz r8,0(r8) ; Get AST flags
723 lis r0,hi16(DoPreemptCall) ; High part of Preempt FW call
724 cmpwi cr1,r7,0 ; Are preemptions masked off?
725 and. r8,r8,r6 ; Are we urgent?
726 crorc cr1_eq,cr0_eq,cr1_eq ; Remember if preemptions are masked or not urgent
727 ori r0,r0,lo16(DoPreemptCall) ; Bottome of FW call
728
d7e50217 729 mtmsr r5 ; Restore the MSR now, before we can preempt
55e303ae
A
730 isync ; Need this because FP/Vec might go off
731
732 beqlr++ cr1 ; Return if no premption...
d7e50217 733 sc ; Preempt
0b4e3aa0
A
734 blr
735
de355530
A
736/* Emulate a decremeter exception
737 *
738 * void machine_clock_assist(void)
739 *
740 */
741
742; Force a line boundry here
743 .align 5
744 .globl EXT(machine_clock_assist)
745
746LEXT(machine_clock_assist)
747
748 mfsprg r7,0
749 lwz r4,PP_INTS_ENABLED(r7)
750 mr. r4,r4
55e303ae
A
751 bnelr+ cr0
752 b EXT(CreateFakeDEC)
de355530 753
1c79356b
A
754/* Set machine into idle power-saving mode.
755 *
756 * void machine_idle_ppc(void)
757 *
758 * We will use the PPC NAP or DOZE for this.
759 * This call always returns. Must be called with spllo (i.e., interruptions
760 * enabled).
761 *
762 */
763
1c79356b
A
764; Force a line boundry here
765 .align 5
766 .globl EXT(machine_idle_ppc)
767
768LEXT(machine_idle_ppc)
769
55e303ae
A
770 lis r0,hi16(MASK(MSR_VEC)) ; Get the vector flag
771 mfmsr r3 ; Save the MSR
772 ori r0,r0,lo16(MASK(MSR_FP)) ; Add the FP flag
773 andc r3,r3,r0 ; Clear VEC and FP
774 ori r0,r0,lo16(MASK(MSR_EE)) ; Drop EE also
775 andc r5,r3,r0 ; Clear VEC, FP, DR, and EE
776
1c79356b 777 mtmsr r5 ; Hold up interruptions for now
9bccf70c 778 isync ; May have messed with fp/vec
1c79356b 779 mfsprg r12,0 ; Get the per_proc_info
de355530 780 mfsprg r11,2 ; Get CPU specific features
55e303ae 781 mfspr r6,hid0 ; Get the current power-saving mode
1c79356b
A
782 mtcrf 0xC7,r11 ; Get the facility flags
783
784 lis r4,hi16(napm) ; Assume we can nap
785 bt pfWillNapb,yesnap ; Yeah, nap is ok...
786
787 lis r4,hi16(dozem) ; Assume we can doze
788 bt pfCanDozeb,yesnap ; We can sleep or doze one this machine...
789
790 ori r3,r3,lo16(MASK(MSR_EE)) ; Flip on EE
791 mtmsr r3 ; Turn interruptions back on
792 blr ; Leave...
793
794yesnap: mftbu r9 ; Get the upper timebase
795 mftb r7 ; Get the lower timebase
796 mftbu r8 ; Get the upper one again
797 cmplw r9,r8 ; Did the top tick?
798 bne- yesnap ; Yeah, need to get it again...
799 stw r8,napStamp(r12) ; Set high order time stamp
800 stw r7,napStamp+4(r12) ; Set low order nap stamp
d52fe63f 801
55e303ae 802 rlwinm. r7,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before nap?
9bccf70c
A
803 beq miL2PFok
804
805 mfspr r7,msscr0 ; Get currect MSSCR0 value
55e303ae 806 rlwinm r7,r7,0,0,l2pfes-1 ; Disable L2 Prefetch
9bccf70c
A
807 mtspr msscr0,r7 ; Updates MSSCR0 value
808 sync
809 isync
810
811miL2PFok:
55e303ae 812 rlwinm. r7,r11,0,pfSlowNapb,pfSlowNapb ; Should nap at slow speed?
9bccf70c
A
813 beq minoslownap
814
815 mfspr r7,hid1 ; Get current HID1 value
55e303ae 816 oris r7,r7,hi16(hid1psm) ; Select PLL1
9bccf70c
A
817 mtspr hid1,r7 ; Update HID1 value
818
819minoslownap:
d52fe63f 820
1c79356b
A
821;
822; We have to open up interruptions here because book 4 says that we should
823; turn on only the POW bit and that we should have interrupts enabled
824; The interrupt handler will detect that nap or doze is set if an interrupt
825; is taken and set everything up to return directly to machine_idle_ret.
826; So, make sure everything we need there is already set up...
827;
55e303ae 828
ab86ba33 829 lis r10,hi16(dozem|napm|sleepm) ; Mask of power management bits
55e303ae
A
830
831 bf-- pf64Bitb,mipNSF1 ; skip if 32-bit...
832
833 sldi r4,r4,32 ; Position the flags
834 sldi r10,r10,32 ; Position the masks
835
836
837mipNSF1: andc r6,r6,r10 ; Clean up the old power bits
838
1c79356b
A
839 ori r7,r5,lo16(MASK(MSR_EE)) ; Flip on EE
840 or r6,r6,r4 ; Set nap or doze
841 oris r5,r7,hi16(MASK(MSR_POW)) ; Turn on power management in next MSR
55e303ae
A
842
843 sync
1c79356b 844 mtspr hid0,r6 ; Set up the HID for nap/doze
55e303ae
A
845 mfspr r6,hid0 ; Yes, this is silly, keep it here
846 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
847 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
848 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
849 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
850 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
1c79356b 851 isync ; Make sure it is set
55e303ae 852
1c79356b
A
853 mtmsr r7 ; Enable for interrupts
854 rlwinm. r11,r11,0,pfAltivecb,pfAltivecb ; Do we have altivec?
855 beq- minovec ; No...
856 dssall ; Stop the streams before we nap/doze
857
858minovec: sync ; Make sure queues are clear
859 mtmsr r5 ; Nap or doze
860 isync ; Make sure this takes before we proceed
861 b minovec ; loop if POW does not take
862;
863; Note that the interrupt handler will turn off the nap/doze bits in the hid.
864; Also remember that the interrupt handler will force return to here whenever
865; the nap/doze bits are set.
866;
867 .globl EXT(machine_idle_ret)
868LEXT(machine_idle_ret)
869 mtmsr r7 ; Make sure the MSR is what we want
870 isync ; In case we turn on translation
871
872 blr ; Return...
873
874/* Put machine to sleep.
875 * This call never returns. We always exit sleep via a soft reset.
876 * All external interruptions must be drained at this point and disabled.
877 *
878 * void ml_ppc_sleep(void)
879 *
880 * We will use the PPC SLEEP for this.
881 *
882 * There is one bit of hackery in here: we need to enable for
883 * interruptions when we go to sleep and there may be a pending
884 * decrimenter rupt. So we make the decrimenter 0x7FFFFFFF and enable for
885 * interruptions. The decrimenter rupt vector recognizes this and returns
886 * directly back here.
887 *
888 */
889
890; Force a line boundry here
891 .align 5
892 .globl EXT(ml_ppc_sleep)
893
894LEXT(ml_ppc_sleep)
895
896#if 0
897 mfmsr r5 ; Hack to spin instead of sleep
898 rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
899 rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
900 mtmsr r5 ; No talking
901 isync
902
1c79356b
A
903deadsleep: addi r3,r3,1 ; Make analyzer happy
904 addi r3,r3,1
905 addi r3,r3,1
906 b deadsleep ; Die the death of 1000 joys...
907#endif
908
55e303ae 909 mfsprg r12,0 ; Get the per_proc_info
1c79356b
A
910 mfspr r4,hid0 ; Get the current power-saving mode
911 eqv r10,r10,r10 ; Get all foxes
912 mfsprg r11,2 ; Get CPU specific features
9bccf70c 913
55e303ae 914 rlwinm. r5,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before sleep?
9bccf70c
A
915 beq mpsL2PFok
916
917 mfspr r5,msscr0 ; Get currect MSSCR0 value
55e303ae 918 rlwinm r5,r5,0,0,l2pfes-1 ; Disable L2 Prefetch
9bccf70c
A
919 mtspr msscr0,r5 ; Updates MSSCR0 value
920 sync
921 isync
922
923mpsL2PFok:
55e303ae
A
924 rlwinm. r5,r11,0,pf64Bitb,pf64Bitb ; PM bits are shifted on 64bit systems.
925 bne mpsPF64bit
926
927 rlwinm r4,r4,0,sleep+1,doze-1 ; Clear all possible power-saving modes (not DPM though)
928 oris r4,r4,hi16(sleepm) ; Set sleep
929 b mpsClearDEC
930
931mpsPF64bit:
932 lis r5, hi16(dozem|napm|sleepm) ; Clear all possible power-saving modes (not DPM though)
933 sldi r5, r5, 32
934 andc r4, r4, r5
935 lis r5, hi16(napm) ; Set sleep
936// lis r5, hi16(dozem) ; Set sleep
937 sldi r5, r5, 32
938 or r4, r4, r5
939
940mpsClearDEC:
1c79356b
A
941 mfmsr r5 ; Get the current MSR
942 rlwinm r10,r10,0,1,31 ; Make 0x7FFFFFFF
1c79356b
A
943 mtdec r10 ; Load decrimenter with 0x7FFFFFFF
944 isync ; and make sure,
945 mfdec r9 ; really sure, it gets there
946
947 mtcrf 0x07,r11 ; Get the cache flags, etc
948
1c79356b
A
949 rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
950;
951; Note that we need translation off before we set the HID to sleep. Otherwise
952; we will ignore any PTE misses that occur and cause an infinite loop.
953;
954 bt pfNoMSRirb,mpsNoMSR ; No MSR...
955
956 mtmsr r5 ; Translation off
957 isync ; Toss prefetch
958 b mpsNoMSRx
959
960mpsNoMSR:
961 li r0,loadMSR ; Get the MSR setter SC
962 mr r3,r5 ; Get new MSR
963 sc ; Set it
964mpsNoMSRx:
965
966 ori r3,r5,lo16(MASK(MSR_EE)) ; Flip on EE
967 sync
968 mtspr hid0,r4 ; Set up the HID to sleep
55e303ae
A
969 mfspr r4,hid0 ; Yes, this is silly, keep it here
970 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
971 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
972 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
973 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
974 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1c79356b
A
975
976 mtmsr r3 ; Enable for interrupts to drain decrimenter
977
978 add r6,r4,r5 ; Just waste time
979 add r6,r6,r4 ; A bit more
980 add r6,r6,r5 ; A bit more
981
982 mtmsr r5 ; Interruptions back off
983 isync ; Toss prefetch
984
1c79356b
A
985;
986; We are here with translation off, interrupts off, all possible
987; interruptions drained off, and a decrimenter that will not pop.
988;
989
990 bl EXT(cacheInit) ; Clear out the caches. This will leave them on
991 bl EXT(cacheDisable) ; Turn off all caches
992
993 mfmsr r5 ; Get the current MSR
994 oris r5,r5,hi16(MASK(MSR_POW)) ; Turn on power management in next MSR
995 ; Leave EE off because power goes off shortly
55e303ae
A
996 mfsprg r12,0 ; Get the per_proc_info
997 li r10,PP_CPU_FLAGS
998 lhz r11,PP_CPU_FLAGS(r12) ; Get the flags
999 ori r11,r11,SleepState ; Marked SleepState
1000 sth r11,PP_CPU_FLAGS(r12) ; Set the flags
1001 dcbf r10,r12
1002slSleepNow:
1003 sync ; Sync it all up
1c79356b
A
1004 mtmsr r5 ; Do sleep with interruptions enabled
1005 isync ; Take a pill
1006 b slSleepNow ; Go back to sleep if we wake up...
1007
1008
1009
1010/* Initialize all caches including the TLBs
1011 *
1012 * void cacheInit(void)
1013 *
1014 * This is used to force the caches to an initial clean state. First, we
1015 * check if the cache is on, if so, we need to flush the contents to memory.
1016 * Then we invalidate the L1. Next, we configure and invalidate the L2 etc.
1017 * Finally we turn on all of the caches
1018 *
1019 * Note that if translation is not disabled when this is called, the TLB will not
1020 * be completely clear after return.
1021 *
1022 */
1023
1024; Force a line boundry here
1025 .align 5
1026 .globl EXT(cacheInit)
1027
1028LEXT(cacheInit)
1029
1030 mfsprg r12,0 ; Get the per_proc_info
1031 mfspr r9,hid0 ; Get the current power-saving mode
1032
1033 mfsprg r11,2 ; Get CPU specific features
1034 mfmsr r7 ; Get the current MSR
9bccf70c
A
1035 rlwinm r7,r7,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1036 rlwinm r7,r7,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
0b4e3aa0 1037 rlwimi r11,r11,pfLClckb+1,31,31 ; Move pfLClck to another position (to keep from using non-volatile CRs)
1c79356b
A
1038 rlwinm r5,r7,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
1039 rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1040 mtcrf 0x87,r11 ; Get the feature flags
55e303ae
A
1041 lis r10,hi16(dozem|napm|sleepm|dpmm) ; Mask of power management bits
1042 bf-- pf64Bitb,cIniNSF1 ; Skip if 32-bit...
1043
1044 sldi r10,r10,32 ; Position the masks
1045
1046cIniNSF1: andc r4,r9,r10 ; Clean up the old power bits
1c79356b 1047 mtspr hid0,r4 ; Set up the HID
55e303ae
A
1048 mfspr r4,hid0 ; Yes, this is silly, keep it here
1049 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1050 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1051 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1052 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1053 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1c79356b
A
1054
1055 bt pfNoMSRirb,ciNoMSR ; No MSR...
1056
1057 mtmsr r5 ; Translation and all off
1058 isync ; Toss prefetch
1059 b ciNoMSRx
1060
1061ciNoMSR:
1062 li r0,loadMSR ; Get the MSR setter SC
1063 mr r3,r5 ; Get new MSR
1064 sc ; Set it
1065ciNoMSRx:
1066
1067 bf pfAltivecb,cinoDSS ; No Altivec here...
1068
1069 dssall ; Stop streams
1070 sync
1071
55e303ae 1072cinoDSS: li r5,tlbieLock ; Get the TLBIE lock
1c79356b 1073 li r0,128 ; Get number of TLB entries
1c79356b
A
1074
1075 li r6,0 ; Start at 0
55e303ae
A
1076 bf-- pf64Bitb,citlbhang ; Skip if 32-bit...
1077 li r0,1024 ; Get the number of TLB entries
1c79356b
A
1078
1079citlbhang: lwarx r2,0,r5 ; Get the TLBIE lock
1080 mr. r2,r2 ; Is it locked?
1081 bne- citlbhang ; It is locked, go wait...
1082 stwcx. r0,0,r5 ; Try to get it
1083 bne- citlbhang ; We was beat...
1084
1085 mtctr r0 ; Set the CTR
1086
1087cipurgeTLB: tlbie r6 ; Purge this entry
1088 addi r6,r6,4096 ; Next page
1089 bdnz cipurgeTLB ; Do them all...
1090
1091 mtcrf 0x80,r11 ; Set SMP capability
1092 sync ; Make sure all TLB purges are done
1093 eieio ; Order, order in the court
1094
1095 bf pfSMPcapb,cinoSMP ; SMP incapable...
1096
1097 tlbsync ; Sync all TLBs
1098 sync
150bd074 1099 isync
1c79356b 1100
55e303ae
A
1101 bf-- pf64Bitb,cinoSMP ; Skip if 32-bit...
1102 ptesync ; Wait for quiet again
1103 sync
1104
1105cinoSMP: stw r2,tlbieLock(0) ; Unlock TLBIE lock
1106
1107 bt++ pf64Bitb,cin64 ; Skip if 64-bit...
1c79356b 1108
1c79356b
A
1109 rlwinm. r0,r9,0,ice,dce ; Were either of the level 1s on?
1110 beq- cinoL1 ; No, no need to flush...
1111
55e303ae
A
1112 rlwinm. r0,r11,0,pfL1fab,pfL1fab ; do we have L1 flush assist?
1113 beq ciswdl1 ; If no hw flush assist, go do by software...
1c79356b
A
1114
1115 mfspr r8,msscr0 ; Get the memory system control register
1116 oris r8,r8,hi16(dl1hwfm) ; Turn on the hardware flush request
1117
1118 mtspr msscr0,r8 ; Start the flush operation
1119
1120ciwdl1f: mfspr r8,msscr0 ; Get the control register again
1121
1122 rlwinm. r8,r8,0,dl1hwf,dl1hwf ; Has the flush request been reset yet?
1123 bne ciwdl1f ; No, flush is still in progress...
1124 b ciinvdl1 ; Go invalidate l1...
1125
1126;
1127; We need to either make this very complicated or to use ROM for
1128; the flush. The problem is that if during the following sequence a
1129; snoop occurs that invalidates one of the lines in the cache, the
1130; PLRU sequence will be altered making it possible to miss lines
1131; during the flush. So, we either need to dedicate an area of RAM
1132; to each processor, lock use of a RAM area, or use ROM. ROM is
1133; by far the easiest. Note that this is not an issue for machines
1134; that have harware flush assists.
1135;
1136
1137ciswdl1: lwz r0,pfl1dSize(r12) ; Get the level 1 cache size
0b4e3aa0
A
1138
1139 bf 31,cisnlck ; Skip if pfLClck not set...
1140
1141 mfspr r4,msscr0 ; ?
1142 rlwinm r6,r4,0,0,l2pfes-1 ; ?
1143 mtspr msscr0,r6 ; Set it
1144 sync
1145 isync
1146
1147 mfspr r8,ldstcr ; Save the LDSTCR
1148 li r2,1 ; Get a mask of 0x01
1149 lis r3,0xFFF0 ; Point to ROM
1150 rlwinm r11,r0,29,3,31 ; Get the amount of memory to handle all indexes
1151
1152 li r6,0 ; Start here
1153
1154cisiniflsh: dcbf r6,r3 ; Flush each line of the range we use
1155 addi r6,r6,32 ; Bump to the next
1156 cmplw r6,r0 ; Have we reached the end?
1157 blt+ cisiniflsh ; Nope, continue initial flush...
1158
1159 sync ; Make sure it is done
1160
1161 addi r11,r11,-1 ; Get mask for index wrap
1162 li r6,0 ; Get starting offset
1163
1164cislckit: not r5,r2 ; Lock all but 1 way
1165 rlwimi r5,r8,0,0,23 ; Build LDSTCR
1166 mtspr ldstcr,r5 ; Lock a way
1167 sync ; Clear out memory accesses
1168 isync ; Wait for all
1169
1170
1171cistouch: lwzx r10,r3,r6 ; Pick up some trash
1172 addi r6,r6,32 ; Go to the next index
1173 and. r0,r6,r11 ; See if we are about to do next index
1174 bne+ cistouch ; Nope, do more...
1175
1176 sync ; Make sure it is all done
1177 isync
1178
1179 sub r6,r6,r11 ; Back up to start + 1
1180 addi r6,r6,-1 ; Get it right
1181
1182cisflush: dcbf r3,r6 ; Flush everything out
1183 addi r6,r6,32 ; Go to the next index
1184 and. r0,r6,r11 ; See if we are about to do next index
1185 bne+ cisflush ; Nope, do more...
1186
1187 sync ; Make sure it is all done
1188 isync
1189
1190
1191 rlwinm. r2,r2,1,24,31 ; Shift to next way
1192 bne+ cislckit ; Do this for all ways...
1193
1194 mtspr ldstcr,r8 ; Slam back to original
1195 sync
1196 isync
1197
1198 mtspr msscr0,r4 ; ?
1199 sync
1200 isync
1201
1202 b cinoL1 ; Go on to level 2...
1203
1204
1205cisnlck: rlwinm r2,r0,0,1,30 ; Double cache size
1c79356b
A
1206 add r0,r0,r2 ; Get 3 times cache size
1207 rlwinm r0,r0,26,6,31 ; Get 3/2 number of cache lines
1208 lis r3,0xFFF0 ; Dead recon ROM address for now
1209 mtctr r0 ; Number of lines to flush
1210
1211ciswfldl1a: lwz r2,0(r3) ; Flush anything else
1212 addi r3,r3,32 ; Next line
1213 bdnz ciswfldl1a ; Flush the lot...
1214
1215ciinvdl1: sync ; Make sure all flushes have been committed
1216
1217 mfspr r8,hid0 ; Get the HID0 bits
1218 rlwinm r8,r8,0,dce+1,ice-1 ; Clear cache enables
1219 mtspr hid0,r8 ; and turn off L1 cache
1220 sync ; Make sure all is done
0b4e3aa0
A
1221 isync
1222
1c79356b
A
1223 ori r8,r8,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate
1224 sync
1225 isync
1226
1227 mtspr hid0,r8 ; Start the invalidate and turn on cache
1228 rlwinm r8,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits
1229 mtspr hid0,r8 ; Turn off the invalidate (needed for some older machines)
1230 sync
0b4e3aa0 1231
1c79356b
A
1232
1233cinoL1:
1234;
1235; Flush and disable the level 2
1236;
55e303ae
A
1237 mfsprg r10,2 ; need to check 2 features we did not put in CR
1238 rlwinm. r0,r10,0,pfL2b,pfL2b ; do we have L2?
1239 beq cinol2 ; No level 2 cache to flush
1c79356b
A
1240
1241 mfspr r8,l2cr ; Get the L2CR
1242 lwz r3,pfl2cr(r12) ; Get the L2CR value
d52fe63f
A
1243 rlwinm. r0,r8,0,l2e,l2e ; Was the L2 enabled?
1244 bne ciflushl2 ; Yes, force flush
1245 cmplwi r8, 0 ; Was the L2 all the way off?
1246 beq ciinvdl2 ; Yes, force invalidate
1c79356b
A
1247 lis r0,hi16(l2sizm|l2clkm|l2ramm|l2ohm) ; Get confiuration bits
1248 xor r2,r8,r3 ; Get changing bits?
1249 ori r0,r0,lo16(l2slm|l2dfm|l2bypm) ; More config bits
1250 and. r0,r0,r2 ; Did any change?
1251 bne- ciinvdl2 ; Yes, just invalidate and get PLL synced...
1252
d52fe63f 1253ciflushl2:
55e303ae
A
1254 rlwinm. r0,r10,0,pfL2fab,pfL2fab ; hardware-assisted L2 flush?
1255 beq ciswfl2 ; Flush not in hardware...
1c79356b 1256
d52fe63f 1257 mr r10,r8 ; Take a copy now
1c79356b 1258
0b4e3aa0 1259 bf 31,cinol2lck ; Skip if pfLClck not set...
1c79356b
A
1260
1261 oris r10,r10,hi16(l2ionlym|l2donlym) ; Set both instruction- and data-only
1262 sync
1263 mtspr l2cr,r10 ; Lock out the cache
1264 sync
1265 isync
1266
1267cinol2lck: ori r10,r10,lo16(l2hwfm) ; Request flush
1268 sync ; Make sure everything is done
1269
1270 mtspr l2cr,r10 ; Request flush
1271
1272cihwfl2: mfspr r10,l2cr ; Get back the L2CR
1273 rlwinm. r10,r10,0,l2hwf,l2hwf ; Is the flush over?
1274 bne+ cihwfl2 ; Nope, keep going...
1275 b ciinvdl2 ; Flush done, go invalidate L2...
1276
1277ciswfl2:
1278 lwz r0,pfl2Size(r12) ; Get the L2 size
d52fe63f 1279 oris r2,r8,hi16(l2dom) ; Set L2 to data only mode
0b4e3aa0
A
1280
1281 b ciswfl2doa ; Branch to next line...
1282
1283 .align 5
1284ciswfl2doc:
1285 mtspr l2cr,r2 ; Disable L2
1286 sync
1287 isync
1288 b ciswfl2dod ; It is off, go invalidate it...
1289
1290ciswfl2doa:
1291 b ciswfl2dob ; Branch to next...
1292
1293ciswfl2dob:
1294 sync ; Finish memory stuff
1295 isync ; Stop speculation
1296 b ciswfl2doc ; Jump back up and turn on data only...
1297ciswfl2dod:
1c79356b
A
1298 rlwinm r0,r0,27,5,31 ; Get the number of lines
1299 lis r10,0xFFF0 ; Dead recon ROM for now
1300 mtctr r0 ; Set the number of lines
1301
1302ciswfldl2a: lwz r0,0(r10) ; Load something to flush something
1303 addi r10,r10,32 ; Next line
1304 bdnz ciswfldl2a ; Do the lot...
1305
55e303ae 1306ciinvdl2: rlwinm r8,r3,0,l2e+1,31 ; Clear the enable bit
1c79356b
A
1307 b cinla ; Branch to next line...
1308
1309 .align 5
d52fe63f 1310cinlc: mtspr l2cr,r8 ; Disable L2
1c79356b
A
1311 sync
1312 isync
1313 b ciinvl2 ; It is off, go invalidate it...
1314
1315cinla: b cinlb ; Branch to next...
1316
1317cinlb: sync ; Finish memory stuff
1318 isync ; Stop speculation
1319 b cinlc ; Jump back up and turn off cache...
1320
1321ciinvl2: sync
1322 isync
d52fe63f
A
1323
1324 cmplwi r3, 0 ; Should the L2 be all the way off?
1325 beq cinol2 ; Yes, done with L2
1326
1327 oris r2,r8,hi16(l2im) ; Get the invalidate flag set
1c79356b
A
1328
1329 mtspr l2cr,r2 ; Start the invalidate
1330 sync
1331 isync
1332ciinvdl2a: mfspr r2,l2cr ; Get the L2CR
55e303ae
A
1333 mfsprg r0,2 ; need to check a feature in "non-volatile" set
1334 rlwinm. r0,r0,0,pfL2ib,pfL2ib ; flush in HW?
1335 beq ciinvdl2b ; Flush not in hardware...
1c79356b
A
1336 rlwinm. r2,r2,0,l2i,l2i ; Is the invalidate still going?
1337 bne+ ciinvdl2a ; Assume so, this will take a looong time...
1338 sync
1339 b cinol2 ; No level 2 cache to flush
1340ciinvdl2b:
1341 rlwinm. r2,r2,0,l2ip,l2ip ; Is the invalidate still going?
1342 bne+ ciinvdl2a ; Assume so, this will take a looong time...
1343 sync
d52fe63f 1344 mtspr l2cr,r8 ; Turn off the invalidate request
1c79356b
A
1345
1346cinol2:
1347
1348;
1349; Flush and enable the level 3
1350;
1351 bf pfL3b,cinol3 ; No level 3 cache to flush
1352
1353 mfspr r8,l3cr ; Get the L3CR
1354 lwz r3,pfl3cr(r12) ; Get the L3CR value
d52fe63f
A
1355 rlwinm. r0,r8,0,l3e,l3e ; Was the L3 enabled?
1356 bne ciflushl3 ; Yes, force flush
1357 cmplwi r8, 0 ; Was the L3 all the way off?
1358 beq ciinvdl3 ; Yes, force invalidate
1c79356b
A
1359 lis r0,hi16(l3pem|l3sizm|l3dxm|l3clkm|l3spom|l3ckspm) ; Get configuration bits
1360 xor r2,r8,r3 ; Get changing bits?
1361 ori r0,r0,lo16(l3pspm|l3repm|l3rtm|l3cyam|l3dmemm|l3dmsizm) ; More config bits
1362 and. r0,r0,r2 ; Did any change?
1363 bne- ciinvdl3 ; Yes, just invalidate and get PLL synced...
1364
d52fe63f 1365ciflushl3:
1c79356b 1366 sync ; 7450 book says do this even though not needed
d52fe63f 1367 mr r10,r8 ; Take a copy now
1c79356b
A
1368
1369 bf 31,cinol3lck ; Skip if pfL23lck not set...
1370
1371 oris r10,r10,hi16(l3iom) ; Set instruction-only
1372 ori r10,r10,lo16(l3donlym) ; Set data-only
1373 sync
1374 mtspr l3cr,r10 ; Lock out the cache
1375 sync
1376 isync
1377
1378cinol3lck: ori r10,r10,lo16(l3hwfm) ; Request flush
1379 sync ; Make sure everything is done
1380
1381 mtspr l3cr,r10 ; Request flush
1382
1383cihwfl3: mfspr r10,l3cr ; Get back the L3CR
1384 rlwinm. r10,r10,0,l3hwf,l3hwf ; Is the flush over?
1385 bne+ cihwfl3 ; Nope, keep going...
1386
55e303ae 1387ciinvdl3: rlwinm r8,r3,0,l3e+1,31 ; Clear the enable bit
1c79356b 1388 sync ; Make sure of life, liberty, and justice
d52fe63f 1389 mtspr l3cr,r8 ; Disable L3
1c79356b
A
1390 sync
1391
d52fe63f
A
1392 cmplwi r3, 0 ; Should the L3 be all the way off?
1393 beq cinol3 ; Yes, done with L3
1c79356b 1394
d52fe63f 1395 ori r8,r8,lo16(l3im) ; Get the invalidate flag set
1c79356b 1396
d52fe63f
A
1397 mtspr l3cr,r8 ; Start the invalidate
1398
1399ciinvdl3b: mfspr r8,l3cr ; Get the L3CR
1400 rlwinm. r8,r8,0,l3i,l3i ; Is the invalidate still going?
1c79356b
A
1401 bne+ ciinvdl3b ; Assume so...
1402 sync
1403
d52fe63f
A
1404 lwz r10, pfBootConfig(r12) ; ?
1405 rlwinm. r10, r10, 24, 28, 31 ; ?
1406 beq ciinvdl3nopdet ; ?
1407
1408 mfspr r8,l3pdet ; ?
1409 srw r2, r8, r10 ; ?
1410 rlwimi r2, r8, 0, 24, 31 ; ?
1411 subfic r10, r10, 32 ; ?
1412 li r8, -1 ; ?
1413 ori r2, r2, 0x0080 ; ?
1414 slw r8, r8, r10 ; ?
1415 or r8, r2, r8 ; ?
1416 mtspr l3pdet, r8 ; ?
1c79356b
A
1417 isync
1418
7b1edb79 1419ciinvdl3nopdet:
d52fe63f
A
1420 mfspr r8,l3cr ; Get the L3CR
1421 rlwinm r8,r8,0,l3clken+1,l3clken-1 ; Clear the clock enable bit
1422 mtspr l3cr,r8 ; Disable the clock
1c79356b
A
1423
1424 li r2,128 ; ?
1425ciinvdl3c: addi r2,r2,-1 ; ?
1426 cmplwi r2,0 ; ?
1427 bne+ ciinvdl3c
1428
1429 mfspr r10,msssr0 ; ?
1430 rlwinm r10,r10,0,vgL3TAG+1,vgL3TAG-1 ; ?
1431 mtspr msssr0,r10 ; ?
1432 sync
1433
d52fe63f 1434 mtspr l3cr,r3 ; Enable it as desired
1c79356b
A
1435 sync
1436cinol3:
55e303ae
A
1437 mfsprg r0,2 ; need to check a feature in "non-volatile" set
1438 rlwinm. r0,r0,0,pfL2b,pfL2b ; is there an L2 cache?
1439 beq cinol2a ; No level 2 cache to enable
1c79356b
A
1440
1441 lwz r3,pfl2cr(r12) ; Get the L2CR value
d52fe63f 1442 cmplwi r3, 0 ; Should the L2 be all the way off?
55e303ae 1443 beq cinol2a : Yes, done with L2
d52fe63f 1444 mtspr l2cr,r3 ; Enable it as desired
1c79356b
A
1445 sync
1446
1447;
1448; Invalidate and turn on L1s
1449;
1450
0b4e3aa0
A
1451cinol2a:
1452 bt 31,cinoexit ; Skip if pfLClck set...
1453
1454 rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables
1c79356b
A
1455 mtspr hid0,r8 ; Turn off dem caches
1456 sync
1457
1458 ori r8,r9,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate
1459 rlwinm r9,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits
1460 sync
1461 isync
1462
1463 mtspr hid0,r8 ; Start the invalidate and turn on L1 cache
0b4e3aa0
A
1464
1465cinoexit: mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) and restore entry conditions
1c79356b
A
1466 sync
1467 mtmsr r7 ; Restore MSR to entry
1468 isync
1469 blr ; Return...
1470
1471
55e303ae
A
1472;
1473; Handle 64-bit architecture
1474; This processor can not run without caches, so we just push everything out
1475; and flush. It will be relativily clean afterwards
1476;
1477
1478 .align 5
1479
1480cin64:
1481 li r10,hi16(dozem|napm|sleepm) ; Mask of power management bits we want cleared
1482 sldi r10,r10,32 ; Position the masks
1483 andc r9,r9,r10 ; Clean up the old power bits
1484 mr r4,r9
1485 isync
1486 mtspr hid0,r4 ; Set up the HID
1487 mfspr r4,hid0 ; Yes, this is silly, keep it here
1488 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1489 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1490 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1491 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1492 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1493 isync
1494
1495 mfspr r10,hid1 ; Save hid1
1496 mfspr r4,hid4 ; Save hid4
1497 mr r12,r10 ; Really save hid1
1498 mr r11,r4 ; Get a working copy of hid4
1499
1500 li r0,0 ; Get a 0
1501 eqv r2,r2,r2 ; Get all foxes
1502
1503 rldimi r10,r0,55,7 ; Clear I$ prefetch bits (7:8)
1504
1505 isync
1506 mtspr hid1,r10 ; Stick it
1507 mtspr hid1,r10 ; Stick it again
1508 isync
1509
1510 rldimi r11,r2,38,25 ; Disable D$ prefetch (25:25)
1511
1512 sync
1513 mtspr hid4,r11 ; Stick it
1514 isync
1515
1516 li r3,8 ; Set bit 28+32
1517 sldi r3,r3,32 ; Make it bit 28
1518 or r3,r3,r11 ; Turn on the flash invalidate L1D$
1519
1520 oris r5,r11,0x0600 ; Set disable L1D$ bits
1521 sync
1522 mtspr hid4,r3 ; Invalidate
1523 isync
1524
1525 mtspr hid4,r5 ; Un-invalidate and disable L1D$
1526 isync
1527
1528 lis r8,GUSModeReg ; Get the GUS mode ring address
1529 mfsprg r0,2 ; Get the feature flags
1530 ori r8,r8,0x8000 ; Set to read data
1531 rlwinm. r0,r0,pfSCOMFixUpb+1,31,31 ; Set shift if we need a fix me up
1532
1533 sync
1534
1535 mtspr scomc,r8 ; Request the GUS mode
1536 mfspr r11,scomd ; Get the GUS mode
1537 mfspr r8,scomc ; Get back the status (we just ignore it)
1538 sync
1539 isync
1540
1541 sld r11,r11,r0 ; Fix up if needed
1542
1543 ori r6,r11,lo16(GUSMdmapen) ; Set the bit that means direct L2 cache address
1544 lis r8,GUSModeReg ; Get GUS mode register address
1545
1546 sync
1547
1548 mtspr scomd,r6 ; Set that we want direct L2 mode
1549 mtspr scomc,r8 ; Tell GUS we want direct L2 mode
1550 mfspr r3,scomc ; Get back the status
1551 sync
1552 isync
1553
1554 li r3,0 ; Clear start point
1555
1556cflushlp: lis r6,0x0040 ; Pick 4MB line as our target
1557 or r6,r6,r3 ; Put in the line offset
1558 lwz r5,0(r6) ; Load a line
1559 addis r6,r6,8 ; Roll bit 42:44
1560 lwz r5,0(r6) ; Load a line
1561 addis r6,r6,8 ; Roll bit 42:44
1562 lwz r5,0(r6) ; Load a line
1563 addis r6,r6,8 ; Roll bit 42:44
1564 lwz r5,0(r6) ; Load a line
1565 addis r6,r6,8 ; Roll bit 42:44
1566 lwz r5,0(r6) ; Load a line
1567 addis r6,r6,8 ; Roll bit 42:44
1568 lwz r5,0(r6) ; Load a line
1569 addis r6,r6,8 ; Roll bit 42:44
1570 lwz r5,0(r6) ; Load a line
1571 addis r6,r6,8 ; Roll bit 42:44
1572 lwz r5,0(r6) ; Load a line
1573
1574 addi r3,r3,128 ; Next line
1575 andis. r5,r3,8 ; Have we done enough?
1576 beq++ cflushlp ; Not yet...
1577
1578 sync
1579
1580 lis r6,0x0040 ; Pick 4MB line as our target
1581
1582cflushx: dcbf 0,r6 ; Flush line and invalidate
1583 addi r6,r6,128 ; Next line
1584 andis. r5,r6,0x0080 ; Have we done enough?
1585 beq++ cflushx ; Keep on flushing...
1586
1587 mr r3,r10 ; Copy current hid1
1588 rldimi r3,r2,54,9 ; Set force icbi match mode
1589
1590 li r6,0 ; Set start if ICBI range
1591 isync
1592 mtspr hid1,r3 ; Stick it
1593 mtspr hid1,r3 ; Stick it again
1594 isync
1595
1596cflicbi: icbi 0,r6 ; Kill I$
1597 addi r6,r6,128 ; Next line
1598 andis. r5,r6,1 ; Have we done them all?
1599 beq++ cflicbi ; Not yet...
1600
1601 lis r8,GUSModeReg ; Get GUS mode register address
1602
1603 sync
1604
1605 mtspr scomd,r11 ; Set that we do not want direct mode
1606 mtspr scomc,r8 ; Tell GUS we do not want direct mode
1607 mfspr r3,scomc ; Get back the status
1608 sync
1609 isync
1610
1611 isync
1612 mtspr hid1,r12 ; Restore entry hid1
1613 mtspr hid1,r12 ; Stick it again
1614 isync
1615
1616 sync
1617 mtspr hid4,r4 ; Restore entry hid4
1618 isync
1619
1620 sync
1621 mtmsr r7 ; Restore MSR to entry
1622 isync
1623 blr ; Return...
1624
1625
1626
1c79356b
A
1627/* Disables all caches
1628 *
1629 * void cacheDisable(void)
1630 *
1631 * Turns off all caches on the processor. They are not flushed.
1632 *
1633 */
1634
1635; Force a line boundry here
1636 .align 5
1637 .globl EXT(cacheDisable)
1638
1639LEXT(cacheDisable)
1640
1641 mfsprg r11,2 ; Get CPU specific features
1642 mtcrf 0x83,r11 ; Set feature flags
1643
1644 bf pfAltivecb,cdNoAlt ; No vectors...
1645
1646 dssall ; Stop streams
1647
1648cdNoAlt: sync
1649
55e303ae
A
1650 btlr pf64Bitb ; No way to disable a 64-bit machine...
1651
1c79356b
A
1652 mfspr r5,hid0 ; Get the hid
1653 rlwinm r5,r5,0,dce+1,ice-1 ; Clear the I- and D- cache enables
1654 mtspr hid0,r5 ; Turn off dem caches
1655 sync
1656
55e303ae
A
1657 rlwinm. r0,r11,0,pfL2b,pfL2b ; is there an L2?
1658 beq cdNoL2 ; Skip if no L2...
1659
1c79356b
A
1660 mfspr r5,l2cr ; Get the L2
1661 rlwinm r5,r5,0,l2e+1,31 ; Turn off enable bit
1662
1663 b cinlaa ; Branch to next line...
1664
1665 .align 5
1666cinlcc: mtspr l2cr,r5 ; Disable L2
1667 sync
1668 isync
1669 b cdNoL2 ; It is off, we are done...
1670
1671cinlaa: b cinlbb ; Branch to next...
1672
1673cinlbb: sync ; Finish memory stuff
1674 isync ; Stop speculation
1675 b cinlcc ; Jump back up and turn off cache...
1676
1677cdNoL2:
55e303ae 1678
1c79356b
A
1679 bf pfL3b,cdNoL3 ; Skip down if no L3...
1680
1681 mfspr r5,l3cr ; Get the L3
1682 rlwinm r5,r5,0,l3e+1,31 ; Turn off enable bit
1683 rlwinm r5,r5,0,l3clken+1,l3clken-1 ; Turn off cache enable bit
1684 mtspr l3cr,r5 ; Disable the caches
1685 sync
1686
1687cdNoL3:
1688 blr ; Leave...
1689
1690
1691/* Initialize processor thermal monitoring
1692 * void ml_thrm_init(void)
1693 *
1694 * Build initial TAU registers and start them all going.
1695 * We ca not do this at initial start up because we need to have the processor frequency first.
1696 * And just why is this in assembler when it does not have to be?? Cause I am just too
1697 * lazy to open up a "C" file, thats why.
1698 */
1699
1700; Force a line boundry here
1701 .align 5
1702 .globl EXT(ml_thrm_init)
1703
1704LEXT(ml_thrm_init)
1705
1706 mfsprg r12,0 ; Get the per_proc blok
1707 lis r11,hi16(EXT(gPEClockFrequencyInfo)) ; Get top of processor information
1708 mfsprg r10,2 ; Get CPU specific features
1709 ori r11,r11,lo16(EXT(gPEClockFrequencyInfo)) ; Get bottom of processor information
1710 mtcrf 0x40,r10 ; Get the installed features
1711
1712 li r3,lo16(thrmtidm|thrmvm) ; Set for lower-than thermal event at 0 degrees
1713 bflr pfThermalb ; No thermal monitoring on this cpu
1714 mtspr thrm1,r3 ; Do it
1715
1716 lwz r3,thrmthrottleTemp(r12) ; Get our throttle temprature
1717 rlwinm r3,r3,31-thrmthre,thrmthrs,thrmthre ; Position it
1718 ori r3,r3,lo16(thrmvm) ; Set for higher-than event
1719 mtspr thrm2,r3 ; Set it
1720
1721 lis r4,hi16(1000000) ; Top of million
1722;
1723; Note: some CPU manuals say this is processor clocks, some say bus rate. The latter
1724; makes more sense because otherwise we can not get over about 400MHz.
1725#if 0
1726 lwz r3,PECFIcpurate(r11) ; Get the processor speed
1727#else
1728 lwz r3,PECFIbusrate(r11) ; Get the bus speed
1729#endif
1730 ori r4,r4,lo16(1000000) ; Bottom of million
1731 lis r7,hi16(thrmsitvm>>1) ; Get top of highest possible value
1732 divwu r3,r3,r4 ; Get number of cycles per microseconds
1733 ori r7,r7,lo16(thrmsitvm>>1) ; Get the bottom of the highest possible value
1734 addi r3,r3,1 ; Insure we have enough
1735 mulli r3,r3,20 ; Get 20 microseconds worth of cycles
1736 cmplw r3,r7 ; Check against max
1737 ble+ smallenuf ; It is ok...
1738 mr r3,r7 ; Saturate
1739
1740smallenuf: rlwinm r3,r3,31-thrmsitve,thrmsitvs,thrmsitve ; Position
1741 ori r3,r3,lo16(thrmem) ; Enable with at least 20micro sec sample
1742 stw r3,thrm3val(r12) ; Save this in case we need it later
1743 mtspr thrm3,r3 ; Do it
1744 blr
1745
1746
1747/* Set thermal monitor bounds
1748 * void ml_thrm_set(unsigned int low, unsigned int high)
1749 *
1750 * Set TAU to interrupt below low and above high. A value of
1751 * zero disables interruptions in that direction.
1752 */
1753
1754; Force a line boundry here
1755 .align 5
1756 .globl EXT(ml_thrm_set)
1757
1758LEXT(ml_thrm_set)
1759
1760 mfmsr r0 ; Get the MSR
9bccf70c
A
1761 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1762 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1c79356b
A
1763 rlwinm r6,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear EE bit
1764 mtmsr r6
9bccf70c 1765 isync
1c79356b
A
1766
1767 mfsprg r12,0 ; Get the per_proc blok
1768
1769 rlwinm. r6,r3,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
1770 mfsprg r9,2 ; Get CPU specific features
1771 stw r3,thrmlowTemp(r12) ; Set the low temprature
1772 mtcrf 0x40,r9 ; See if we can thermal this machine
1773 rlwinm r9,r9,(((31-thrmtie)+(pfThermIntb+1))&31),thrmtie,thrmtie ; Set interrupt enable if this machine can handle it
1774 bf pfThermalb,tsetcant ; No can do...
1775 beq tsetlowo ; We are setting the low off...
1776 ori r6,r6,lo16(thrmtidm|thrmvm) ; Set the lower-than and valid bit
1777 or r6,r6,r9 ; Set interruption request if supported
1778
1779tsetlowo: mtspr thrm1,r6 ; Cram the register
1780
1781 rlwinm. r6,r4,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
1782 stw r4,thrmhighTemp(r12) ; Set the high temprature
1783 beq tsethigho ; We are setting the high off...
1784 ori r6,r6,lo16(thrmvm) ; Set valid bit
1785 or r6,r6,r9 ; Set interruption request if supported
1786
1787tsethigho: mtspr thrm2,r6 ; Cram the register
1788
1789tsetcant: mtmsr r0 ; Reenable interruptions
1790 blr ; Leave...
1791
1792/* Read processor temprature
1793 * unsigned int ml_read_temp(void)
1794 *
1795 */
1796
1797; Force a line boundry here
1798 .align 5
1799 .globl EXT(ml_read_temp)
1800
1801LEXT(ml_read_temp)
1802
1803 mfmsr r9 ; Save the MSR
1c79356b 1804 li r5,15 ; Starting point for ranging (start at 15 so we do not overflow)
9bccf70c
A
1805 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1806 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1807 rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1c79356b
A
1808 mfsprg r7,2 ; Get CPU specific features
1809 mtmsr r8 ; Do not allow interruptions
1810 mtcrf 0x40,r7 ; See if we can thermal this machine
1811 bf pfThermalb,thrmcant ; No can do...
1812
1813 mfspr r11,thrm1 ; Save thrm1
1814
1815thrmrange: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
1816 ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
1817
1818 mtspr thrm1,r4 ; Set the test value
1819
1820thrmreada: mfspr r3,thrm1 ; Get the thermal register back
1821 rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
1822 beq+ thrmreada ; Nope...
1823
1824 rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
1825 bne thrmsearch ; No, we went over...
1826
1827 addi r5,r5,16 ; Start by trying every 16 degrees
1828 cmplwi r5,127 ; Have we hit the max?
1829 blt- thrmrange ; Got some more to do...
1830
1831thrmsearch: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
1832 ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
1833
1834 mtspr thrm1,r4 ; Set the test value
1835
1836thrmread: mfspr r3,thrm1 ; Get the thermal register back
1837 rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
1838 beq+ thrmread ; Nope...
1839
1840 rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
1841 beq thrmdone ; No, we hit it...
1842 addic. r5,r5,-1 ; Go down a degree
1843 bge+ thrmsearch ; Try again (until we are below freezing)...
1844
1845thrmdone: addi r3,r5,1 ; Return the temprature (bump it up to make it correct)
1846 mtspr thrm1,r11 ; Restore the thermal register
1847 mtmsr r9 ; Re-enable interruptions
1848 blr ; Leave...
1849
1850thrmcant: eqv r3,r3,r3 ; Return bogus temprature because we can not read it
1851 mtmsr r9 ; Re-enable interruptions
1852 blr ; Leave...
1853
1854/* Throttle processor speed up or down
1855 * unsigned int ml_throttle(unsigned int step)
1856 *
1857 * Returns old speed and sets new. Both step and return are values from 0 to
1858 * 255 that define number of throttle steps, 0 being off and "ictcfim" is max * 2.
1859 *
1860 */
1861
1862; Force a line boundry here
1863 .align 5
1864 .globl EXT(ml_throttle)
1865
1866LEXT(ml_throttle)
1867
1868 mfmsr r9 ; Save the MSR
9bccf70c
A
1869 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1870 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1c79356b
A
1871 rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1872 cmplwi r3,lo16(ictcfim>>1) ; See if we are going too far
9bccf70c
A
1873 mtmsr r8 ; Do not allow interruptions
1874 isync
1c79356b
A
1875 ble+ throtok ; Throttle value is ok...
1876 li r3,lo16(ictcfim>>1) ; Set max
1877
1878throtok: rlwinm. r4,r3,1,ictcfib,ictcfie ; Set the throttle
1879 beq throtoff ; Skip if we are turning it off...
1880 ori r4,r4,lo16(thrmvm) ; Turn on the valid bit
1881
1882throtoff: mfspr r3,ictc ; Get the old throttle
1883 mtspr ictc,r4 ; Set the new
1884 rlwinm r3,r3,31,1,31 ; Shift throttle value over
1885 mtmsr r9 ; Restore interruptions
1886 blr ; Return...
1887
1888/*
1889** ml_get_timebase()
1890**
1891** Entry - R3 contains pointer to 64 bit structure.
1892**
1893** Exit - 64 bit structure filled in.
1894**
1895*/
1896; Force a line boundry here
1897 .align 5
1898 .globl EXT(ml_get_timebase)
1899
1900LEXT(ml_get_timebase)
1901
1902loop:
55e303ae
A
1903 mftbu r4
1904 mftb r5
1905 mftbu r6
1906 cmpw r6, r4
1907 bne- loop
1908
1909 stw r4, 0(r3)
1910 stw r5, 4(r3)
1911
1912 blr
1c79356b 1913
55e303ae
A
1914/*
1915 * unsigned int cpu_number(void)
1916 *
1917 * Returns the current cpu number.
1918 */
1919
1920 .align 5
1921 .globl EXT(cpu_number)
1922
1923LEXT(cpu_number)
1924 mfsprg r4,0 ; Get per-proc block
1925 lhz r3,PP_CPU_NUMBER(r4) ; Get CPU number
1926 blr ; Return...
9bccf70c 1927
d7e50217
A
1928
1929/*
55e303ae
A
1930 * void set_machine_current_act(thread_act_t)
1931 *
1932 * Set the current activation
d7e50217 1933 */
55e303ae
A
1934 .align 5
1935 .globl EXT(set_machine_current_act)
d7e50217 1936
55e303ae
A
1937LEXT(set_machine_current_act)
1938
1939 mtsprg 1,r3 ; Set spr1 with the active thread
1940 blr ; Return...
1941
1942/*
1943 * thread_t current_act(void)
1944 * thread_t current_thread(void)
1945 *
1946 *
1947 * Return the current thread for outside components.
1948 */
1949 .align 5
1950 .globl EXT(current_act)
1951 .globl EXT(current_thread)
1952
1953LEXT(current_act)
1954LEXT(current_thread)
1955
1956 mfsprg r3,1
1957 blr
1958
1959 .align 5
1960 .globl EXT(clock_get_uptime)
1961LEXT(clock_get_uptime)
19621: mftbu r9
1963 mftb r0
1964 mftbu r11
1965 cmpw r11,r9
1966 bne- 1b
1967 stw r0,4(r3)
1968 stw r9,0(r3)
1969 blr
1970
1971
1972 .align 5
1973 .globl EXT(mach_absolute_time)
1974LEXT(mach_absolute_time)
19751: mftbu r3
1976 mftb r4
1977 mftbu r0
1978 cmpw r0,r3
1979 bne- 1b
1980 blr
9bccf70c 1981
1c79356b
A
1982/*
1983** ml_sense_nmi()
1984**
1985*/
1986; Force a line boundry here
1987 .align 5
1988 .globl EXT(ml_sense_nmi)
1989
1990LEXT(ml_sense_nmi)
1991
1992 blr ; Leave...
1993
d52fe63f
A
1994/*
1995** ml_set_processor_speed()
1996**
1997*/
1998; Force a line boundry here
1999 .align 5
2000 .globl EXT(ml_set_processor_speed)
2001
2002LEXT(ml_set_processor_speed)
9bccf70c
A
2003 mfsprg r5, 0 ; Get the per_proc_info
2004
2005 cmpli cr0, r3, 0 ; Turn off BTIC before low speed
2006 beq sps1
2007 mfspr r4, hid0 ; Get the current hid0 value
2008 rlwinm r4, r4, 0, btic+1, btic-1 ; Clear the BTIC bit
2009 sync
2010 mtspr hid0, r4 ; Set the new hid0 value
2011 isync
2012 sync
2013
2014sps1:
2015 mfspr r4, hid1 ; Get the current PLL settings
2016 rlwimi r4, r3, 31-hid1ps, hid1ps, hid1ps ; Copy the PLL Select bit
2017 stw r4, pfHID1(r5) ; Save the new hid1 value
2018 mtspr hid1, r4 ; Select desired PLL
2019
2020 cmpli cr0, r3, 0 ; Restore BTIC after high speed
2021 bne sps2
2022 lwz r4, pfHID0(r5) ; Load the hid0 value
2023 sync
2024 mtspr hid0, r4 ; Set the hid0 value
2025 isync
2026 sync
2027
2028sps2:
d52fe63f 2029 blr
d12e1678
A
2030
2031/*
2032** ml_set_processor_voltage()
2033**
2034*/
2035; Force a line boundry here
2036 .align 5
2037 .globl EXT(ml_set_processor_voltage)
2038
2039LEXT(ml_set_processor_voltage)
2040 mfspr r4, hid2 ; Get HID2 value
2041 rlwimi r4, r3, 31-hid2vmin, hid2vmin, hid2vmin ; Insert the voltage mode bit
2042 mtspr hid2, r4 ; Set the voltage mode
2043 sync ; Make sure it is done
2044 blr