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