]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/savearea.c
xnu-124.1.tar.gz
[apple/xnu.git] / osfmk / ppc / savearea.c
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/*
23 * This file is used to maintain the exception save areas
24 *
25 */
26
27#include <cpus.h>
28#include <debug.h>
29#include <mach_kgdb.h>
30#include <mach_vm_debug.h>
31
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>
39#include <kern/spl.h>
40#include <kern/simple_lock.h>
41
42#include <kern/misc_protos.h>
43#include <ppc/misc_protos.h>
44#include <ppc/proc_reg.h>
45#include <ppc/mem.h>
46#include <ppc/pmap.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>
53
54
55extern struct Saveanchor saveanchor; /* Aliged savearea anchor */
56unsigned int debsave0 = 0; /* Debug flag */
57unsigned int backchain = 0; /* Debug flag */
58
59/*
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.
69 *
70 *
71 */
72
73/*
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.
77 */
78
79
80
81struct savearea *save_alloc(void) { /* Reserve a save area */
82
83 kern_return_t retr;
84 savectl *sctl; /* Previous and current save pages */
85 vm_offset_t vaddr, paddr;
86 struct savearea *newbaby;
87
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 */
90
91
92 retr = kmem_alloc_wired(kernel_map, &vaddr, PAGE_SIZE); /* Find a virtual address to use */
93
94 if(retr != KERN_SUCCESS) { /* Did we get some memory? */
95 panic("Whoops... Not a bit of wired memory left for saveareas\n");
96 }
97
98 paddr = pmap_extract(kernel_pmap, vaddr); /* Get the physical */
99
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 */
104
105 sctl->sac_flags |= 0x0000EE00; /* (TEST/DEBUG) */
106
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");
109 }
110 }
111 }
112 if (saveanchor.savecount > saveanchor.savemaxcount)
113 saveanchor.savemaxcount = saveanchor.savecount;
114
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");
118 }
119
120 return newbaby; /* Bye-bye baby... */
121
122}
123
124
125/*
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.
128 */
129
130
131
132void save_release(struct savearea *save) { /* Release a save area */
133
134 savectl *csave; /* The just released savearea block */
135
136 save_ret(save); /* Return a savearea to the free list */
137
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 */
141
142 csave = save_dequeue(); /* Find and dequeue one that is all empty */
143
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");
146 return;
147 }
148
149 if((unsigned int)csave) kmem_free(kernel_map, (vm_offset_t) csave, PAGE_SIZE); /* Release the page if we found one */
150 }
151 }
152 return;
153
154}
155
156
157save_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)
159{
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;
165 *collectable = 1;
166 *exhaustable = 0;
167}
168
169
170
171/*
172 * This routine prints the free savearea block chain for debugging.
173 */
174
175
176
177void save_free_dump(void) { /* Dump the free chain */
178
179 unsigned int *dsv, omsr;
180 savectl *dsc;
181
182 dsv = save_deb(&omsr); /* Get the virtual of the first and disable interrupts */
183
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 */
189
190 }
191 __asm__ volatile ("mtmsr %0" : : "r" (omsr)); /* Restore the interruption mask */
192 return;
193}
194
195/*
196 * This routine prints the free savearea block chain for debugging.
197 */
198
199
200
201void DumpTheSave(struct savearea *save) { /* Dump the free chain */
202
203 unsigned int *r;
204
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);
210 r=&save->save_r0;
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]);
224 r=&save->save_sr0;
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);
229 return;
230}
231
232
233
234
235/*
236 * Dumps out savearea and stack backchains
237 */
238
239void DumpBackChain(struct savearea *save) { /* Prints out back chains */
240
241 unsigned int *r;
242 savearea *sv;
243
244 if(!backchain) return;
245 printf("Proceeding back from savearea at %08X:\n", save);
246 sv=save;
247 while(sv) {
248 printf(" curr=%08X; prev=%08X; stack=%08X\n", sv, sv->save_prev, sv->save_r1);
249 sv=sv->save_prev;
250 }
251 return;
252}
253
254
255
256