]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | #include <assym.s> | |
23 | #include <debug.h> | |
24 | #include <cpus.h> | |
25 | #include <db_machine_commands.h> | |
26 | #include <mach_rt.h> | |
27 | ||
28 | #include <mach_debug.h> | |
29 | #include <ppc/asm.h> | |
30 | #include <ppc/proc_reg.h> | |
31 | #include <ppc/exception.h> | |
32 | #include <ppc/Performance.h> | |
33 | #include <ppc/exception.h> | |
34 | #include <ppc/pmap_internals.h> | |
35 | #include <mach/ppc/vm_param.h> | |
36 | ||
37 | .text | |
38 | ||
39 | /* | |
40 | * This routine will add a savearea block to the free list. | |
41 | * Note really well: we can take NO exceptions of any kind, | |
42 | * including a PTE miss once the savearea lock is held. That's | |
43 | * a guaranteed deadlock. That means we must disable for interrutions | |
44 | * and turn all translation off. | |
45 | * | |
46 | * Note that the savearea list should NEVER be empty | |
47 | */ | |
48 | ||
49 | ENTRY(save_queue,TAG_NO_FRAME_USED) | |
50 | ||
51 | ||
150bd074 A |
52 | mfsprg r9,2 ; Get the feature flags |
53 | mr r11,r3 ; Save the block | |
54 | mtcrf 0x04,r9 ; Set the features | |
55 | mfmsr r12 ; Get the MSR | |
56 | lis r10,HIGH_ADDR(EXT(saveanchor)) ; Get the high part of the anchor | |
57 | andi. r3,r12,0x7FCF ; Turn off all translation and rupts | |
58 | ori r10,r10,LOW_ADDR(EXT(saveanchor)) ; Bottom half of the anchor | |
59 | ||
60 | bt pfNoMSRirb,sqNoMSR ; No MSR... | |
61 | ||
62 | mtmsr r3 ; Translation and all off | |
63 | isync ; Toss prefetch | |
64 | b sqNoMSRx | |
65 | ||
66 | sqNoMSR: li r0,loadMSR ; Get the MSR setter SC | |
67 | sc ; Set it | |
68 | sqNoMSRx: | |
1c79356b A |
69 | |
70 | #if 0 | |
150bd074 | 71 | rlwinm. r3,r11,0,0,19 /* (TEST/DEBUG) */ |
1c79356b A |
72 | bne+ notraceit /* (TEST/DEBUG) */ |
73 | BREAKPOINT_TRAP /* (TEST/DEBUG) */ | |
74 | notraceit: /* (TEST/DEBUG) */ | |
75 | #else | |
150bd074 | 76 | rlwinm r3,r11,0,0,19 /* Make sure it's clean and tidy */ |
1c79356b A |
77 | #endif |
78 | ||
1c79356b A |
79 | sqlck: lwarx r9,0,r10 /* Grab the lock value */ |
80 | li r8,1 /* Use part of the delay time */ | |
81 | mr. r9,r9 /* Is it locked? */ | |
82 | bne- sqlcks /* Yeah, wait for it to clear... */ | |
83 | stwcx. r8,0,r10 /* Try to seize that there durn lock */ | |
84 | beq+ sqlckd /* Got it... */ | |
85 | b sqlck /* Collision, try again... */ | |
86 | ||
87 | sqlcks: lwz r9,SVlock(r10) /* Get that lock in here */ | |
88 | mr. r9,r9 /* Is it free yet? */ | |
89 | beq+ sqlck /* Yeah, try for it again... */ | |
90 | b sqlcks /* Sniff away... */ | |
91 | ||
92 | sqlckd: isync /* Make sure translation is off */ | |
93 | lwz r7,SVfree(r10) /* Get the free save area list anchor */ | |
94 | lwz r6,SVcount(r10) /* Get the total count of saveareas */ | |
95 | stw r3,SVfree(r10) /* Queue in the new one */ | |
96 | addi r6,r6,sac_cnt /* Count the ones we are linking in */ | |
97 | stw r7,SACnext(r3) /* Queue the old first one off of us */ | |
98 | li r8,0 /* Get a free lock value */ | |
99 | stw r6,SVcount(r10) /* Save the new count */ | |
100 | ||
101 | sync /* Make sure everything is done */ | |
102 | stw r8,SVlock(r10) /* Unlock the savearea chain */ | |
103 | ||
104 | mtmsr r12 /* Restore interrupts and translation */ | |
105 | isync /* Dump any speculations */ | |
106 | ||
107 | #if 0 | |
108 | lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
109 | li r2,0x2201 ; (TEST/DEBUG) | |
110 | oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
111 | sc /* (TEST/DEBUG) */ | |
112 | #endif | |
113 | ||
114 | blr /* Leave... */ | |
115 | ||
116 | ||
117 | /* | |
118 | * This routine will find and remove an empty savearea block from the free list. | |
119 | * Note really well: we can take NO exceptions of any kind, | |
120 | * including a PTE miss once the savearea lock is held. That's | |
121 | * a guaranteed deadlock. That means we must disable for interrutions | |
122 | * and turn all translation off. | |
123 | * | |
124 | * We pass back the virtual address of the one we just released | |
125 | * or a zero if none to free. | |
126 | * | |
127 | * Note that the savearea list should NEVER be empty | |
128 | */ | |
129 | ||
130 | ENTRY(save_dequeue,TAG_NO_FRAME_USED) | |
131 | ||
132 | ||
150bd074 | 133 | mfsprg r9,2 ; Get the feature flags |
1c79356b | 134 | mfmsr r12 /* Get the MSR */ |
150bd074 | 135 | mtcrf 0x04,r9 ; Set the features |
1c79356b | 136 | lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ |
150bd074 | 137 | andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */ |
1c79356b | 138 | ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ |
1c79356b | 139 | |
150bd074 A |
140 | bt pfNoMSRirb,sdNoMSR ; No MSR... |
141 | ||
142 | mtmsr r3 ; Translation and all off | |
143 | isync ; Toss prefetch | |
144 | b sdNoMSRx | |
145 | ||
146 | sdNoMSR: li r0,loadMSR ; Get the MSR setter SC | |
147 | sc ; Set it | |
148 | sdNoMSRx: | |
1c79356b A |
149 | |
150 | sdqlck: lwarx r9,0,r10 /* Grab the lock value */ | |
151 | li r8,1 /* Use part of the delay time */ | |
152 | mr. r9,r9 /* Is it locked? */ | |
153 | bne- sdqlcks /* Yeah, wait for it to clear... */ | |
154 | stwcx. r8,0,r10 /* Try to seize that there durn lock */ | |
155 | beq+ sdqlckd /* Got it... */ | |
156 | b sdqlck /* Collision, try again... */ | |
157 | ||
158 | sdqlcks: lwz r9,SVlock(r10) /* Get that lock in here */ | |
159 | mr. r9,r9 /* Is it free yet? */ | |
160 | beq+ sdqlck /* Yeah, try for it again... */ | |
161 | b sdqlcks /* Sniff away... */ | |
162 | ||
163 | ||
765c9de3 A |
164 | sdqlckd: isync ; Clean out the prefetches |
165 | lwz r3,SVfree(r10) /* Get the free save area list anchor */ | |
1c79356b A |
166 | la r5,SVfree(r10) /* Remember that the we're just starting out */ |
167 | lwz r6,SVcount(r10) /* Get the total count of saveareas for later */ | |
168 | lis r8,sac_empty>>16 /* Get the empty block indication */ | |
169 | ||
170 | sdqchk: lwz r4,SACalloc(r3) /* Get the allocation flags */ | |
171 | lwz r9,SACflags(r3) /* Get the flags */ | |
172 | lwz r7,SACnext(r3) /* Point on to the next one */ | |
173 | andis. r9,r9,hi16(sac_perm) /* Is this permanently allocated? */ | |
174 | cmplw cr1,r4,r8 /* Does this look empty? */ | |
175 | bne- sdqperm /* It's permanent, can't release... */ | |
176 | beq- cr1,sdqfnd /* Yeah, empty... */ | |
177 | ||
178 | sdqperm: la r5,SACnext(r3) /* Remember the last guy */ | |
179 | mr. r3,r7 /* Any more left? */ | |
180 | bne+ sdqchk /* Yeah... */ | |
181 | b sdqunlk /* Nope, just go unlock and leave... */ | |
182 | ||
183 | sdqfnd: subi r6,r6,sac_cnt /* Back off the number of saveareas in here */ | |
184 | stw r7,0(r5) /* Dequeue our guy */ | |
185 | lwz r9,SACvrswap(r3) /* Get addressing conversion */ | |
186 | stw r6,SVcount(r10) /* Back off the count for this block */ | |
187 | xor r3,r3,r9 /* Flip to virtual addressing */ | |
188 | ||
189 | sdqunlk: li r8,0 /* Get a free lock value */ | |
190 | sync /* Make sure everything is done */ | |
191 | stw r8,SVlock(r10) /* Unlock the savearea chain */ | |
192 | ||
193 | mtmsr r12 /* Restore interrupts and translation */ | |
194 | isync /* Dump any speculations */ | |
195 | ||
196 | #if 0 | |
197 | lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
198 | li r2,0x2202 ; (TEST/DEBUG) | |
199 | oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
200 | sc /* (TEST/DEBUG) */ | |
201 | #endif | |
202 | ||
203 | blr /* Leave... */ | |
204 | ||
205 | ||
206 | ||
207 | /* | |
208 | * This routine will obtain a savearea from the free list. | |
209 | * Note really well: we can take NO exceptions of any kind, | |
210 | * including a PTE miss once the savearea lock is held. That's | |
211 | * a guaranteed deadlock. That means we must disable for interrutions | |
212 | * and turn all translation off. | |
213 | * | |
214 | * We pass back the virtual address of the one we just obtained | |
215 | * or a zero if none to allocate. | |
216 | * | |
217 | * Note that the savearea list should NEVER be empty | |
218 | * NOTE!!! NEVER USE R0, R2, or R12 IN HERE THAT WAY WE DON'T NEED A | |
219 | * STACK FRAME IN FPU_SAVE, FPU_SWITCH, VEC_SAVE, OR VEC_SWITCH. | |
220 | */ | |
221 | ||
222 | ENTRY(save_get_phys,TAG_NO_FRAME_USED) | |
223 | ||
224 | cmplw cr1,r1,r1 ; Set CR1_eq to indicate we want physical address | |
225 | b csaveget ; Join the common... | |
226 | ||
227 | ENTRY(save_get,TAG_NO_FRAME_USED) | |
228 | ||
229 | cmplwi cr1,r1,0 ; Set CR1_ne to indicate we want virtual address | |
230 | ||
150bd074 A |
231 | csaveget: mfsprg r9,2 ; Get the feature flags |
232 | mfmsr r11 ; Get the MSR | |
233 | mtcrf 0x04,r9 ; Set the features | |
1c79356b | 234 | lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ |
150bd074 | 235 | andi. r3,r11,0x7FCF /* Turn off all translation and 'rupts */ |
1c79356b | 236 | ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ |
150bd074 A |
237 | |
238 | bt pfNoMSRirb,sgNoMSR ; No MSR... | |
239 | ||
240 | mtmsr r3 ; Translation and all off | |
241 | isync ; Toss prefetch | |
242 | b sgNoMSRx | |
1c79356b | 243 | |
150bd074 A |
244 | sgNoMSR: mr r9,r0 ; Save this |
245 | li r0,loadMSR ; Get the MSR setter SC | |
246 | sc ; Set it | |
247 | mr r0,r9 ; Restore it | |
248 | ||
249 | sgNoMSRx: | |
1c79356b A |
250 | |
251 | sglck: lwarx r9,0,r10 /* Grab the lock value */ | |
252 | li r7,1 /* Use part of the delay time */ | |
253 | mr. r9,r9 /* Is it locked? */ | |
254 | bne- sglcks /* Yeah, wait for it to clear... */ | |
255 | stwcx. r7,0,r10 /* Try to seize that there durn lock */ | |
256 | beq+ sglckd /* Got it... */ | |
257 | b sglck /* Collision, try again... */ | |
258 | ||
259 | sglcks: lwz r9,SVlock(r10) /* Get that lock in here */ | |
260 | mr. r9,r9 /* Is it free yet? */ | |
261 | beq+ sglck /* Yeah, try for it again... */ | |
262 | b sglcks /* Sniff away... */ | |
263 | ||
264 | sglckd: isync /* Make sure translation is off */ | |
265 | lwz r8,SVfree(r10) /* Get the head of the save area list */ | |
266 | lwz r9,SVinuse(r10) /* Get the inuse field */ | |
267 | ||
268 | lwz r7,SACalloc(r8) /* Pick up the allocation bits */ | |
269 | lwz r5,SACvrswap(r8) /* Get real to virtual translation */ | |
270 | mr. r7,r7 /* Can we use the first one? */ | |
271 | blt use1st /* Yeah... */ | |
272 | ||
273 | andis. r7,r7,0x8000 /* Show we used the second and remember if it was the last */ | |
274 | addi r3,r8,0x0800 /* Point to the first one */ | |
275 | b gotsave /* We have the area now... */ | |
276 | ||
277 | use1st: andis. r7,r7,0x4000 /* Mark first gone and remember if empty */ | |
278 | mr r3,r8 /* Set the save area */ | |
279 | ||
280 | gotsave: stw r7,SACalloc(r8) /* Put back the allocation bits */ | |
281 | bne nodqsave /* There's still an empty slot, don't dequeue... */ | |
282 | ||
283 | lwz r4,SACnext(r8) /* Get the next in line */ | |
284 | stw r4,SVfree(r10) /* Dequeue our now empty save area block */ | |
285 | ||
286 | nodqsave: lis r6,HIGH_ADDR(SAVattach) /* Show that it is attached for now */ | |
287 | li r4,0 /* Clear this for the lock */ | |
288 | stw r6,SAVflags(r3) /* Set the flags to attached */ | |
289 | addi r9,r9,1 /* Bump up the inuse count */ | |
290 | stw r4,SAVprev(r3) /* Make sure that backchain is clear */ | |
291 | stw r9,SVinuse(r10) /* Set the inuse field */ | |
292 | sync /* Make sure all stores are done */ | |
293 | stw r4,SVlock(r10) /* Unlock both save and trace areas */ | |
294 | mtmsr r11 /* Restore translation and exceptions */ | |
295 | isync /* Make sure about it */ | |
296 | ||
297 | #if 0 | |
298 | mr r11,r0 /* (TEST/DEBUG) */ | |
299 | mr r7,r2 /* (TEST/DEBUG) */ | |
300 | lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
301 | li r2,0x2203 ; (TEST/DEBUG) | |
302 | oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
303 | sc /* (TEST/DEBUG) */ | |
304 | mr r0,r11 /* (TEST/DEBUG) */ | |
305 | mr r2,r7 /* (TEST/DEBUG) */ | |
306 | #endif | |
307 | ||
308 | li r7,0 ; NOTE WELL: we set R7 to zero for vector and float saving code in cswtch.s | |
309 | beqlr- cr1 ; Return now if we want the physical address | |
310 | xor r3,r3,r5 /* Get the virtual address */ | |
311 | blr /* Leave... */ | |
312 | ||
313 | ||
314 | /* | |
315 | * This routine will return a savearea to the free list. | |
316 | * Note really well: we can take NO exceptions of any kind, | |
317 | * including a PTE miss once the savearea lock is held. That's | |
318 | * a guaranteed deadlock. That means we must disable for interrutions | |
319 | * and turn all translation off. | |
320 | * | |
321 | * We take a virtual address. | |
322 | * | |
323 | */ | |
324 | ||
325 | ENTRY(save_ret,TAG_NO_FRAME_USED) | |
326 | ||
327 | #if 0 | |
328 | cmplwi r3,0x1000 ; (TEST/DEBUG) | |
329 | bgt+ notpage0 ; (TEST/DEBUG) | |
330 | BREAKPOINT_TRAP /* (TEST/DEBUG) */ | |
331 | ||
332 | notpage0: rlwinm r6,r3,0,0,19 /* (TEST/DEBUG) */ | |
333 | rlwinm r7,r3,21,31,31 /* (TEST/DEBUG) */ | |
334 | lis r8,0x8000 /* (TEST/DEBUG) */ | |
335 | lwz r6,SACalloc(r6) /* (TEST/DEBUG) */ | |
336 | srw r8,r8,r7 /* (TEST/DEBUG) */ | |
337 | and. r8,r8,r6 /* (TEST/DEBUG) */ | |
338 | beq+ nodoublefret /* (TEST/DEBUG) */ | |
339 | BREAKPOINT_TRAP /* (TEST/DEBUG) */ | |
340 | ||
341 | nodoublefret: /* (TEST/DEBUG) */ | |
342 | #endif | |
343 | ||
150bd074 | 344 | mfsprg r9,2 ; Get the feature flags |
1c79356b A |
345 | lwz r7,SAVflags(r3) /* Get the flags */ |
346 | rlwinm r6,r3,0,0,19 /* Round back down to the savearea page block */ | |
347 | andis. r7,r7,HIGH_ADDR(SAVinuse) /* Still in use? */ | |
348 | mfmsr r12 /* Get the MSR */ | |
349 | bnelr- /* Still in use, just leave... */ | |
350 | lwz r5,SACvrswap(r6) /* Get the conversion to real */ | |
150bd074 A |
351 | mr r8,r3 ; Save the savearea address |
352 | mtcrf 0x04,r9 ; Set the features | |
1c79356b | 353 | lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ |
150bd074 | 354 | andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */ |
1c79356b | 355 | ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ |
150bd074 A |
356 | |
357 | bt pfNoMSRirb,srNoMSR ; No MSR... | |
358 | ||
359 | mtmsr r3 ; Translation and all off | |
360 | isync ; Toss prefetch | |
361 | b srNoMSRx | |
362 | ||
363 | srNoMSR: li r0,loadMSR ; Get the MSR setter SC | |
364 | sc ; Set it | |
365 | srNoMSRx: | |
1c79356b A |
366 | |
367 | mfsprg r11,1 /* Get the active save area */ | |
150bd074 | 368 | xor r3,r8,r5 /* Get the real address of the savearea */ |
1c79356b A |
369 | cmplw r11,r3 /* Are we trying to toss the active one? */ |
370 | xor r6,r6,r5 /* Make the savearea block real also */ | |
371 | beq- srbigtimepanic /* This is a no-no... */ | |
372 | ||
373 | rlwinm r7,r3,21,31,31 /* Get position of savearea in block */ | |
374 | lis r8,0x8000 /* Build a bit mask and assume first savearea */ | |
375 | srw r8,r8,r7 /* Get bit position of do deallocate */ | |
376 | ||
1c79356b A |
377 | srlck: lwarx r11,0,r10 /* Grab the lock value */ |
378 | li r7,1 /* Use part of the delay time */ | |
379 | mr. r11,r11 /* Is it locked? */ | |
380 | bne- srlcks /* Yeah, wait for it to clear... */ | |
381 | stwcx. r7,0,r10 /* Try to seize that there durn lock */ | |
382 | beq+ srlckd /* Got it... */ | |
383 | b srlck /* Collision, try again... */ | |
384 | ||
385 | srlcks: lwz r11,SVlock(r10) /* Get that lock in here */ | |
386 | mr. r11,r11 /* Is it free yet? */ | |
387 | beq+ srlck /* Yeah, try for it again... */ | |
388 | b srlcks /* Sniff away... */ | |
389 | ||
390 | srlckd: isync /* Toss preexecutions */ | |
391 | lwz r11,SACalloc(r6) /* Get the allocation for this block */ | |
392 | lwz r7,SVinuse(r10) /* Get the in use count */ | |
393 | or r11,r11,r8 /* Turn on our bit */ | |
394 | subi r7,r7,1 /* We released one, adjust count */ | |
395 | cmplw r11,r8 /* Is our's the only one free? */ | |
396 | stw r7,SVinuse(r10) /* Save out count */ | |
397 | stw r11,SACalloc(r6) /* Save it out */ | |
398 | bne+ srtrest /* Nope, then the block is already on the free list */ | |
399 | ||
400 | lwz r11,SVfree(r10) /* Get the old head of the free list */ | |
401 | stw r6,SVfree(r10) /* Point the head at us now */ | |
402 | stw r11,SACnext(r6) /* Point us at the old last */ | |
403 | ||
404 | srtrest: li r8,0 /* Get set to clear the savearea lock */ | |
405 | sync /* Make sure it's all out there */ | |
406 | stw r8,SVlock(r10) /* Unlock it */ | |
407 | mtmsr r12 /* Restore interruptions and translation */ | |
408 | isync | |
409 | ||
410 | #if 0 | |
411 | lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
412 | li r2,0x2204 ; (TEST/DEBUG) | |
413 | oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ | |
414 | sc /* (TEST/DEBUG) */ | |
415 | #endif | |
416 | ||
417 | blr /* Go away... */ | |
418 | ||
419 | srbigtimepanic: | |
420 | lis r6,HIGH_ADDR(EXT(panic)) /* First half of panic call */ | |
421 | lis r3,HIGH_ADDR(EXT(srfreeactive)) /* First half of panic string */ | |
422 | ori r6,r6,LOW_ADDR(EXT(panic)) /* Second half of panic call */ | |
423 | ori r3,r3,LOW_ADDR(EXT(srfreeactive)) /* Second half of panic string */ | |
424 | mtlr r6 /* Get the address of the panic routine */ | |
425 | mtmsr r12 /* Restore interruptions and translation */ | |
426 | isync | |
427 | blrl /* Panic... */ | |
428 | ||
429 | .data | |
430 | EXT(srfreeactive): | |
431 | STRINGD "save_ret: Attempting to release the active savearea!!!!\000" | |
432 | .text | |
433 | ||
434 | ||
435 | /* | |
436 | * struct savearea *save_cpv(struct savearea *); Converts a physical savearea address to virtual | |
437 | */ | |
438 | ||
439 | .align 5 | |
440 | .globl EXT(save_cpv) | |
441 | ||
442 | LEXT(save_cpv) | |
443 | ||
444 | mfmsr r10 ; Get the current MSR | |
445 | rlwinm r4,r3,0,0,19 ; Round back to the start of the physical savearea block | |
446 | andi. r9,r10,0x7FEF ; Turn off interrupts and data translation | |
447 | mtmsr r9 ; Disable DR and EE | |
448 | isync | |
449 | ||
450 | lwz r4,SACvrswap(r4) ; Get the conversion to virtual | |
451 | mtmsr r10 ; Interrupts and DR back on | |
452 | isync | |
453 | xor r3,r3,r4 ; Convert to physical | |
454 | blr | |
455 | ||
456 | ||
457 | /* | |
458 | * This routine will return the virtual address of the first free savearea | |
459 | * block and disable for interruptions. | |
460 | * Note really well: this is only for debugging, don't expect it to always work! | |
461 | * | |
150bd074 | 462 | * We take a virtual address in R3 to save the original MSR, and |
1c79356b A |
463 | * return the virtual address. |
464 | * | |
465 | */ | |
466 | ||
467 | ENTRY(save_deb,TAG_NO_FRAME_USED) | |
468 | ||
150bd074 | 469 | mfsprg r9,2 ; Get the feature flags |
1c79356b A |
470 | mfmsr r12 /* Get the MSR */ |
471 | lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ | |
150bd074 | 472 | mtcrf 0x04,r9 ; Set the features |
1c79356b | 473 | stw r12,0(r3) /* Save it */ |
150bd074 | 474 | andi. r3,r12,0x7FCF /* Turn off all translation and 'rupts */ |
1c79356b | 475 | ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ |
150bd074 A |
476 | |
477 | bt pfNoMSRirb,sdbNoMSR ; No MSR... | |
478 | ||
479 | mtmsr r3 ; Translation and all off | |
480 | isync ; Toss prefetch | |
481 | b sdbNoMSRx | |
482 | ||
483 | sdbNoMSR: li r0,loadMSR ; Get the MSR setter SC | |
484 | sc ; Set it | |
485 | sdbNoMSRx: | |
486 | ||
1c79356b A |
487 | lwz r3,SVfree(r10) /* Get the physical first in list */ |
488 | andi. r11,r12,0x7FFF /* Clear only interruption */ | |
489 | lwz r5,SACvrswap(r3) /* Get the conversion to virtual */ | |
490 | mtmsr r11 /* Restore DAT but not INT */ | |
491 | xor r3,r3,r5 /* Make it virtual */ | |
492 | isync | |
493 | blr | |
494 | ||
495 | ||
496 | ||
497 | ||
498 |