]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/savearea_asm.s
xnu-123.5.tar.gz
[apple/xnu.git] / osfmk / ppc / savearea_asm.s
CommitLineData
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
49ENTRY(save_queue,TAG_NO_FRAME_USED)
50
51
52 mfmsr r12 /* Get the MSR */
53 lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
54 andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
55 ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
56 mtmsr r11 /* Make the MSR current */
57
58 isync
59
60#if 0
61 rlwinm. r3,r3,0,0,19 /* (TEST/DEBUG) */
62 bne+ notraceit /* (TEST/DEBUG) */
63 BREAKPOINT_TRAP /* (TEST/DEBUG) */
64notraceit: /* (TEST/DEBUG) */
65#else
66 rlwinm r3,r3,0,0,19 /* Make sure it's clean and tidy */
67#endif
68
69 lwarx r9,0,r10 ; ?
70
71sqlck: lwarx r9,0,r10 /* Grab the lock value */
72 li r8,1 /* Use part of the delay time */
73 mr. r9,r9 /* Is it locked? */
74 bne- sqlcks /* Yeah, wait for it to clear... */
75 stwcx. r8,0,r10 /* Try to seize that there durn lock */
76 beq+ sqlckd /* Got it... */
77 b sqlck /* Collision, try again... */
78
79sqlcks: lwz r9,SVlock(r10) /* Get that lock in here */
80 mr. r9,r9 /* Is it free yet? */
81 beq+ sqlck /* Yeah, try for it again... */
82 b sqlcks /* Sniff away... */
83
84sqlckd: isync /* Make sure translation is off */
85 lwz r7,SVfree(r10) /* Get the free save area list anchor */
86 lwz r6,SVcount(r10) /* Get the total count of saveareas */
87 stw r3,SVfree(r10) /* Queue in the new one */
88 addi r6,r6,sac_cnt /* Count the ones we are linking in */
89 stw r7,SACnext(r3) /* Queue the old first one off of us */
90 li r8,0 /* Get a free lock value */
91 stw r6,SVcount(r10) /* Save the new count */
92
93 sync /* Make sure everything is done */
94 stw r8,SVlock(r10) /* Unlock the savearea chain */
95
96 mtmsr r12 /* Restore interrupts and translation */
97 isync /* Dump any speculations */
98
99#if 0
100 lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */
101 li r2,0x2201 ; (TEST/DEBUG)
102 oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */
103 sc /* (TEST/DEBUG) */
104#endif
105
106 blr /* Leave... */
107
108
109/*
110 * This routine will find and remove an empty savearea block from the free list.
111 * Note really well: we can take NO exceptions of any kind,
112 * including a PTE miss once the savearea lock is held. That's
113 * a guaranteed deadlock. That means we must disable for interrutions
114 * and turn all translation off.
115 *
116 * We pass back the virtual address of the one we just released
117 * or a zero if none to free.
118 *
119 * Note that the savearea list should NEVER be empty
120 */
121
122ENTRY(save_dequeue,TAG_NO_FRAME_USED)
123
124
125 mfmsr r12 /* Get the MSR */
126 lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
127 andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
128 ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
129 mtmsr r11 /* Make the MSR current */
130 isync /* Make sure translation is off */
131
132 lwarx r9,0,r10 ; ?
133
134sdqlck: lwarx r9,0,r10 /* Grab the lock value */
135 li r8,1 /* Use part of the delay time */
136 mr. r9,r9 /* Is it locked? */
137 bne- sdqlcks /* Yeah, wait for it to clear... */
138 stwcx. r8,0,r10 /* Try to seize that there durn lock */
139 beq+ sdqlckd /* Got it... */
140 b sdqlck /* Collision, try again... */
141
142sdqlcks: lwz r9,SVlock(r10) /* Get that lock in here */
143 mr. r9,r9 /* Is it free yet? */
144 beq+ sdqlck /* Yeah, try for it again... */
145 b sdqlcks /* Sniff away... */
146
147
148sdqlckd: lwz r3,SVfree(r10) /* Get the free save area list anchor */
149 la r5,SVfree(r10) /* Remember that the we're just starting out */
150 lwz r6,SVcount(r10) /* Get the total count of saveareas for later */
151 lis r8,sac_empty>>16 /* Get the empty block indication */
152
153sdqchk: lwz r4,SACalloc(r3) /* Get the allocation flags */
154 lwz r9,SACflags(r3) /* Get the flags */
155 lwz r7,SACnext(r3) /* Point on to the next one */
156 andis. r9,r9,hi16(sac_perm) /* Is this permanently allocated? */
157 cmplw cr1,r4,r8 /* Does this look empty? */
158 bne- sdqperm /* It's permanent, can't release... */
159 beq- cr1,sdqfnd /* Yeah, empty... */
160
161sdqperm: la r5,SACnext(r3) /* Remember the last guy */
162 mr. r3,r7 /* Any more left? */
163 bne+ sdqchk /* Yeah... */
164 b sdqunlk /* Nope, just go unlock and leave... */
165
166sdqfnd: subi r6,r6,sac_cnt /* Back off the number of saveareas in here */
167 stw r7,0(r5) /* Dequeue our guy */
168 lwz r9,SACvrswap(r3) /* Get addressing conversion */
169 stw r6,SVcount(r10) /* Back off the count for this block */
170 xor r3,r3,r9 /* Flip to virtual addressing */
171
172sdqunlk: li r8,0 /* Get a free lock value */
173 sync /* Make sure everything is done */
174 stw r8,SVlock(r10) /* Unlock the savearea chain */
175
176 mtmsr r12 /* Restore interrupts and translation */
177 isync /* Dump any speculations */
178
179#if 0
180 lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */
181 li r2,0x2202 ; (TEST/DEBUG)
182 oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */
183 sc /* (TEST/DEBUG) */
184#endif
185
186 blr /* Leave... */
187
188
189
190/*
191 * This routine will obtain a savearea from the free list.
192 * Note really well: we can take NO exceptions of any kind,
193 * including a PTE miss once the savearea lock is held. That's
194 * a guaranteed deadlock. That means we must disable for interrutions
195 * and turn all translation off.
196 *
197 * We pass back the virtual address of the one we just obtained
198 * or a zero if none to allocate.
199 *
200 * Note that the savearea list should NEVER be empty
201 * NOTE!!! NEVER USE R0, R2, or R12 IN HERE THAT WAY WE DON'T NEED A
202 * STACK FRAME IN FPU_SAVE, FPU_SWITCH, VEC_SAVE, OR VEC_SWITCH.
203 */
204
205ENTRY(save_get_phys,TAG_NO_FRAME_USED)
206
207 cmplw cr1,r1,r1 ; Set CR1_eq to indicate we want physical address
208 b csaveget ; Join the common...
209
210ENTRY(save_get,TAG_NO_FRAME_USED)
211
212 cmplwi cr1,r1,0 ; Set CR1_ne to indicate we want virtual address
213
214csaveget: mfmsr r11 /* Get the MSR */
215 lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
216 andi. r8,r11,0x7FCF /* Turn off all translation and 'rupts */
217 ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
218 mtmsr r8 /* Make the MSR current */
219 isync ; Make sure it is done
220
221 lwarx r9,0,r10 ; ?
222
223sglck: lwarx r9,0,r10 /* Grab the lock value */
224 li r7,1 /* Use part of the delay time */
225 mr. r9,r9 /* Is it locked? */
226 bne- sglcks /* Yeah, wait for it to clear... */
227 stwcx. r7,0,r10 /* Try to seize that there durn lock */
228 beq+ sglckd /* Got it... */
229 b sglck /* Collision, try again... */
230
231sglcks: lwz r9,SVlock(r10) /* Get that lock in here */
232 mr. r9,r9 /* Is it free yet? */
233 beq+ sglck /* Yeah, try for it again... */
234 b sglcks /* Sniff away... */
235
236sglckd: isync /* Make sure translation is off */
237 lwz r8,SVfree(r10) /* Get the head of the save area list */
238 lwz r9,SVinuse(r10) /* Get the inuse field */
239
240 lwz r7,SACalloc(r8) /* Pick up the allocation bits */
241 lwz r5,SACvrswap(r8) /* Get real to virtual translation */
242 mr. r7,r7 /* Can we use the first one? */
243 blt use1st /* Yeah... */
244
245 andis. r7,r7,0x8000 /* Show we used the second and remember if it was the last */
246 addi r3,r8,0x0800 /* Point to the first one */
247 b gotsave /* We have the area now... */
248
249use1st: andis. r7,r7,0x4000 /* Mark first gone and remember if empty */
250 mr r3,r8 /* Set the save area */
251
252gotsave: stw r7,SACalloc(r8) /* Put back the allocation bits */
253 bne nodqsave /* There's still an empty slot, don't dequeue... */
254
255 lwz r4,SACnext(r8) /* Get the next in line */
256 stw r4,SVfree(r10) /* Dequeue our now empty save area block */
257
258nodqsave: lis r6,HIGH_ADDR(SAVattach) /* Show that it is attached for now */
259 li r4,0 /* Clear this for the lock */
260 stw r6,SAVflags(r3) /* Set the flags to attached */
261 addi r9,r9,1 /* Bump up the inuse count */
262 stw r4,SAVprev(r3) /* Make sure that backchain is clear */
263 stw r9,SVinuse(r10) /* Set the inuse field */
264 sync /* Make sure all stores are done */
265 stw r4,SVlock(r10) /* Unlock both save and trace areas */
266 mtmsr r11 /* Restore translation and exceptions */
267 isync /* Make sure about it */
268
269#if 0
270 mr r11,r0 /* (TEST/DEBUG) */
271 mr r7,r2 /* (TEST/DEBUG) */
272 lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */
273 li r2,0x2203 ; (TEST/DEBUG)
274 oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */
275 sc /* (TEST/DEBUG) */
276 mr r0,r11 /* (TEST/DEBUG) */
277 mr r2,r7 /* (TEST/DEBUG) */
278#endif
279
280 li r7,0 ; NOTE WELL: we set R7 to zero for vector and float saving code in cswtch.s
281 beqlr- cr1 ; Return now if we want the physical address
282 xor r3,r3,r5 /* Get the virtual address */
283 blr /* Leave... */
284
285
286/*
287 * This routine will return a savearea to the free list.
288 * Note really well: we can take NO exceptions of any kind,
289 * including a PTE miss once the savearea lock is held. That's
290 * a guaranteed deadlock. That means we must disable for interrutions
291 * and turn all translation off.
292 *
293 * We take a virtual address.
294 *
295 */
296
297ENTRY(save_ret,TAG_NO_FRAME_USED)
298
299#if 0
300 cmplwi r3,0x1000 ; (TEST/DEBUG)
301 bgt+ notpage0 ; (TEST/DEBUG)
302 BREAKPOINT_TRAP /* (TEST/DEBUG) */
303
304notpage0: rlwinm r6,r3,0,0,19 /* (TEST/DEBUG) */
305 rlwinm r7,r3,21,31,31 /* (TEST/DEBUG) */
306 lis r8,0x8000 /* (TEST/DEBUG) */
307 lwz r6,SACalloc(r6) /* (TEST/DEBUG) */
308 srw r8,r8,r7 /* (TEST/DEBUG) */
309 and. r8,r8,r6 /* (TEST/DEBUG) */
310 beq+ nodoublefret /* (TEST/DEBUG) */
311 BREAKPOINT_TRAP /* (TEST/DEBUG) */
312
313nodoublefret: /* (TEST/DEBUG) */
314#endif
315
316 lwz r7,SAVflags(r3) /* Get the flags */
317 rlwinm r6,r3,0,0,19 /* Round back down to the savearea page block */
318 andis. r7,r7,HIGH_ADDR(SAVinuse) /* Still in use? */
319 mfmsr r12 /* Get the MSR */
320 bnelr- /* Still in use, just leave... */
321 lwz r5,SACvrswap(r6) /* Get the conversion to real */
322 lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
323 andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
324 ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
325 mtmsr r11 /* Make the MSR current */
326 isync /* Make sure translation is off */
327
328 mfsprg r11,1 /* Get the active save area */
329 xor r3,r3,r5 /* Get the real address of the savearea */
330 cmplw r11,r3 /* Are we trying to toss the active one? */
331 xor r6,r6,r5 /* Make the savearea block real also */
332 beq- srbigtimepanic /* This is a no-no... */
333
334 rlwinm r7,r3,21,31,31 /* Get position of savearea in block */
335 lis r8,0x8000 /* Build a bit mask and assume first savearea */
336 srw r8,r8,r7 /* Get bit position of do deallocate */
337
338 lwarx r11,0,r10 ; ?
339
340srlck: lwarx r11,0,r10 /* Grab the lock value */
341 li r7,1 /* Use part of the delay time */
342 mr. r11,r11 /* Is it locked? */
343 bne- srlcks /* Yeah, wait for it to clear... */
344 stwcx. r7,0,r10 /* Try to seize that there durn lock */
345 beq+ srlckd /* Got it... */
346 b srlck /* Collision, try again... */
347
348srlcks: lwz r11,SVlock(r10) /* Get that lock in here */
349 mr. r11,r11 /* Is it free yet? */
350 beq+ srlck /* Yeah, try for it again... */
351 b srlcks /* Sniff away... */
352
353srlckd: isync /* Toss preexecutions */
354 lwz r11,SACalloc(r6) /* Get the allocation for this block */
355 lwz r7,SVinuse(r10) /* Get the in use count */
356 or r11,r11,r8 /* Turn on our bit */
357 subi r7,r7,1 /* We released one, adjust count */
358 cmplw r11,r8 /* Is our's the only one free? */
359 stw r7,SVinuse(r10) /* Save out count */
360 stw r11,SACalloc(r6) /* Save it out */
361 bne+ srtrest /* Nope, then the block is already on the free list */
362
363 lwz r11,SVfree(r10) /* Get the old head of the free list */
364 stw r6,SVfree(r10) /* Point the head at us now */
365 stw r11,SACnext(r6) /* Point us at the old last */
366
367srtrest: li r8,0 /* Get set to clear the savearea lock */
368 sync /* Make sure it's all out there */
369 stw r8,SVlock(r10) /* Unlock it */
370 mtmsr r12 /* Restore interruptions and translation */
371 isync
372
373#if 0
374 lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */
375 li r2,0x2204 ; (TEST/DEBUG)
376 oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */
377 sc /* (TEST/DEBUG) */
378#endif
379
380 blr /* Go away... */
381
382srbigtimepanic:
383 lis r6,HIGH_ADDR(EXT(panic)) /* First half of panic call */
384 lis r3,HIGH_ADDR(EXT(srfreeactive)) /* First half of panic string */
385 ori r6,r6,LOW_ADDR(EXT(panic)) /* Second half of panic call */
386 ori r3,r3,LOW_ADDR(EXT(srfreeactive)) /* Second half of panic string */
387 mtlr r6 /* Get the address of the panic routine */
388 mtmsr r12 /* Restore interruptions and translation */
389 isync
390 blrl /* Panic... */
391
392 .data
393EXT(srfreeactive):
394 STRINGD "save_ret: Attempting to release the active savearea!!!!\000"
395 .text
396
397
398/*
399 * struct savearea *save_cpv(struct savearea *); Converts a physical savearea address to virtual
400 */
401
402 .align 5
403 .globl EXT(save_cpv)
404
405LEXT(save_cpv)
406
407 mfmsr r10 ; Get the current MSR
408 rlwinm r4,r3,0,0,19 ; Round back to the start of the physical savearea block
409 andi. r9,r10,0x7FEF ; Turn off interrupts and data translation
410 mtmsr r9 ; Disable DR and EE
411 isync
412
413 lwz r4,SACvrswap(r4) ; Get the conversion to virtual
414 mtmsr r10 ; Interrupts and DR back on
415 isync
416 xor r3,r3,r4 ; Convert to physical
417 blr
418
419
420/*
421 * This routine will return the virtual address of the first free savearea
422 * block and disable for interruptions.
423 * Note really well: this is only for debugging, don't expect it to always work!
424 *
425 * We take a virtual address in R4 to save the original MSR, and
426 * return the virtual address.
427 *
428 */
429
430ENTRY(save_deb,TAG_NO_FRAME_USED)
431
432 mfmsr r12 /* Get the MSR */
433 lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
434 stw r12,0(r3) /* Save it */
435 andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
436 ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
437 mtmsr r11 /* Make the MSR current */
438 isync /* Make sure translation is off */
439 lwz r3,SVfree(r10) /* Get the physical first in list */
440 andi. r11,r12,0x7FFF /* Clear only interruption */
441 lwz r5,SACvrswap(r3) /* Get the conversion to virtual */
442 mtmsr r11 /* Restore DAT but not INT */
443 xor r3,r3,r5 /* Make it virtual */
444 isync
445 blr
446
447
448
449
450