]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/savearea.c
e96dd02466db5cbc2d641fb5d69faf7e606f59b1
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * This file is used to maintain the exception save areas
29 #include <mach_kgdb.h>
30 #include <mach_vm_debug.h>
32 #include <kern/thread.h>
33 #include <mach/vm_attributes.h>
34 #include <mach/vm_param.h>
35 #include <vm/vm_kern.h>
36 #include <vm/vm_map.h>
37 #include <vm/vm_page.h>
38 #include <mach/ppc/thread_status.h>
40 #include <kern/simple_lock.h>
42 #include <kern/misc_protos.h>
43 #include <ppc/misc_protos.h>
44 #include <ppc/proc_reg.h>
47 #include <ppc/pmap_internals.h>
48 #include <ppc/Firmware.h>
49 #include <ppc/mappings.h>
50 #include <ppc/exception.h>
51 #include <ppc/savearea.h>
52 #include <ddb/db_output.h>
55 extern struct Saveanchor saveanchor
; /* Aliged savearea anchor */
56 unsigned int debsave0
= 0; /* Debug flag */
57 unsigned int backchain
= 0; /* Debug flag */
60 * These routines keep track of exception save areas and keeps the count within specific limits. If there are
61 * too few, more are allocated, too many, and they are released. This savearea is where the PCBs are
62 * stored. They never span a page boundary and are referenced by both virtual and real addresses.
63 * Within the interrupt vectors, the real address is used because at that level, no exceptions
64 * can be tolerated. Save areas can be dynamic or permanent. Permanant saveareas are allocated
65 * at boot time and must be in place before any type of exception occurs. These are never released,
66 * and the number is based upon some arbitrary (yet to be determined) amount times the number of
67 * processors. This represents the minimum number required to process a total system failure without
68 * destroying valuable and ever-so-handy system debugging information.
74 * This routine allocates a save area. It checks if enough are available.
75 * If not, it allocates upward to the target free count.
76 * Then, it allocates one and returns it.
81 struct savearea
*save_alloc(void) { /* Reserve a save area */
84 savectl
*sctl
; /* Previous and current save pages */
85 vm_offset_t vaddr
, paddr
;
86 struct savearea
*newbaby
;
88 if(saveanchor
.savecount
<= (saveanchor
.saveneed
- saveanchor
.saveneghyst
)) { /* Start allocating if we drop too far */
89 while(saveanchor
.savecount
< saveanchor
.saveneed
) { /* Keep adding until the adjustment is done */
92 retr
= kmem_alloc_wired(kernel_map
, &vaddr
, PAGE_SIZE
); /* Find a virtual address to use */
94 if(retr
!= KERN_SUCCESS
) { /* Did we get some memory? */
95 panic("Whoops... Not a bit of wired memory left for saveareas\n");
98 paddr
= pmap_extract(kernel_pmap
, vaddr
); /* Get the physical */
100 bzero((void *)vaddr
, PAGE_SIZE
); /* Clear it all to zeros */
101 sctl
= (savectl
*)(vaddr
+PAGE_SIZE
-sizeof(savectl
)); /* Point to the control area of the new page */
102 sctl
->sac_alloc
= sac_empty
; /* Mark all entries free */
103 sctl
->sac_vrswap
= (unsigned int)vaddr
^ (unsigned int)paddr
; /* Form mask to convert V to R and vice versa */
105 sctl
->sac_flags
|= 0x0000EE00; /* (TEST/DEBUG) */
107 if(!save_queue(paddr
)) { /* Add the new ones to the free savearea list */
108 panic("Arrgghhhh, time out trying to lock the savearea anchor during upward adjustment\n");
112 if (saveanchor
.savecount
> saveanchor
.savemaxcount
)
113 saveanchor
.savemaxcount
= saveanchor
.savecount
;
115 newbaby
= save_get(); /* Get a savearea and return it */
116 if(!((unsigned int)newbaby
& 0xFFFFF000)) { /* Whoa... None left??? No, way, no can do... */
117 panic("No saveareas?!?!?! No way! Can't happen! Nuh-uh... I'm dead, done for, kaput...\n");
120 return newbaby
; /* Bye-bye baby... */
126 * This routine releases a save area to the free queue. If after that, we have more than our maximum target,
127 * we start releasing what we can until we hit the normal target.
132 void save_release(struct savearea
*save
) { /* Release a save area */
134 savectl
*csave
; /* The just released savearea block */
136 save_ret(save
); /* Return a savearea to the free list */
138 if(saveanchor
.savecount
> (saveanchor
.saveneed
+ saveanchor
.saveposhyst
)) { /* Start releasing if we have to many */
139 csave
= (savectl
*)42; /* Start with some nonzero garbage */
140 while((unsigned int)csave
&& (saveanchor
.savecount
> saveanchor
.saveneed
)) { /* Keep removing until the adjustment is done */
142 csave
= save_dequeue(); /* Find and dequeue one that is all empty */
144 if((unsigned int)csave
& 1) { /* Did we timeout trying to get the lock? */
145 panic("Arrgghhhh, time out trying to lock the savearea anchor during downward adjustment\n");
149 if((unsigned int)csave
) kmem_free(kernel_map
, (vm_offset_t
) csave
, PAGE_SIZE
); /* Release the page if we found one */
157 save_fake_zone_info(int *count
, vm_size_t
*cur_size
, vm_size_t
*max_size
, vm_size_t
*elem_size
,
158 vm_size_t
*alloc_size
, int *collectable
, int *exhaustable
)
160 *count
= saveanchor
.saveinuse
;
161 *cur_size
= saveanchor
.savecount
* (PAGE_SIZE
/ 2);
162 *max_size
= saveanchor
.savemaxcount
* (PAGE_SIZE
/ 2);
163 *elem_size
= PAGE_SIZE
/ 2;
164 *alloc_size
= PAGE_SIZE
;
172 * This routine prints the free savearea block chain for debugging.
177 void save_free_dump(void) { /* Dump the free chain */
179 unsigned int *dsv
, omsr
;
182 dsv
= save_deb(&omsr
); /* Get the virtual of the first and disable interrupts */
184 while(dsv
) { /* Do 'em all */
185 dsc
=(savectl
*)((unsigned int)dsv
+4096-sizeof(savectl
)); /* Point to the control area */
186 // printf("%08X %08X: nxt=%08X; alloc=%08X; flags=%08X\n", dsv, /* Print it all out */
187 // ((unsigned int)dsv)^(dsc->sac_vrswap), dsc->sac_next, dsc->sac_alloc, dsc->sac_flags);
188 dsv
=(unsigned int *)(((unsigned int) dsc
->sac_next
)^(dsc
->sac_vrswap
)); /* On to the next, virtually */
191 __asm__
volatile ("mtmsr %0" : : "r" (omsr
)); /* Restore the interruption mask */
196 * This routine prints the free savearea block chain for debugging.
201 void DumpTheSave(struct savearea
*save
) { /* Dump the free chain */
205 printf("savearea at %08X\n", save
);
206 printf(" srrs: %08X %08X\n", save
->save_srr0
, save
->save_srr1
);
207 printf(" cr, xer, lr: %08X %08X %08X\n", save
->save_cr
, save
->save_xer
, save
->save_lr
);
208 printf("ctr, dar, dsisr: %08X %08X %08X\n", save
->save_ctr
, save
->save_dar
, save
->save_dsisr
);
209 printf(" space, copyin: %08X %08X\n", save
->save_space
, save
->save_sr_copyin
);
211 printf(" regs: %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[0], r
[1], r
[2], r
[3], r
[4], r
[5], r
[6], r
[7]);
212 printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[8], r
[9], r
[10], r
[11], r
[12], r
[13], r
[14], r
[15]);
213 printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[16], r
[17], r
[18], r
[19], r
[20], r
[21], r
[22], r
[23]);
214 printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[24], r
[25], r
[29], r
[27], r
[28], r
[29], r
[30], r
[31]);
215 r
=(unsigned int *)&save
->save_fp0
;
216 printf(" floats: %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[0], r
[1], r
[2], r
[3], r
[4], r
[5], r
[6], r
[7]);
217 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[8], r
[9], r
[10], r
[11], r
[12], r
[13], r
[14], r
[15]);
218 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[16], r
[17], r
[18], r
[19], r
[20], r
[21], r
[22], r
[23]);
219 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[24], r
[25], r
[29], r
[27], r
[28], r
[29], r
[30], r
[31]);
220 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[32], r
[33], r
[34], r
[35], r
[36], r
[37], r
[38], r
[39]);
221 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[40], r
[41], r
[42], r
[43], r
[44], r
[45], r
[46], r
[47]);
222 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[48], r
[49], r
[50], r
[51], r
[52], r
[53], r
[54], r
[55]);
223 printf(" %08X%08X %08X%08X %08X%08X %08X%08X\n", r
[56], r
[57], r
[58], r
[59], r
[60], r
[61], r
[62], r
[63]);
225 printf(" srs: %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[0], r
[1], r
[2], r
[3], r
[4], r
[5], r
[6], r
[7]);
226 printf(" %08X %08X %08X %08X %08X %08X %08X %08X\n", r
[8], r
[9], r
[10], r
[11], r
[12], r
[13], r
[14], r
[15]);
227 printf("prev, phys, act: %08X %08X %08X\n", save
->save_prev
, save
->save_phys
, save
->save_act
);
228 printf(" flags: %08X\n", save
->save_flags
);
236 * Dumps out savearea and stack backchains
239 void DumpBackChain(struct savearea
*save
) { /* Prints out back chains */
244 if(!backchain
) return;
245 printf("Proceeding back from savearea at %08X:\n", save
);
248 printf(" curr=%08X; prev=%08X; stack=%08X\n", sv
, sv
->save_prev
, sv
->save_r1
);