|
|
1.1 root 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:
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) */
64: notraceit: /* (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:
71: sqlck: 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:
79: sqlcks: 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:
84: sqlckd: 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:
122: ENTRY(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:
134: sdqlck: 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:
142: sdqlcks: 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:
148: sdqlckd: 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:
153: sdqchk: 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:
161: sdqperm: 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:
166: sdqfnd: 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:
172: sdqunlk: 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:
205: ENTRY(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:
210: ENTRY(save_get,TAG_NO_FRAME_USED)
211:
212: cmplwi cr1,r1,0 ; Set CR1_ne to indicate we want virutal address
213:
214: csaveget: 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:
223: sglck: 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:
231: sglcks: 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:
236: sglckd: 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:
249: use1st: andis. r7,r7,0x4000 /* Mark first gone and remember if empty */
250: mr r3,r8 /* Set the save area */
251:
252: gotsave: 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:
258: nodqsave: 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:
297: ENTRY(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:
304: notpage0: 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:
313: nodoublefret: /* (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:
340: srlck: 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:
348: srlcks: 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:
353: srlckd: 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:
367: srtrest: 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:
382: srbigtimepanic:
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
393: EXT(srfreeactive):
394: STRINGD "save_ret: Attempting to release the active savearea!!!!"
395: .text
396:
397:
398: /*
399: * This routine will return the virtual address of the first free savearea
400: * block and disable for interruptions.
401: * Note really well: this is only for debugging, don't expect it to always work!
402: *
403: * We take a virtual address in R4 to save the original MSR, and
404: * return the virtual address.
405: *
406: */
407:
408: ENTRY(save_deb,TAG_NO_FRAME_USED)
409:
410: mfmsr r12 /* Get the MSR */
411: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */
412: stw r12,0(r3) /* Save it */
413: andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */
414: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */
415: mtmsr r11 /* Make the MSR current */
416: isync /* Make sure translation is off */
417: lwz r3,SVfree(r10) /* Get the physical first in list */
418: andi. r11,r12,0x7FFF /* Clear only interruption */
419: lwz r5,SACvrswap(r3) /* Get the conversion to virtual */
420: mtmsr r11 /* Restore DAT but not INT */
421: xor r3,r3,r5 /* Make it virtual */
422: isync
423: blr
424:
425:
426:
427:
428:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.