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