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