]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/machine_routines_asm.s
xnu-517.7.7.tar.gz
[apple/xnu.git] / osfmk / ppc / machine_routines_asm.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
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.
1c79356b 11 *
e5568f75
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
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.
1c79356b
A
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
55e303ae
A
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)
49LEXT(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
68LEXT(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
78LEXT(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)
83LEXT(ml_set_physical)
84
85 li r0,0 // do not turn off interrupts
86
87ml_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)
93ml_set_physical_32:
94 mtmsr r2 // turn off translation
95 isync
96 blr
97
98ml_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
118LEXT(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
124ml_restore_64:
125 mtmsrd r11 // restore a 64-bit MSR
126 isync
127 blr
128
129
1c79356b
A
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
144LEXT(ml_probe_read)
145
146 mfsprg r9,2 ; Get feature flags
55e303ae
A
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
152mpr32bit: lis r8,hi16(MASK(MSR_VEC)) ; Get the vector flag
1c79356b 153 mfmsr r0 ; Save the current MSR
55e303ae
A
154 ori r8,r8,lo16(MASK(MSR_FP)) ; Add the FP flag
155
1c79356b 156 neg r10,r3 ; Number of bytes to end of page
55e303ae 157 andc r0,r0,r8 ; Clear VEC and FP
1c79356b 158 rlwinm. r10,r10,0,20,31 ; Clear excess junk and test for page bndry
55e303ae 159 ori r8,r8,lo16(MASK(MSR_EE)|MASK(MSR_IR)|MASK(MSR_DR)) ; Drop EE, IR, and DR
1c79356b 160 mr r12,r3 ; Save the load address
55e303ae 161 andc r2,r0,r8 ; Clear VEC, FP, and EE
1c79356b
A
162 mtcrf 0x04,r9 ; Set the features
163 cmplwi cr1,r10,4 ; At least 4 bytes left in page?
1c79356b
A
164 beq- mprdoit ; We are right on the boundary...
165 li r3,0
166 bltlr- cr1 ; No, just return failure...
167
168mprdoit:
169
170 bt pfNoMSRirb,mprNoMSR ; No MSR...
171
172 mtmsr r2 ; Translation and all off
173 isync ; Toss prefetch
174 b mprNoMSRx
175
176mprNoMSR:
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
183mprNoMSRx:
d52fe63f
A
184
185 mfspr r6, hid0 ; Get a copy of hid0
1c79356b 186
9bccf70c
A
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
195mprNoMuM:
d52fe63f 196
1c79356b
A
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;
d52fe63f
A
202
203; Note: we will reload these from the shadow BATs later
204
1c79356b 205 li r10,0 ; Clear a register
1c79356b
A
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
d52fe63f
A
220 dcbf 0,r12 ; Make sure we kill the cache to avoid paradoxes
221 sync
222
1c79356b
A
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
d52fe63f
A
236 mtmsr r2 ; Turn translation back off
237 isync
238
d52fe63f
A
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
1c79356b
A
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)
266LEXT(ml_probe_read_mck)
267
55e303ae
A
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
283LEXT(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
293mpr64bit: 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
349mprFail: 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)
355LEXT(ml_probe_read_mck_64)
356
357
358/* Read physical address byte
1c79356b
A
359 *
360 * unsigned int ml_phys_read_byte(vm_offset_t paddr)
55e303ae 361 * unsigned int ml_phys_read_byte_64(addr64_t paddr)
1c79356b
A
362 *
363 * Read the byte at physical address paddr. Memory should not be cache inhibited.
364 */
365
366; Force a line boundry here
55e303ae 367
1c79356b 368 .align 5
55e303ae
A
369 .globl EXT(ml_phys_read_byte_64)
370
371LEXT(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
1c79356b
A
377 .globl EXT(ml_phys_read_byte)
378
379LEXT(ml_phys_read_byte)
55e303ae
A
380 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
381ml_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...
d7e50217 387
d7e50217 388
55e303ae
A
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 */
1c79356b 396
55e303ae 397; Force a line boundry here
d7e50217 398
55e303ae
A
399 .align 5
400 .globl EXT(ml_phys_read_half_64)
401
402LEXT(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
d7e50217 407
55e303ae
A
408 .globl EXT(ml_phys_read_half)
409
410LEXT(ml_phys_read_half)
411 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
412ml_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
1c79356b
A
421 *
422 * unsigned int ml_phys_read(vm_offset_t paddr)
55e303ae
A
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)
1c79356b
A
426 *
427 * Read the word at physical address paddr. Memory should not be cache inhibited.
428 */
429
430; Force a line boundry here
55e303ae 431
1c79356b 432 .align 5
55e303ae
A
433 .globl EXT(ml_phys_read_64)
434 .globl EXT(ml_phys_read_word_64)
435
436LEXT(ml_phys_read_64)
437LEXT(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
1c79356b 443 .globl EXT(ml_phys_read)
55e303ae 444 .globl EXT(ml_phys_read_word)
1c79356b
A
445
446LEXT(ml_phys_read)
55e303ae
A
447LEXT(ml_phys_read_word)
448 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
449ml_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...
d7e50217 455
d7e50217 456
55e303ae
A
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
470LEXT(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
478LEXT(ml_phys_read_double)
479 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
480ml_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.
1c79356b 483
55e303ae
A
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...
1c79356b 487
1c79356b
A
488
489/* Write physical address byte
490 *
491 * void ml_phys_write_byte(vm_offset_t paddr, unsigned int data)
55e303ae 492 * void ml_phys_write_byte_64(addr64_t paddr, unsigned int data)
1c79356b
A
493 *
494 * Write the byte at physical address paddr. Memory should not be cache inhibited.
495 */
496
1c79356b 497 .align 5
55e303ae
A
498 .globl EXT(ml_phys_write_byte_64)
499
500LEXT(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
1c79356b
A
507 .globl EXT(ml_phys_write_byte)
508
509LEXT(ml_phys_write_byte)
55e303ae
A
510 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
511ml_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...
1c79356b 517
d7e50217 518
55e303ae
A
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
530LEXT(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
539LEXT(ml_phys_write_half)
540 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
541ml_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.
1c79356b 544
55e303ae
A
545 sth r4,0(r3) ; Set the half word
546 b rdwrpost ; Clean up and leave...
1c79356b 547
1c79356b 548
55e303ae 549/* Write physical address word
1c79356b
A
550 *
551 * void ml_phys_write(vm_offset_t paddr, unsigned int data)
55e303ae
A
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)
1c79356b
A
555 *
556 * Write the word at physical address paddr. Memory should not be cache inhibited.
557 */
558
1c79356b 559 .align 5
55e303ae
A
560 .globl EXT(ml_phys_write_64)
561 .globl EXT(ml_phys_write_word_64)
562
563LEXT(ml_phys_write_64)
564LEXT(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
1c79356b 571 .globl EXT(ml_phys_write)
55e303ae 572 .globl EXT(ml_phys_write_word)
1c79356b
A
573
574LEXT(ml_phys_write)
55e303ae
A
575LEXT(ml_phys_write_word)
576 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
577ml_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...
d7e50217 583
d7e50217 584
55e303ae
A
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
596LEXT(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
606LEXT(ml_phys_write_double)
607 rlwinm r3,r3,0,0,31 ; truncate address to 32-bits
608ml_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
619rdwrpre: 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
1c79356b 649
1c79356b 650 sync
55e303ae
A
651 isync
652 blr ; Finally, all ready...
653
654 .align 5
655
656rdwrpre32: 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
663rdwrpost: 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
670rdwrpost64: bne++ cr7,rdwrpcok ; Skip enabling real mode caching if we did not change it...
1c79356b 671
55e303ae
A
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
680rdwrpcok: mtmsrd r10 ; Restore entry MSR (sans FP and VEC)
1c79356b 681 isync
55e303ae 682 blr ; Leave...
1c79356b
A
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
0b4e3aa0
A
693 .align 5
694 .globl EXT(ml_set_interrupts_enabled)
695
696LEXT(ml_set_interrupts_enabled)
1c79356b 697
55e303ae
A
698 andi. r4,r3,1 ; Are we turning interruptions on?
699 lis r0,hi16(MASK(MSR_VEC)) ; Get vector enable
1c79356b 700 mfmsr r5 ; Get the current MSR
55e303ae 701 ori r0,r0,lo16(MASK(MSR_EE)|MASK(MSR_FP)) ; Get float enable and EE enable
1c79356b 702 rlwinm r3,r5,17,31,31 ; Set return value
55e303ae
A
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
1c79356b
A
708 blr
709
55e303ae
A
710 .align 5
711
d7e50217 712CheckPreemption:
55e303ae
A
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
d7e50217 726 mtmsr r5 ; Restore the MSR now, before we can preempt
55e303ae
A
727 isync ; Need this because FP/Vec might go off
728
729 beqlr++ cr1 ; Return if no premption...
d7e50217 730 sc ; Preempt
0b4e3aa0
A
731 blr
732
de355530
A
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
743LEXT(machine_clock_assist)
744
745 mfsprg r7,0
746 lwz r4,PP_INTS_ENABLED(r7)
747 mr. r4,r4
55e303ae
A
748 bnelr+ cr0
749 b EXT(CreateFakeDEC)
de355530 750
1c79356b
A
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
1c79356b
A
761; Force a line boundry here
762 .align 5
763 .globl EXT(machine_idle_ppc)
764
765LEXT(machine_idle_ppc)
766
55e303ae
A
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
1c79356b 774 mtmsr r5 ; Hold up interruptions for now
9bccf70c 775 isync ; May have messed with fp/vec
1c79356b 776 mfsprg r12,0 ; Get the per_proc_info
de355530 777 mfsprg r11,2 ; Get CPU specific features
55e303ae 778 mfspr r6,hid0 ; Get the current power-saving mode
1c79356b
A
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 mtmsr r3 ; Turn interruptions back on
789 blr ; Leave...
790
791yesnap: mftbu r9 ; Get the upper timebase
792 mftb r7 ; Get the lower timebase
793 mftbu r8 ; Get the upper one again
794 cmplw r9,r8 ; Did the top tick?
795 bne- yesnap ; Yeah, need to get it again...
796 stw r8,napStamp(r12) ; Set high order time stamp
797 stw r7,napStamp+4(r12) ; Set low order nap stamp
d52fe63f 798
55e303ae 799 rlwinm. r7,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before nap?
9bccf70c
A
800 beq miL2PFok
801
802 mfspr r7,msscr0 ; Get currect MSSCR0 value
55e303ae 803 rlwinm r7,r7,0,0,l2pfes-1 ; Disable L2 Prefetch
9bccf70c
A
804 mtspr msscr0,r7 ; Updates MSSCR0 value
805 sync
806 isync
807
808miL2PFok:
55e303ae 809 rlwinm. r7,r11,0,pfSlowNapb,pfSlowNapb ; Should nap at slow speed?
9bccf70c
A
810 beq minoslownap
811
812 mfspr r7,hid1 ; Get current HID1 value
55e303ae 813 oris r7,r7,hi16(hid1psm) ; Select PLL1
9bccf70c
A
814 mtspr hid1,r7 ; Update HID1 value
815
816minoslownap:
d52fe63f 817
1c79356b
A
818;
819; We have to open up interruptions here because book 4 says that we should
820; turn on only the POW bit and that we should have interrupts enabled
821; The interrupt handler will detect that nap or doze is set if an interrupt
822; is taken and set everything up to return directly to machine_idle_ret.
823; So, make sure everything we need there is already set up...
824;
55e303ae 825
ab86ba33 826 lis r10,hi16(dozem|napm|sleepm) ; Mask of power management bits
55e303ae
A
827
828 bf-- pf64Bitb,mipNSF1 ; skip if 32-bit...
829
830 sldi r4,r4,32 ; Position the flags
831 sldi r10,r10,32 ; Position the masks
832
833
834mipNSF1: andc r6,r6,r10 ; Clean up the old power bits
835
1c79356b
A
836 ori r7,r5,lo16(MASK(MSR_EE)) ; Flip on EE
837 or r6,r6,r4 ; Set nap or doze
838 oris r5,r7,hi16(MASK(MSR_POW)) ; Turn on power management in next MSR
55e303ae
A
839
840 sync
1c79356b 841 mtspr hid0,r6 ; Set up the HID for nap/doze
55e303ae
A
842 mfspr r6,hid0 ; Yes, this is silly, keep it here
843 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
844 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
845 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
846 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
847 mfspr r6,hid0 ; Yes, this is a duplicate, keep it here
1c79356b 848 isync ; Make sure it is set
55e303ae 849
1c79356b
A
850 mtmsr r7 ; Enable for interrupts
851 rlwinm. r11,r11,0,pfAltivecb,pfAltivecb ; Do we have altivec?
852 beq- minovec ; No...
853 dssall ; Stop the streams before we nap/doze
854
4a249263
A
855minovec:
856 bf-- pf64Bitb,mipowloop ; skip if 32-bit...
857
858 li r3,0x10 ; Fancy nap threashold is 0x10 ticks
859 mftb r8 ; Get the low half of the time base
860 mfdec r4 ; Get the decrementer ticks
861 cmplw r4,r3 ; Less than threashold?
862 blt mipowloop
863
864 mtdec r3 ; Load decrimenter with threshold
865 isync ; and make sure,
866 mfdec r3 ; really sure, it gets there
867
868 rlwinm r6,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear out the EE bit
869 sync ; Make sure queues are clear
870 mtmsr r6 ; Set MSR with EE off but POW on
1c79356b 871 isync ; Make sure this takes before we proceed
4a249263
A
872
873 mftb r9 ; Get the low half of the time base
874 sub r9,r9,r8 ; Get the number of ticks spent waiting
875 sub r4,r4,r9 ; Adjust the decrementer value
876
877 mtdec r4 ; Load decrimenter with the rest of the timeout
878 isync ; and make sure,
879 mfdec r4 ; really sure, it gets there
880
881mipowloop:
882 sync ; Make sure queues are clear
883 mtmsr r5 ; Nap or doze, MSR with POW and EE set
884 isync ; Make sure this takes before we proceed
885 b mipowloop ; loop if POW does not take
886
1c79356b
A
887;
888; Note that the interrupt handler will turn off the nap/doze bits in the hid.
889; Also remember that the interrupt handler will force return to here whenever
890; the nap/doze bits are set.
891;
892 .globl EXT(machine_idle_ret)
893LEXT(machine_idle_ret)
894 mtmsr r7 ; Make sure the MSR is what we want
895 isync ; In case we turn on translation
896
897 blr ; Return...
898
899/* Put machine to sleep.
900 * This call never returns. We always exit sleep via a soft reset.
901 * All external interruptions must be drained at this point and disabled.
902 *
903 * void ml_ppc_sleep(void)
904 *
905 * We will use the PPC SLEEP for this.
906 *
907 * There is one bit of hackery in here: we need to enable for
908 * interruptions when we go to sleep and there may be a pending
909 * decrimenter rupt. So we make the decrimenter 0x7FFFFFFF and enable for
910 * interruptions. The decrimenter rupt vector recognizes this and returns
911 * directly back here.
912 *
913 */
914
915; Force a line boundry here
916 .align 5
917 .globl EXT(ml_ppc_sleep)
918
919LEXT(ml_ppc_sleep)
920
921#if 0
922 mfmsr r5 ; Hack to spin instead of sleep
923 rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
924 rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
925 mtmsr r5 ; No talking
926 isync
927
1c79356b
A
928deadsleep: addi r3,r3,1 ; Make analyzer happy
929 addi r3,r3,1
930 addi r3,r3,1
931 b deadsleep ; Die the death of 1000 joys...
932#endif
933
55e303ae 934 mfsprg r12,0 ; Get the per_proc_info
1c79356b
A
935 mfspr r4,hid0 ; Get the current power-saving mode
936 eqv r10,r10,r10 ; Get all foxes
937 mfsprg r11,2 ; Get CPU specific features
9bccf70c 938
55e303ae 939 rlwinm. r5,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before sleep?
9bccf70c
A
940 beq mpsL2PFok
941
942 mfspr r5,msscr0 ; Get currect MSSCR0 value
55e303ae 943 rlwinm r5,r5,0,0,l2pfes-1 ; Disable L2 Prefetch
9bccf70c
A
944 mtspr msscr0,r5 ; Updates MSSCR0 value
945 sync
946 isync
947
948mpsL2PFok:
55e303ae
A
949 rlwinm. r5,r11,0,pf64Bitb,pf64Bitb ; PM bits are shifted on 64bit systems.
950 bne mpsPF64bit
951
952 rlwinm r4,r4,0,sleep+1,doze-1 ; Clear all possible power-saving modes (not DPM though)
953 oris r4,r4,hi16(sleepm) ; Set sleep
4a249263 954 b mpsClearDEC
55e303ae
A
955
956mpsPF64bit:
4a249263 957 lis r5, hi16(dozem|napm|sleepm) ; Clear all possible power-saving modes (not DPM though)
55e303ae
A
958 sldi r5, r5, 32
959 andc r4, r4, r5
4a249263 960 lis r5, hi16(napm) ; Set sleep
55e303ae 961 sldi r5, r5, 32
4a249263 962 or r4, r4, r5
55e303ae
A
963
964mpsClearDEC:
1c79356b
A
965 mfmsr r5 ; Get the current MSR
966 rlwinm r10,r10,0,1,31 ; Make 0x7FFFFFFF
1c79356b
A
967 mtdec r10 ; Load decrimenter with 0x7FFFFFFF
968 isync ; and make sure,
969 mfdec r9 ; really sure, it gets there
970
971 mtcrf 0x07,r11 ; Get the cache flags, etc
972
1c79356b
A
973 rlwinm r5,r5,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
974;
975; Note that we need translation off before we set the HID to sleep. Otherwise
976; we will ignore any PTE misses that occur and cause an infinite loop.
977;
978 bt pfNoMSRirb,mpsNoMSR ; No MSR...
979
980 mtmsr r5 ; Translation off
981 isync ; Toss prefetch
982 b mpsNoMSRx
983
984mpsNoMSR:
985 li r0,loadMSR ; Get the MSR setter SC
986 mr r3,r5 ; Get new MSR
987 sc ; Set it
988mpsNoMSRx:
989
990 ori r3,r5,lo16(MASK(MSR_EE)) ; Flip on EE
991 sync
992 mtspr hid0,r4 ; Set up the HID to sleep
55e303ae
A
993 mfspr r4,hid0 ; Yes, this is silly, keep it here
994 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
995 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
996 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
997 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
998 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1c79356b
A
999
1000 mtmsr r3 ; Enable for interrupts to drain decrimenter
1001
1002 add r6,r4,r5 ; Just waste time
1003 add r6,r6,r4 ; A bit more
1004 add r6,r6,r5 ; A bit more
1005
1006 mtmsr r5 ; Interruptions back off
1007 isync ; Toss prefetch
1008
1c79356b
A
1009;
1010; We are here with translation off, interrupts off, all possible
1011; interruptions drained off, and a decrimenter that will not pop.
1012;
1013
1014 bl EXT(cacheInit) ; Clear out the caches. This will leave them on
1015 bl EXT(cacheDisable) ; Turn off all caches
1016
1017 mfmsr r5 ; Get the current MSR
1018 oris r5,r5,hi16(MASK(MSR_POW)) ; Turn on power management in next MSR
1019 ; Leave EE off because power goes off shortly
55e303ae
A
1020 mfsprg r12,0 ; Get the per_proc_info
1021 li r10,PP_CPU_FLAGS
1022 lhz r11,PP_CPU_FLAGS(r12) ; Get the flags
1023 ori r11,r11,SleepState ; Marked SleepState
1024 sth r11,PP_CPU_FLAGS(r12) ; Set the flags
1025 dcbf r10,r12
4a249263
A
1026
1027 mfsprg r11,2 ; Get CPU specific features
1028 rlwinm. r0,r11,0,pf64Bitb,pf64Bitb ; Test for 64 bit processor
1029 eqv r4,r4,r4 ; Get all foxes
1030 rlwinm r4,r4,0,1,31 ; Make 0x7FFFFFFF
1031 beq slSleepNow ; skip if 32-bit...
1032 li r3, 0x4000 ; Cause decrimenter to roll over soon
1033 mtdec r3 ; Load decrimenter with 0x00004000
1034 isync ; and make sure,
1035 mfdec r3 ; really sure, it gets there
1036
55e303ae
A
1037slSleepNow:
1038 sync ; Sync it all up
1c79356b
A
1039 mtmsr r5 ; Do sleep with interruptions enabled
1040 isync ; Take a pill
4a249263
A
1041 mtdec r4 ; Load decrimenter with 0x7FFFFFFF
1042 isync ; and make sure,
1043 mfdec r3 ; really sure, it gets there
1c79356b
A
1044 b slSleepNow ; Go back to sleep if we wake up...
1045
1046
1047
1048/* Initialize all caches including the TLBs
1049 *
1050 * void cacheInit(void)
1051 *
1052 * This is used to force the caches to an initial clean state. First, we
1053 * check if the cache is on, if so, we need to flush the contents to memory.
1054 * Then we invalidate the L1. Next, we configure and invalidate the L2 etc.
1055 * Finally we turn on all of the caches
1056 *
1057 * Note that if translation is not disabled when this is called, the TLB will not
1058 * be completely clear after return.
1059 *
1060 */
1061
1062; Force a line boundry here
1063 .align 5
1064 .globl EXT(cacheInit)
1065
1066LEXT(cacheInit)
1067
1068 mfsprg r12,0 ; Get the per_proc_info
1069 mfspr r9,hid0 ; Get the current power-saving mode
1070
1071 mfsprg r11,2 ; Get CPU specific features
1072 mfmsr r7 ; Get the current MSR
9bccf70c
A
1073 rlwinm r7,r7,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1074 rlwinm r7,r7,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
0b4e3aa0 1075 rlwimi r11,r11,pfLClckb+1,31,31 ; Move pfLClck to another position (to keep from using non-volatile CRs)
1c79356b
A
1076 rlwinm r5,r7,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation
1077 rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1078 mtcrf 0x87,r11 ; Get the feature flags
55e303ae
A
1079 lis r10,hi16(dozem|napm|sleepm|dpmm) ; Mask of power management bits
1080 bf-- pf64Bitb,cIniNSF1 ; Skip if 32-bit...
1081
1082 sldi r10,r10,32 ; Position the masks
1083
1084cIniNSF1: andc r4,r9,r10 ; Clean up the old power bits
1c79356b 1085 mtspr hid0,r4 ; Set up the HID
55e303ae
A
1086 mfspr r4,hid0 ; Yes, this is silly, keep it here
1087 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1088 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1089 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1090 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1091 mfspr r4,hid0 ; Yes, this is a duplicate, keep it here
1c79356b
A
1092
1093 bt pfNoMSRirb,ciNoMSR ; No MSR...
1094
1095 mtmsr r5 ; Translation and all off
1096 isync ; Toss prefetch
1097 b ciNoMSRx
1098
1099ciNoMSR:
1100 li r0,loadMSR ; Get the MSR setter SC
1101 mr r3,r5 ; Get new MSR
1102 sc ; Set it
1103ciNoMSRx:
1104
1105 bf pfAltivecb,cinoDSS ; No Altivec here...
1106
1107 dssall ; Stop streams
1108 sync
1109
55e303ae 1110cinoDSS: li r5,tlbieLock ; Get the TLBIE lock
1c79356b 1111 li r0,128 ; Get number of TLB entries
1c79356b
A
1112
1113 li r6,0 ; Start at 0
55e303ae
A
1114 bf-- pf64Bitb,citlbhang ; Skip if 32-bit...
1115 li r0,1024 ; Get the number of TLB entries
1c79356b
A
1116
1117citlbhang: lwarx r2,0,r5 ; Get the TLBIE lock
1118 mr. r2,r2 ; Is it locked?
1119 bne- citlbhang ; It is locked, go wait...
1120 stwcx. r0,0,r5 ; Try to get it
1121 bne- citlbhang ; We was beat...
1122
1123 mtctr r0 ; Set the CTR
1124
1125cipurgeTLB: tlbie r6 ; Purge this entry
1126 addi r6,r6,4096 ; Next page
1127 bdnz cipurgeTLB ; Do them all...
1128
1129 mtcrf 0x80,r11 ; Set SMP capability
1130 sync ; Make sure all TLB purges are done
1131 eieio ; Order, order in the court
1132
1133 bf pfSMPcapb,cinoSMP ; SMP incapable...
1134
1135 tlbsync ; Sync all TLBs
1136 sync
150bd074 1137 isync
1c79356b 1138
55e303ae
A
1139 bf-- pf64Bitb,cinoSMP ; Skip if 32-bit...
1140 ptesync ; Wait for quiet again
1141 sync
1142
1143cinoSMP: stw r2,tlbieLock(0) ; Unlock TLBIE lock
1144
1145 bt++ pf64Bitb,cin64 ; Skip if 64-bit...
1c79356b 1146
1c79356b
A
1147 rlwinm. r0,r9,0,ice,dce ; Were either of the level 1s on?
1148 beq- cinoL1 ; No, no need to flush...
1149
55e303ae
A
1150 rlwinm. r0,r11,0,pfL1fab,pfL1fab ; do we have L1 flush assist?
1151 beq ciswdl1 ; If no hw flush assist, go do by software...
1c79356b
A
1152
1153 mfspr r8,msscr0 ; Get the memory system control register
1154 oris r8,r8,hi16(dl1hwfm) ; Turn on the hardware flush request
1155
1156 mtspr msscr0,r8 ; Start the flush operation
1157
1158ciwdl1f: mfspr r8,msscr0 ; Get the control register again
1159
1160 rlwinm. r8,r8,0,dl1hwf,dl1hwf ; Has the flush request been reset yet?
1161 bne ciwdl1f ; No, flush is still in progress...
1162 b ciinvdl1 ; Go invalidate l1...
1163
1164;
1165; We need to either make this very complicated or to use ROM for
1166; the flush. The problem is that if during the following sequence a
1167; snoop occurs that invalidates one of the lines in the cache, the
1168; PLRU sequence will be altered making it possible to miss lines
1169; during the flush. So, we either need to dedicate an area of RAM
1170; to each processor, lock use of a RAM area, or use ROM. ROM is
1171; by far the easiest. Note that this is not an issue for machines
1172; that have harware flush assists.
1173;
1174
1175ciswdl1: lwz r0,pfl1dSize(r12) ; Get the level 1 cache size
0b4e3aa0
A
1176
1177 bf 31,cisnlck ; Skip if pfLClck not set...
1178
1179 mfspr r4,msscr0 ; ?
1180 rlwinm r6,r4,0,0,l2pfes-1 ; ?
1181 mtspr msscr0,r6 ; Set it
1182 sync
1183 isync
1184
1185 mfspr r8,ldstcr ; Save the LDSTCR
1186 li r2,1 ; Get a mask of 0x01
1187 lis r3,0xFFF0 ; Point to ROM
1188 rlwinm r11,r0,29,3,31 ; Get the amount of memory to handle all indexes
1189
1190 li r6,0 ; Start here
1191
1192cisiniflsh: dcbf r6,r3 ; Flush each line of the range we use
1193 addi r6,r6,32 ; Bump to the next
1194 cmplw r6,r0 ; Have we reached the end?
1195 blt+ cisiniflsh ; Nope, continue initial flush...
1196
1197 sync ; Make sure it is done
1198
1199 addi r11,r11,-1 ; Get mask for index wrap
1200 li r6,0 ; Get starting offset
1201
1202cislckit: not r5,r2 ; Lock all but 1 way
1203 rlwimi r5,r8,0,0,23 ; Build LDSTCR
1204 mtspr ldstcr,r5 ; Lock a way
1205 sync ; Clear out memory accesses
1206 isync ; Wait for all
1207
1208
1209cistouch: lwzx r10,r3,r6 ; Pick up some trash
1210 addi r6,r6,32 ; Go to the next index
1211 and. r0,r6,r11 ; See if we are about to do next index
1212 bne+ cistouch ; Nope, do more...
1213
1214 sync ; Make sure it is all done
1215 isync
1216
1217 sub r6,r6,r11 ; Back up to start + 1
1218 addi r6,r6,-1 ; Get it right
1219
1220cisflush: dcbf r3,r6 ; Flush everything out
1221 addi r6,r6,32 ; Go to the next index
1222 and. r0,r6,r11 ; See if we are about to do next index
1223 bne+ cisflush ; Nope, do more...
1224
1225 sync ; Make sure it is all done
1226 isync
1227
1228
1229 rlwinm. r2,r2,1,24,31 ; Shift to next way
1230 bne+ cislckit ; Do this for all ways...
1231
1232 mtspr ldstcr,r8 ; Slam back to original
1233 sync
1234 isync
1235
1236 mtspr msscr0,r4 ; ?
1237 sync
1238 isync
1239
1240 b cinoL1 ; Go on to level 2...
1241
1242
1243cisnlck: rlwinm r2,r0,0,1,30 ; Double cache size
1c79356b
A
1244 add r0,r0,r2 ; Get 3 times cache size
1245 rlwinm r0,r0,26,6,31 ; Get 3/2 number of cache lines
1246 lis r3,0xFFF0 ; Dead recon ROM address for now
1247 mtctr r0 ; Number of lines to flush
1248
1249ciswfldl1a: lwz r2,0(r3) ; Flush anything else
1250 addi r3,r3,32 ; Next line
1251 bdnz ciswfldl1a ; Flush the lot...
1252
1253ciinvdl1: sync ; Make sure all flushes have been committed
1254
1255 mfspr r8,hid0 ; Get the HID0 bits
1256 rlwinm r8,r8,0,dce+1,ice-1 ; Clear cache enables
1257 mtspr hid0,r8 ; and turn off L1 cache
1258 sync ; Make sure all is done
0b4e3aa0
A
1259 isync
1260
1c79356b
A
1261 ori r8,r8,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate
1262 sync
1263 isync
1264
1265 mtspr hid0,r8 ; Start the invalidate and turn on cache
1266 rlwinm r8,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits
1267 mtspr hid0,r8 ; Turn off the invalidate (needed for some older machines)
1268 sync
0b4e3aa0 1269
1c79356b
A
1270
1271cinoL1:
1272;
1273; Flush and disable the level 2
1274;
55e303ae
A
1275 mfsprg r10,2 ; need to check 2 features we did not put in CR
1276 rlwinm. r0,r10,0,pfL2b,pfL2b ; do we have L2?
1277 beq cinol2 ; No level 2 cache to flush
1c79356b
A
1278
1279 mfspr r8,l2cr ; Get the L2CR
1280 lwz r3,pfl2cr(r12) ; Get the L2CR value
d52fe63f
A
1281 rlwinm. r0,r8,0,l2e,l2e ; Was the L2 enabled?
1282 bne ciflushl2 ; Yes, force flush
1283 cmplwi r8, 0 ; Was the L2 all the way off?
1284 beq ciinvdl2 ; Yes, force invalidate
1c79356b
A
1285 lis r0,hi16(l2sizm|l2clkm|l2ramm|l2ohm) ; Get confiuration bits
1286 xor r2,r8,r3 ; Get changing bits?
1287 ori r0,r0,lo16(l2slm|l2dfm|l2bypm) ; More config bits
1288 and. r0,r0,r2 ; Did any change?
1289 bne- ciinvdl2 ; Yes, just invalidate and get PLL synced...
1290
d52fe63f 1291ciflushl2:
55e303ae
A
1292 rlwinm. r0,r10,0,pfL2fab,pfL2fab ; hardware-assisted L2 flush?
1293 beq ciswfl2 ; Flush not in hardware...
1c79356b 1294
d52fe63f 1295 mr r10,r8 ; Take a copy now
1c79356b 1296
0b4e3aa0 1297 bf 31,cinol2lck ; Skip if pfLClck not set...
1c79356b
A
1298
1299 oris r10,r10,hi16(l2ionlym|l2donlym) ; Set both instruction- and data-only
1300 sync
1301 mtspr l2cr,r10 ; Lock out the cache
1302 sync
1303 isync
1304
1305cinol2lck: ori r10,r10,lo16(l2hwfm) ; Request flush
1306 sync ; Make sure everything is done
1307
1308 mtspr l2cr,r10 ; Request flush
1309
1310cihwfl2: mfspr r10,l2cr ; Get back the L2CR
1311 rlwinm. r10,r10,0,l2hwf,l2hwf ; Is the flush over?
1312 bne+ cihwfl2 ; Nope, keep going...
1313 b ciinvdl2 ; Flush done, go invalidate L2...
1314
1315ciswfl2:
1316 lwz r0,pfl2Size(r12) ; Get the L2 size
d52fe63f 1317 oris r2,r8,hi16(l2dom) ; Set L2 to data only mode
0b4e3aa0
A
1318
1319 b ciswfl2doa ; Branch to next line...
1320
1321 .align 5
1322ciswfl2doc:
1323 mtspr l2cr,r2 ; Disable L2
1324 sync
1325 isync
1326 b ciswfl2dod ; It is off, go invalidate it...
1327
1328ciswfl2doa:
1329 b ciswfl2dob ; Branch to next...
1330
1331ciswfl2dob:
1332 sync ; Finish memory stuff
1333 isync ; Stop speculation
1334 b ciswfl2doc ; Jump back up and turn on data only...
1335ciswfl2dod:
1c79356b
A
1336 rlwinm r0,r0,27,5,31 ; Get the number of lines
1337 lis r10,0xFFF0 ; Dead recon ROM for now
1338 mtctr r0 ; Set the number of lines
1339
1340ciswfldl2a: lwz r0,0(r10) ; Load something to flush something
1341 addi r10,r10,32 ; Next line
1342 bdnz ciswfldl2a ; Do the lot...
1343
55e303ae 1344ciinvdl2: rlwinm r8,r3,0,l2e+1,31 ; Clear the enable bit
1c79356b
A
1345 b cinla ; Branch to next line...
1346
1347 .align 5
d52fe63f 1348cinlc: mtspr l2cr,r8 ; Disable L2
1c79356b
A
1349 sync
1350 isync
1351 b ciinvl2 ; It is off, go invalidate it...
1352
1353cinla: b cinlb ; Branch to next...
1354
1355cinlb: sync ; Finish memory stuff
1356 isync ; Stop speculation
1357 b cinlc ; Jump back up and turn off cache...
1358
1359ciinvl2: sync
1360 isync
d52fe63f
A
1361
1362 cmplwi r3, 0 ; Should the L2 be all the way off?
1363 beq cinol2 ; Yes, done with L2
1364
1365 oris r2,r8,hi16(l2im) ; Get the invalidate flag set
1c79356b
A
1366
1367 mtspr l2cr,r2 ; Start the invalidate
1368 sync
1369 isync
1370ciinvdl2a: mfspr r2,l2cr ; Get the L2CR
55e303ae
A
1371 mfsprg r0,2 ; need to check a feature in "non-volatile" set
1372 rlwinm. r0,r0,0,pfL2ib,pfL2ib ; flush in HW?
1373 beq ciinvdl2b ; Flush not in hardware...
1c79356b
A
1374 rlwinm. r2,r2,0,l2i,l2i ; Is the invalidate still going?
1375 bne+ ciinvdl2a ; Assume so, this will take a looong time...
1376 sync
1377 b cinol2 ; No level 2 cache to flush
1378ciinvdl2b:
1379 rlwinm. r2,r2,0,l2ip,l2ip ; Is the invalidate still going?
1380 bne+ ciinvdl2a ; Assume so, this will take a looong time...
1381 sync
d52fe63f 1382 mtspr l2cr,r8 ; Turn off the invalidate request
1c79356b
A
1383
1384cinol2:
1385
1386;
1387; Flush and enable the level 3
1388;
1389 bf pfL3b,cinol3 ; No level 3 cache to flush
1390
1391 mfspr r8,l3cr ; Get the L3CR
1392 lwz r3,pfl3cr(r12) ; Get the L3CR value
d52fe63f
A
1393 rlwinm. r0,r8,0,l3e,l3e ; Was the L3 enabled?
1394 bne ciflushl3 ; Yes, force flush
1395 cmplwi r8, 0 ; Was the L3 all the way off?
1396 beq ciinvdl3 ; Yes, force invalidate
1c79356b
A
1397 lis r0,hi16(l3pem|l3sizm|l3dxm|l3clkm|l3spom|l3ckspm) ; Get configuration bits
1398 xor r2,r8,r3 ; Get changing bits?
1399 ori r0,r0,lo16(l3pspm|l3repm|l3rtm|l3cyam|l3dmemm|l3dmsizm) ; More config bits
1400 and. r0,r0,r2 ; Did any change?
1401 bne- ciinvdl3 ; Yes, just invalidate and get PLL synced...
1402
d52fe63f 1403ciflushl3:
1c79356b 1404 sync ; 7450 book says do this even though not needed
d52fe63f 1405 mr r10,r8 ; Take a copy now
1c79356b
A
1406
1407 bf 31,cinol3lck ; Skip if pfL23lck not set...
1408
1409 oris r10,r10,hi16(l3iom) ; Set instruction-only
1410 ori r10,r10,lo16(l3donlym) ; Set data-only
1411 sync
1412 mtspr l3cr,r10 ; Lock out the cache
1413 sync
1414 isync
1415
1416cinol3lck: ori r10,r10,lo16(l3hwfm) ; Request flush
1417 sync ; Make sure everything is done
1418
1419 mtspr l3cr,r10 ; Request flush
1420
1421cihwfl3: mfspr r10,l3cr ; Get back the L3CR
1422 rlwinm. r10,r10,0,l3hwf,l3hwf ; Is the flush over?
1423 bne+ cihwfl3 ; Nope, keep going...
1424
55e303ae 1425ciinvdl3: rlwinm r8,r3,0,l3e+1,31 ; Clear the enable bit
1c79356b 1426 sync ; Make sure of life, liberty, and justice
d52fe63f 1427 mtspr l3cr,r8 ; Disable L3
1c79356b
A
1428 sync
1429
d52fe63f
A
1430 cmplwi r3, 0 ; Should the L3 be all the way off?
1431 beq cinol3 ; Yes, done with L3
1c79356b 1432
d52fe63f 1433 ori r8,r8,lo16(l3im) ; Get the invalidate flag set
1c79356b 1434
d52fe63f
A
1435 mtspr l3cr,r8 ; Start the invalidate
1436
1437ciinvdl3b: mfspr r8,l3cr ; Get the L3CR
1438 rlwinm. r8,r8,0,l3i,l3i ; Is the invalidate still going?
1c79356b
A
1439 bne+ ciinvdl3b ; Assume so...
1440 sync
1441
d52fe63f
A
1442 lwz r10, pfBootConfig(r12) ; ?
1443 rlwinm. r10, r10, 24, 28, 31 ; ?
1444 beq ciinvdl3nopdet ; ?
1445
1446 mfspr r8,l3pdet ; ?
1447 srw r2, r8, r10 ; ?
1448 rlwimi r2, r8, 0, 24, 31 ; ?
1449 subfic r10, r10, 32 ; ?
1450 li r8, -1 ; ?
1451 ori r2, r2, 0x0080 ; ?
1452 slw r8, r8, r10 ; ?
1453 or r8, r2, r8 ; ?
1454 mtspr l3pdet, r8 ; ?
1c79356b
A
1455 isync
1456
7b1edb79 1457ciinvdl3nopdet:
d52fe63f
A
1458 mfspr r8,l3cr ; Get the L3CR
1459 rlwinm r8,r8,0,l3clken+1,l3clken-1 ; Clear the clock enable bit
1460 mtspr l3cr,r8 ; Disable the clock
1c79356b
A
1461
1462 li r2,128 ; ?
1463ciinvdl3c: addi r2,r2,-1 ; ?
1464 cmplwi r2,0 ; ?
1465 bne+ ciinvdl3c
1466
1467 mfspr r10,msssr0 ; ?
1468 rlwinm r10,r10,0,vgL3TAG+1,vgL3TAG-1 ; ?
1469 mtspr msssr0,r10 ; ?
1470 sync
1471
d52fe63f 1472 mtspr l3cr,r3 ; Enable it as desired
1c79356b
A
1473 sync
1474cinol3:
55e303ae
A
1475 mfsprg r0,2 ; need to check a feature in "non-volatile" set
1476 rlwinm. r0,r0,0,pfL2b,pfL2b ; is there an L2 cache?
1477 beq cinol2a ; No level 2 cache to enable
1c79356b
A
1478
1479 lwz r3,pfl2cr(r12) ; Get the L2CR value
d52fe63f 1480 cmplwi r3, 0 ; Should the L2 be all the way off?
55e303ae 1481 beq cinol2a : Yes, done with L2
d52fe63f 1482 mtspr l2cr,r3 ; Enable it as desired
1c79356b
A
1483 sync
1484
1485;
1486; Invalidate and turn on L1s
1487;
1488
0b4e3aa0
A
1489cinol2a:
1490 bt 31,cinoexit ; Skip if pfLClck set...
1491
1492 rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables
1c79356b
A
1493 mtspr hid0,r8 ; Turn off dem caches
1494 sync
1495
1496 ori r8,r9,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate
1497 rlwinm r9,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits
1498 sync
1499 isync
1500
1501 mtspr hid0,r8 ; Start the invalidate and turn on L1 cache
0b4e3aa0
A
1502
1503cinoexit: mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) and restore entry conditions
1c79356b
A
1504 sync
1505 mtmsr r7 ; Restore MSR to entry
1506 isync
1507 blr ; Return...
1508
1509
55e303ae
A
1510;
1511; Handle 64-bit architecture
1512; This processor can not run without caches, so we just push everything out
1513; and flush. It will be relativily clean afterwards
1514;
1515
1516 .align 5
1517
1518cin64:
55e303ae
A
1519 mfspr r10,hid1 ; Save hid1
1520 mfspr r4,hid4 ; Save hid4
1521 mr r12,r10 ; Really save hid1
1522 mr r11,r4 ; Get a working copy of hid4
1523
1524 li r0,0 ; Get a 0
1525 eqv r2,r2,r2 ; Get all foxes
1526
1527 rldimi r10,r0,55,7 ; Clear I$ prefetch bits (7:8)
1528
1529 isync
1530 mtspr hid1,r10 ; Stick it
1531 mtspr hid1,r10 ; Stick it again
1532 isync
1533
1534 rldimi r11,r2,38,25 ; Disable D$ prefetch (25:25)
1535
1536 sync
1537 mtspr hid4,r11 ; Stick it
1538 isync
1539
1540 li r3,8 ; Set bit 28+32
1541 sldi r3,r3,32 ; Make it bit 28
1542 or r3,r3,r11 ; Turn on the flash invalidate L1D$
1543
1544 oris r5,r11,0x0600 ; Set disable L1D$ bits
1545 sync
1546 mtspr hid4,r3 ; Invalidate
1547 isync
1548
1549 mtspr hid4,r5 ; Un-invalidate and disable L1D$
1550 isync
1551
1552 lis r8,GUSModeReg ; Get the GUS mode ring address
1553 mfsprg r0,2 ; Get the feature flags
1554 ori r8,r8,0x8000 ; Set to read data
1555 rlwinm. r0,r0,pfSCOMFixUpb+1,31,31 ; Set shift if we need a fix me up
1556
1557 sync
1558
1559 mtspr scomc,r8 ; Request the GUS mode
1560 mfspr r11,scomd ; Get the GUS mode
1561 mfspr r8,scomc ; Get back the status (we just ignore it)
1562 sync
1563 isync
1564
1565 sld r11,r11,r0 ; Fix up if needed
1566
1567 ori r6,r11,lo16(GUSMdmapen) ; Set the bit that means direct L2 cache address
1568 lis r8,GUSModeReg ; Get GUS mode register address
1569
1570 sync
1571
1572 mtspr scomd,r6 ; Set that we want direct L2 mode
1573 mtspr scomc,r8 ; Tell GUS we want direct L2 mode
1574 mfspr r3,scomc ; Get back the status
1575 sync
1576 isync
1577
1578 li r3,0 ; Clear start point
1579
1580cflushlp: lis r6,0x0040 ; Pick 4MB line as our target
1581 or r6,r6,r3 ; Put in the line offset
1582 lwz r5,0(r6) ; Load a line
1583 addis r6,r6,8 ; Roll bit 42:44
1584 lwz r5,0(r6) ; Load a line
1585 addis r6,r6,8 ; Roll bit 42:44
1586 lwz r5,0(r6) ; Load a line
1587 addis r6,r6,8 ; Roll bit 42:44
1588 lwz r5,0(r6) ; Load a line
1589 addis r6,r6,8 ; Roll bit 42:44
1590 lwz r5,0(r6) ; Load a line
1591 addis r6,r6,8 ; Roll bit 42:44
1592 lwz r5,0(r6) ; Load a line
1593 addis r6,r6,8 ; Roll bit 42:44
1594 lwz r5,0(r6) ; Load a line
1595 addis r6,r6,8 ; Roll bit 42:44
1596 lwz r5,0(r6) ; Load a line
1597
1598 addi r3,r3,128 ; Next line
1599 andis. r5,r3,8 ; Have we done enough?
1600 beq++ cflushlp ; Not yet...
1601
1602 sync
1603
1604 lis r6,0x0040 ; Pick 4MB line as our target
1605
1606cflushx: dcbf 0,r6 ; Flush line and invalidate
1607 addi r6,r6,128 ; Next line
1608 andis. r5,r6,0x0080 ; Have we done enough?
1609 beq++ cflushx ; Keep on flushing...
1610
1611 mr r3,r10 ; Copy current hid1
1612 rldimi r3,r2,54,9 ; Set force icbi match mode
1613
1614 li r6,0 ; Set start if ICBI range
1615 isync
1616 mtspr hid1,r3 ; Stick it
1617 mtspr hid1,r3 ; Stick it again
1618 isync
1619
1620cflicbi: icbi 0,r6 ; Kill I$
1621 addi r6,r6,128 ; Next line
1622 andis. r5,r6,1 ; Have we done them all?
1623 beq++ cflicbi ; Not yet...
1624
1625 lis r8,GUSModeReg ; Get GUS mode register address
1626
1627 sync
1628
1629 mtspr scomd,r11 ; Set that we do not want direct mode
1630 mtspr scomc,r8 ; Tell GUS we do not want direct mode
1631 mfspr r3,scomc ; Get back the status
1632 sync
1633 isync
4a249263
A
1634
1635 isync
1636 mtspr hid0,r9 ; Restore entry hid0
1637 mfspr r9,hid0 ; Yes, this is silly, keep it here
1638 mfspr r9,hid0 ; Yes, this is a duplicate, keep it here
1639 mfspr r9,hid0 ; Yes, this is a duplicate, keep it here
1640 mfspr r9,hid0 ; Yes, this is a duplicate, keep it here
1641 mfspr r9,hid0 ; Yes, this is a duplicate, keep it here
1642 mfspr r9,hid0 ; Yes, this is a duplicate, keep it here
1643 isync
1644
55e303ae
A
1645 isync
1646 mtspr hid1,r12 ; Restore entry hid1
1647 mtspr hid1,r12 ; Stick it again
1648 isync
1649
1650 sync
1651 mtspr hid4,r4 ; Restore entry hid4
1652 isync
1653
1654 sync
1655 mtmsr r7 ; Restore MSR to entry
1656 isync
1657 blr ; Return...
1658
1659
1660
1c79356b
A
1661/* Disables all caches
1662 *
1663 * void cacheDisable(void)
1664 *
1665 * Turns off all caches on the processor. They are not flushed.
1666 *
1667 */
1668
1669; Force a line boundry here
1670 .align 5
1671 .globl EXT(cacheDisable)
1672
1673LEXT(cacheDisable)
1674
1675 mfsprg r11,2 ; Get CPU specific features
1676 mtcrf 0x83,r11 ; Set feature flags
1677
1678 bf pfAltivecb,cdNoAlt ; No vectors...
1679
1680 dssall ; Stop streams
1681
1682cdNoAlt: sync
1683
55e303ae
A
1684 btlr pf64Bitb ; No way to disable a 64-bit machine...
1685
1c79356b
A
1686 mfspr r5,hid0 ; Get the hid
1687 rlwinm r5,r5,0,dce+1,ice-1 ; Clear the I- and D- cache enables
1688 mtspr hid0,r5 ; Turn off dem caches
1689 sync
1690
55e303ae
A
1691 rlwinm. r0,r11,0,pfL2b,pfL2b ; is there an L2?
1692 beq cdNoL2 ; Skip if no L2...
1693
1c79356b
A
1694 mfspr r5,l2cr ; Get the L2
1695 rlwinm r5,r5,0,l2e+1,31 ; Turn off enable bit
1696
1697 b cinlaa ; Branch to next line...
1698
1699 .align 5
1700cinlcc: mtspr l2cr,r5 ; Disable L2
1701 sync
1702 isync
1703 b cdNoL2 ; It is off, we are done...
1704
1705cinlaa: b cinlbb ; Branch to next...
1706
1707cinlbb: sync ; Finish memory stuff
1708 isync ; Stop speculation
1709 b cinlcc ; Jump back up and turn off cache...
1710
1711cdNoL2:
55e303ae 1712
1c79356b
A
1713 bf pfL3b,cdNoL3 ; Skip down if no L3...
1714
1715 mfspr r5,l3cr ; Get the L3
1716 rlwinm r5,r5,0,l3e+1,31 ; Turn off enable bit
1717 rlwinm r5,r5,0,l3clken+1,l3clken-1 ; Turn off cache enable bit
1718 mtspr l3cr,r5 ; Disable the caches
1719 sync
1720
1721cdNoL3:
1722 blr ; Leave...
1723
1724
1725/* Initialize processor thermal monitoring
1726 * void ml_thrm_init(void)
1727 *
1728 * Build initial TAU registers and start them all going.
1729 * We ca not do this at initial start up because we need to have the processor frequency first.
1730 * And just why is this in assembler when it does not have to be?? Cause I am just too
1731 * lazy to open up a "C" file, thats why.
1732 */
1733
1734; Force a line boundry here
1735 .align 5
1736 .globl EXT(ml_thrm_init)
1737
1738LEXT(ml_thrm_init)
1739
1740 mfsprg r12,0 ; Get the per_proc blok
1741 lis r11,hi16(EXT(gPEClockFrequencyInfo)) ; Get top of processor information
1742 mfsprg r10,2 ; Get CPU specific features
1743 ori r11,r11,lo16(EXT(gPEClockFrequencyInfo)) ; Get bottom of processor information
1744 mtcrf 0x40,r10 ; Get the installed features
1745
1746 li r3,lo16(thrmtidm|thrmvm) ; Set for lower-than thermal event at 0 degrees
1747 bflr pfThermalb ; No thermal monitoring on this cpu
1748 mtspr thrm1,r3 ; Do it
1749
1750 lwz r3,thrmthrottleTemp(r12) ; Get our throttle temprature
1751 rlwinm r3,r3,31-thrmthre,thrmthrs,thrmthre ; Position it
1752 ori r3,r3,lo16(thrmvm) ; Set for higher-than event
1753 mtspr thrm2,r3 ; Set it
1754
1755 lis r4,hi16(1000000) ; Top of million
1756;
1757; Note: some CPU manuals say this is processor clocks, some say bus rate. The latter
1758; makes more sense because otherwise we can not get over about 400MHz.
1759#if 0
1760 lwz r3,PECFIcpurate(r11) ; Get the processor speed
1761#else
1762 lwz r3,PECFIbusrate(r11) ; Get the bus speed
1763#endif
1764 ori r4,r4,lo16(1000000) ; Bottom of million
1765 lis r7,hi16(thrmsitvm>>1) ; Get top of highest possible value
1766 divwu r3,r3,r4 ; Get number of cycles per microseconds
1767 ori r7,r7,lo16(thrmsitvm>>1) ; Get the bottom of the highest possible value
1768 addi r3,r3,1 ; Insure we have enough
1769 mulli r3,r3,20 ; Get 20 microseconds worth of cycles
1770 cmplw r3,r7 ; Check against max
1771 ble+ smallenuf ; It is ok...
1772 mr r3,r7 ; Saturate
1773
1774smallenuf: rlwinm r3,r3,31-thrmsitve,thrmsitvs,thrmsitve ; Position
1775 ori r3,r3,lo16(thrmem) ; Enable with at least 20micro sec sample
1776 stw r3,thrm3val(r12) ; Save this in case we need it later
1777 mtspr thrm3,r3 ; Do it
1778 blr
1779
1780
1781/* Set thermal monitor bounds
1782 * void ml_thrm_set(unsigned int low, unsigned int high)
1783 *
1784 * Set TAU to interrupt below low and above high. A value of
1785 * zero disables interruptions in that direction.
1786 */
1787
1788; Force a line boundry here
1789 .align 5
1790 .globl EXT(ml_thrm_set)
1791
1792LEXT(ml_thrm_set)
1793
1794 mfmsr r0 ; Get the MSR
9bccf70c
A
1795 rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1796 rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1c79356b
A
1797 rlwinm r6,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear EE bit
1798 mtmsr r6
9bccf70c 1799 isync
1c79356b
A
1800
1801 mfsprg r12,0 ; Get the per_proc blok
1802
1803 rlwinm. r6,r3,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
1804 mfsprg r9,2 ; Get CPU specific features
1805 stw r3,thrmlowTemp(r12) ; Set the low temprature
1806 mtcrf 0x40,r9 ; See if we can thermal this machine
1807 rlwinm r9,r9,(((31-thrmtie)+(pfThermIntb+1))&31),thrmtie,thrmtie ; Set interrupt enable if this machine can handle it
1808 bf pfThermalb,tsetcant ; No can do...
1809 beq tsetlowo ; We are setting the low off...
1810 ori r6,r6,lo16(thrmtidm|thrmvm) ; Set the lower-than and valid bit
1811 or r6,r6,r9 ; Set interruption request if supported
1812
1813tsetlowo: mtspr thrm1,r6 ; Cram the register
1814
1815 rlwinm. r6,r4,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
1816 stw r4,thrmhighTemp(r12) ; Set the high temprature
1817 beq tsethigho ; We are setting the high off...
1818 ori r6,r6,lo16(thrmvm) ; Set valid bit
1819 or r6,r6,r9 ; Set interruption request if supported
1820
1821tsethigho: mtspr thrm2,r6 ; Cram the register
1822
1823tsetcant: mtmsr r0 ; Reenable interruptions
1824 blr ; Leave...
1825
1826/* Read processor temprature
1827 * unsigned int ml_read_temp(void)
1828 *
1829 */
1830
1831; Force a line boundry here
1832 .align 5
1833 .globl EXT(ml_read_temp)
1834
1835LEXT(ml_read_temp)
1836
1837 mfmsr r9 ; Save the MSR
1c79356b 1838 li r5,15 ; Starting point for ranging (start at 15 so we do not overflow)
9bccf70c
A
1839 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1840 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1841 rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1c79356b
A
1842 mfsprg r7,2 ; Get CPU specific features
1843 mtmsr r8 ; Do not allow interruptions
1844 mtcrf 0x40,r7 ; See if we can thermal this machine
1845 bf pfThermalb,thrmcant ; No can do...
1846
1847 mfspr r11,thrm1 ; Save thrm1
1848
1849thrmrange: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
1850 ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
1851
1852 mtspr thrm1,r4 ; Set the test value
1853
1854thrmreada: mfspr r3,thrm1 ; Get the thermal register back
1855 rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
1856 beq+ thrmreada ; Nope...
1857
1858 rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
1859 bne thrmsearch ; No, we went over...
1860
1861 addi r5,r5,16 ; Start by trying every 16 degrees
1862 cmplwi r5,127 ; Have we hit the max?
1863 blt- thrmrange ; Got some more to do...
1864
1865thrmsearch: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
1866 ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
1867
1868 mtspr thrm1,r4 ; Set the test value
1869
1870thrmread: mfspr r3,thrm1 ; Get the thermal register back
1871 rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
1872 beq+ thrmread ; Nope...
1873
1874 rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
1875 beq thrmdone ; No, we hit it...
1876 addic. r5,r5,-1 ; Go down a degree
1877 bge+ thrmsearch ; Try again (until we are below freezing)...
1878
1879thrmdone: addi r3,r5,1 ; Return the temprature (bump it up to make it correct)
1880 mtspr thrm1,r11 ; Restore the thermal register
1881 mtmsr r9 ; Re-enable interruptions
1882 blr ; Leave...
1883
1884thrmcant: eqv r3,r3,r3 ; Return bogus temprature because we can not read it
1885 mtmsr r9 ; Re-enable interruptions
1886 blr ; Leave...
1887
1888/* Throttle processor speed up or down
1889 * unsigned int ml_throttle(unsigned int step)
1890 *
1891 * Returns old speed and sets new. Both step and return are values from 0 to
1892 * 255 that define number of throttle steps, 0 being off and "ictcfim" is max * 2.
1893 *
1894 */
1895
1896; Force a line boundry here
1897 .align 5
1898 .globl EXT(ml_throttle)
1899
1900LEXT(ml_throttle)
1901
1902 mfmsr r9 ; Save the MSR
9bccf70c
A
1903 rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
1904 rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
1c79356b
A
1905 rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
1906 cmplwi r3,lo16(ictcfim>>1) ; See if we are going too far
9bccf70c
A
1907 mtmsr r8 ; Do not allow interruptions
1908 isync
1c79356b
A
1909 ble+ throtok ; Throttle value is ok...
1910 li r3,lo16(ictcfim>>1) ; Set max
1911
1912throtok: rlwinm. r4,r3,1,ictcfib,ictcfie ; Set the throttle
1913 beq throtoff ; Skip if we are turning it off...
1914 ori r4,r4,lo16(thrmvm) ; Turn on the valid bit
1915
1916throtoff: mfspr r3,ictc ; Get the old throttle
1917 mtspr ictc,r4 ; Set the new
1918 rlwinm r3,r3,31,1,31 ; Shift throttle value over
1919 mtmsr r9 ; Restore interruptions
1920 blr ; Return...
1921
1922/*
1923** ml_get_timebase()
1924**
1925** Entry - R3 contains pointer to 64 bit structure.
1926**
1927** Exit - 64 bit structure filled in.
1928**
1929*/
1930; Force a line boundry here
1931 .align 5
1932 .globl EXT(ml_get_timebase)
1933
1934LEXT(ml_get_timebase)
1935
1936loop:
55e303ae
A
1937 mftbu r4
1938 mftb r5
1939 mftbu r6
1940 cmpw r6, r4
1941 bne- loop
1942
1943 stw r4, 0(r3)
1944 stw r5, 4(r3)
1945
1946 blr
1c79356b 1947
55e303ae
A
1948/*
1949 * unsigned int cpu_number(void)
1950 *
1951 * Returns the current cpu number.
1952 */
1953
1954 .align 5
1955 .globl EXT(cpu_number)
1956
1957LEXT(cpu_number)
1958 mfsprg r4,0 ; Get per-proc block
1959 lhz r3,PP_CPU_NUMBER(r4) ; Get CPU number
1960 blr ; Return...
9bccf70c 1961
d7e50217
A
1962
1963/*
55e303ae
A
1964 * void set_machine_current_act(thread_act_t)
1965 *
1966 * Set the current activation
d7e50217 1967 */
55e303ae
A
1968 .align 5
1969 .globl EXT(set_machine_current_act)
d7e50217 1970
55e303ae
A
1971LEXT(set_machine_current_act)
1972
1973 mtsprg 1,r3 ; Set spr1 with the active thread
1974 blr ; Return...
1975
1976/*
1977 * thread_t current_act(void)
1978 * thread_t current_thread(void)
1979 *
1980 *
1981 * Return the current thread for outside components.
1982 */
1983 .align 5
1984 .globl EXT(current_act)
1985 .globl EXT(current_thread)
1986
1987LEXT(current_act)
1988LEXT(current_thread)
1989
1990 mfsprg r3,1
1991 blr
1992
1993 .align 5
1994 .globl EXT(clock_get_uptime)
1995LEXT(clock_get_uptime)
19961: mftbu r9
1997 mftb r0
1998 mftbu r11
1999 cmpw r11,r9
2000 bne- 1b
2001 stw r0,4(r3)
2002 stw r9,0(r3)
2003 blr
2004
2005
2006 .align 5
2007 .globl EXT(mach_absolute_time)
2008LEXT(mach_absolute_time)
20091: mftbu r3
2010 mftb r4
2011 mftbu r0
2012 cmpw r0,r3
2013 bne- 1b
2014 blr
9bccf70c 2015
1c79356b
A
2016/*
2017** ml_sense_nmi()
2018**
2019*/
2020; Force a line boundry here
2021 .align 5
2022 .globl EXT(ml_sense_nmi)
2023
2024LEXT(ml_sense_nmi)
2025
2026 blr ; Leave...
2027
d52fe63f
A
2028/*
2029** ml_set_processor_speed()
2030**
2031*/
2032; Force a line boundry here
2033 .align 5
2034 .globl EXT(ml_set_processor_speed)
2035
2036LEXT(ml_set_processor_speed)
4a249263 2037 mfsprg r5, 0 ; Get the per_proc_info
9bccf70c 2038
4a249263
A
2039 lwz r6, pfPowerModes(r5) ; Get the supported power modes
2040
2041 rlwinm. r0, r6, 0, pmDualPLLb, pmDualPLLb ; Is DualPLL supported?
2042 bne spsDPLL
2043
e5568f75
A
2044 rlwinm. r0, r6, 0, pmDFSb, pmDFSb ; Is DFS supported?
2045 bne spsDFS
2046
4a249263
A
2047 rlwinm. r0, r6, 0, pmPowerTuneb, pmPowerTuneb ; Is DualPLL supported?
2048 bne spsPowerTune
2049
2050 b spsDone ; No supported power modes
2051
2052spsDPLL:
2053 cmpli cr0, r3, 0 ; Turn off BTIC before low speed
2054 beq spsDPLL1
2055 mfspr r4, hid0 ; Get the current hid0 value
2056 rlwinm r4, r4, 0, btic+1, btic-1 ; Clear the BTIC bit
9bccf70c 2057 sync
4a249263 2058 mtspr hid0, r4 ; Set the new hid0 value
9bccf70c
A
2059 isync
2060 sync
2061
4a249263
A
2062spsDPLL1:
2063 mfspr r4, hid1 ; Get the current PLL settings
2064 rlwimi r4, r3, 31-hid1ps, hid1ps, hid1ps ; Copy the PLL Select bit
2065 stw r4, pfHID1(r5) ; Save the new hid1 value
2066 mtspr hid1, r4 ; Select desired PLL
9bccf70c 2067
4a249263
A
2068 cmpli cr0, r3, 0 ; Restore BTIC after high speed
2069 bne spsDone
2070 lwz r4, pfHID0(r5) ; Load the hid0 value
9bccf70c 2071 sync
4a249263 2072 mtspr hid0, r4 ; Set the hid0 value
9bccf70c
A
2073 isync
2074 sync
4a249263
A
2075 b spsDone
2076
e5568f75
A
2077spsDFS:
2078 cmplwi r3, 0 ; full speed?
2079 mfspr r3, hid1 ; Get the current HID1
2080 rlwinm r3, r3, 0, hid1dfs1+1, hid1dfs0-1 ; assume full speed, clear dfs bits
2081 beq spsDFS1
2082 oris r3, r3, hi16(hid1dfs1m) ; slow, set half speed dfs1 bit
2083spsDFS1:
2084 stw r3, pfHID1(r5) ; Save the new hid1 value
2085 sync
2086 mtspr hid1, r3 ; Set the new HID1
2087 sync
2088 isync
2089 b spsDone
2090
4a249263
A
2091spsPowerTune:
2092 b spsDone
9bccf70c 2093
4a249263 2094spsDone:
d52fe63f 2095 blr
d12e1678
A
2096
2097/*
2098** ml_set_processor_voltage()
2099**
2100*/
2101; Force a line boundry here
2102 .align 5
2103 .globl EXT(ml_set_processor_voltage)
2104
2105LEXT(ml_set_processor_voltage)
4a249263
A
2106 mfsprg r5, 0 ; Get the per_proc_info
2107
2108 lwz r6, pfPowerModes(r5) ; Get the supported power modes
2109
2110 rlwinm. r0, r6, 0, pmDPLLVminb, pmDPLLVminb ; Is DPLL Vmin supported
2111 beq spvDone
2112
2113 mfspr r4, hid2 ; Get HID2 value
2114 rlwimi r4, r3, 31-hid2vmin, hid2vmin, hid2vmin ; Insert the voltage mode bit
2115 mtspr hid2, r4 ; Set the voltage mode
2116 sync ; Make sure it is done
2117
2118spvDone:
d12e1678 2119 blr