Rev 814 | Rev 822 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 814 | Rev 820 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (C) 2001-2005 Jakub Jermar |
2 | * Copyright (C) 2001-2005 Jakub Jermar |
3 | * Copyright (C) 2005 Sergey Bondari |
3 | * Copyright (C) 2005 Sergey Bondari |
4 | * All rights reserved. |
4 | * All rights reserved. |
5 | * |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
8 | * are met: |
9 | * |
9 | * |
10 | * - Redistributions of source code must retain the above copyright |
10 | * - Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * - Redistributions in binary form must reproduce the above copyright |
12 | * - Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
14 | * documentation and/or other materials provided with the distribution. |
15 | * - The name of the author may not be used to endorse or promote products |
15 | * - The name of the author may not be used to endorse or promote products |
16 | * derived from this software without specific prior written permission. |
16 | * derived from this software without specific prior written permission. |
17 | * |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
28 | */ |
29 | 29 | ||
30 | /* |
30 | /* |
31 | * Locking order |
31 | * Locking order |
32 | * |
32 | * |
33 | * In order to access particular zone, the process must first lock |
33 | * In order to access particular zone, the process must first lock |
34 | * the zones.lock, then lock the zone and then unlock the zones.lock. |
34 | * the zones.lock, then lock the zone and then unlock the zones.lock. |
35 | * This insures, that we can fiddle with the zones in runtime without |
35 | * This insures, that we can fiddle with the zones in runtime without |
36 | * affecting the processes. |
36 | * affecting the processes. |
37 | * |
37 | * |
38 | */ |
38 | */ |
39 | 39 | ||
40 | #include <typedefs.h> |
40 | #include <typedefs.h> |
41 | #include <arch/types.h> |
41 | #include <arch/types.h> |
42 | #include <mm/frame.h> |
42 | #include <mm/frame.h> |
43 | #include <mm/as.h> |
43 | #include <mm/as.h> |
44 | #include <panic.h> |
44 | #include <panic.h> |
45 | #include <debug.h> |
45 | #include <debug.h> |
46 | #include <adt/list.h> |
46 | #include <adt/list.h> |
47 | #include <synch/spinlock.h> |
47 | #include <synch/spinlock.h> |
48 | #include <arch/asm.h> |
48 | #include <arch/asm.h> |
49 | #include <arch.h> |
49 | #include <arch.h> |
50 | #include <print.h> |
50 | #include <print.h> |
51 | #include <align.h> |
51 | #include <align.h> |
52 | #include <mm/slab.h> |
52 | #include <mm/slab.h> |
53 | 53 | ||
54 | typedef struct { |
54 | typedef struct { |
55 | count_t refcount; /**< tracking of shared frames */ |
55 | count_t refcount; /**< tracking of shared frames */ |
56 | __u8 buddy_order; /**< buddy system block order */ |
56 | __u8 buddy_order; /**< buddy system block order */ |
57 | link_t buddy_link; /**< link to the next free block inside one order */ |
57 | link_t buddy_link; /**< link to the next free block inside one order */ |
58 | void *parent; /**< If allocated by slab, this points there */ |
58 | void *parent; /**< If allocated by slab, this points there */ |
59 | }frame_t; |
59 | }frame_t; |
60 | 60 | ||
61 | typedef struct { |
61 | typedef struct { |
62 | SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ |
62 | SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ |
63 | pfn_t base; /**< frame_no of the first frame in the frames array */ |
63 | pfn_t base; /**< frame_no of the first frame in the frames array */ |
64 | pfn_t count; /**< Size of zone */ |
64 | count_t count; /**< Size of zone */ |
65 | 65 | ||
66 | frame_t *frames; /**< array of frame_t structures in this zone */ |
66 | frame_t *frames; /**< array of frame_t structures in this zone */ |
67 | count_t free_count; /**< number of free frame_t structures */ |
67 | count_t free_count; /**< number of free frame_t structures */ |
68 | count_t busy_count; /**< number of busy frame_t structures */ |
68 | count_t busy_count; /**< number of busy frame_t structures */ |
69 | 69 | ||
70 | buddy_system_t * buddy_system; /**< buddy system for the zone */ |
70 | buddy_system_t * buddy_system; /**< buddy system for the zone */ |
71 | int flags; |
71 | int flags; |
72 | }zone_t; |
72 | }zone_t; |
73 | 73 | ||
74 | /* |
74 | /* |
75 | * The zoneinfo.lock must be locked when accessing zoneinfo structure. |
75 | * The zoneinfo.lock must be locked when accessing zoneinfo structure. |
76 | * Some of the attributes in zone_t structures are 'read-only' |
76 | * Some of the attributes in zone_t structures are 'read-only' |
77 | */ |
77 | */ |
78 | 78 | ||
79 | struct { |
79 | struct { |
80 | SPINLOCK_DECLARE(lock); |
80 | SPINLOCK_DECLARE(lock); |
81 | int count; |
81 | int count; |
82 | zone_t *info[ZONES_MAX]; |
82 | zone_t *info[ZONES_MAX]; |
83 | }zones; |
83 | }zones; |
84 | 84 | ||
85 | 85 | ||
86 | /*********************************/ |
86 | /*********************************/ |
87 | /* Helper functions */ |
87 | /* Helper functions */ |
88 | static inline index_t frame_index(zone_t *zone, frame_t *frame) |
88 | static inline index_t frame_index(zone_t *zone, frame_t *frame) |
89 | { |
89 | { |
90 | return (index_t)(frame - zone->frames); |
90 | return (index_t)(frame - zone->frames); |
91 | } |
91 | } |
92 | static inline index_t frame_index_abs(zone_t *zone, frame_t *frame) |
92 | static inline index_t frame_index_abs(zone_t *zone, frame_t *frame) |
93 | { |
93 | { |
94 | return (index_t)(frame - zone->frames) + zone->base; |
94 | return (index_t)(frame - zone->frames) + zone->base; |
95 | } |
95 | } |
96 | static inline int frame_index_valid(zone_t *zone, index_t index) |
96 | static inline int frame_index_valid(zone_t *zone, index_t index) |
97 | { |
97 | { |
98 | return index >= 0 && index < zone->count; |
98 | return index >= 0 && index < zone->count; |
99 | } |
99 | } |
100 | 100 | ||
101 | /** Compute pfn_t from frame_t pointer & zone pointer */ |
101 | /** Compute pfn_t from frame_t pointer & zone pointer */ |
102 | static pfn_t make_frame_index(zone_t *zone, frame_t *frame) |
102 | static index_t make_frame_index(zone_t *zone, frame_t *frame) |
103 | { |
103 | { |
104 | return frame - zone->frames; |
104 | return frame - zone->frames; |
105 | } |
105 | } |
106 | 106 | ||
107 | /** Initialize frame structure |
107 | /** Initialize frame structure |
108 | * |
108 | * |
109 | * Initialize frame structure. |
109 | * Initialize frame structure. |
110 | * |
110 | * |
111 | * @param frame Frame structure to be initialized. |
111 | * @param frame Frame structure to be initialized. |
112 | */ |
112 | */ |
113 | static void frame_initialize(frame_t *frame) |
113 | static void frame_initialize(frame_t *frame) |
114 | { |
114 | { |
115 | frame->refcount = 1; |
115 | frame->refcount = 1; |
116 | frame->buddy_order = 0; |
116 | frame->buddy_order = 0; |
117 | } |
117 | } |
118 | 118 | ||
119 | /*************************************/ |
119 | /*************************************/ |
120 | /* Zoneinfo functions */ |
120 | /* Zoneinfo functions */ |
121 | 121 | ||
122 | /** |
122 | /** |
123 | * Insert-sort zone into zones list |
123 | * Insert-sort zone into zones list |
124 | */ |
124 | */ |
125 | static void zones_add_zone(zone_t *zone) |
125 | static void zones_add_zone(zone_t *zone) |
126 | { |
126 | { |
127 | int i; |
127 | int i; |
128 | 128 | ||
129 | spinlock_lock(&zones.lock); |
129 | spinlock_lock(&zones.lock); |
130 | /* Try to merge */ |
130 | /* Try to merge */ |
131 | if (zone->flags & ZONE_JOIN) { |
131 | if (zone->flags & ZONE_JOIN) { |
132 | for (i=0; i < zones.count; i++) { |
132 | for (i=0; i < zones.count; i++) { |
133 | spinlock_lock(&zones.info[i]->lock); |
133 | spinlock_lock(&zones.info[i]->lock); |
134 | 134 | ||
135 | /* Join forward, join backward */ |
135 | /* Join forward, join backward */ |
136 | panic("Not implemented"); |
136 | panic("Not implemented"); |
137 | 137 | ||
138 | spinlock_unlock(&zones.info[i]->lock); |
138 | spinlock_unlock(&zones.info[i]->lock); |
139 | } |
139 | } |
140 | spinlock_unlock(&zones.lock); |
140 | spinlock_unlock(&zones.lock); |
141 | } else { |
141 | } else { |
142 | if (zones.count+1 == ZONES_MAX) |
142 | if (zones.count+1 == ZONES_MAX) |
143 | panic("Maximum zone(%d) count exceeded.", ZONES_MAX); |
143 | panic("Maximum zone(%d) count exceeded.", ZONES_MAX); |
144 | zones.info[zones.count++] = zone; |
144 | zones.info[zones.count++] = zone; |
145 | } |
145 | } |
146 | spinlock_unlock(&zones.lock); |
146 | spinlock_unlock(&zones.lock); |
147 | } |
147 | } |
148 | 148 | ||
149 | /** |
149 | /** |
150 | * Try to find a zone where can we find the frame |
150 | * Try to find a zone where can we find the frame |
151 | * |
151 | * |
152 | * @param hint Start searching in zone 'hint' |
152 | * @param hint Start searching in zone 'hint' |
153 | * @param lock Lock zone if true |
153 | * @param lock Lock zone if true |
154 | * |
154 | * |
155 | * Assume interrupts disable |
155 | * Assume interrupts disable |
156 | */ |
156 | */ |
157 | static zone_t * find_zone_and_lock(pfn_t frame, int *pzone) |
157 | static zone_t * find_zone_and_lock(pfn_t frame, int *pzone) |
158 | { |
158 | { |
159 | int i; |
159 | int i; |
160 | int hint = pzone ? *pzone : 0; |
160 | int hint = pzone ? *pzone : 0; |
161 | zone_t *z; |
161 | zone_t *z; |
162 | 162 | ||
163 | spinlock_lock(&zones.lock); |
163 | spinlock_lock(&zones.lock); |
164 | 164 | ||
165 | if (hint >= zones.count || hint < 0) |
165 | if (hint >= zones.count || hint < 0) |
166 | hint = 0; |
166 | hint = 0; |
167 | 167 | ||
168 | i = hint; |
168 | i = hint; |
169 | do { |
169 | do { |
170 | z = zones.info[i]; |
170 | z = zones.info[i]; |
171 | spinlock_lock(&z->lock); |
171 | spinlock_lock(&z->lock); |
172 | if (z->base <= frame && z->base + z->count > frame) { |
172 | if (z->base <= frame && z->base + z->count > frame) { |
173 | spinlock_unlock(&zones.lock); /* Unlock the global lock */ |
173 | spinlock_unlock(&zones.lock); /* Unlock the global lock */ |
174 | if (pzone) |
174 | if (pzone) |
175 | *pzone = i; |
175 | *pzone = i; |
176 | return z; |
176 | return z; |
177 | } |
177 | } |
178 | spinlock_unlock(&z->lock); |
178 | spinlock_unlock(&z->lock); |
179 | 179 | ||
180 | i++; |
180 | i++; |
181 | if (i >= zones.count) |
181 | if (i >= zones.count) |
182 | i = 0; |
182 | i = 0; |
183 | } while(i != hint); |
183 | } while(i != hint); |
184 | 184 | ||
185 | spinlock_unlock(&zones.lock); |
185 | spinlock_unlock(&zones.lock); |
186 | return NULL; |
186 | return NULL; |
187 | } |
187 | } |
188 | 188 | ||
189 | /** |
189 | /** |
190 | * Find AND LOCK zone that can allocate order frames |
190 | * Find AND LOCK zone that can allocate order frames |
191 | * |
191 | * |
192 | * Assume interrupts are disabled!! |
192 | * Assume interrupts are disabled!! |
193 | * |
193 | * |
194 | * @param pzone Pointer to preferred zone or NULL, on return contains zone number |
194 | * @param pzone Pointer to preferred zone or NULL, on return contains zone number |
195 | */ |
195 | */ |
196 | static zone_t * find_free_zone_lock(__u8 order, int *pzone) |
196 | static zone_t * find_free_zone_lock(__u8 order, int *pzone) |
197 | { |
197 | { |
198 | int i; |
198 | int i; |
199 | zone_t *z; |
199 | zone_t *z; |
200 | int hint = pzone ? *pzone : 0; |
200 | int hint = pzone ? *pzone : 0; |
201 | 201 | ||
202 | spinlock_lock(&zones.lock); |
202 | spinlock_lock(&zones.lock); |
203 | if (hint >= zones.count) |
203 | if (hint >= zones.count) |
204 | hint = 0; |
204 | hint = 0; |
205 | i = hint; |
205 | i = hint; |
206 | do { |
206 | do { |
207 | z = zones.info[i]; |
207 | z = zones.info[i]; |
208 | 208 | ||
209 | spinlock_lock(&z->lock); |
209 | spinlock_lock(&z->lock); |
210 | 210 | ||
211 | /* Check if the zone has 2^order frames area available */ |
211 | /* Check if the zone has 2^order frames area available */ |
212 | if (buddy_system_can_alloc(z->buddy_system, order)) { |
212 | if (buddy_system_can_alloc(z->buddy_system, order)) { |
213 | spinlock_unlock(&zones.lock); |
213 | spinlock_unlock(&zones.lock); |
214 | if (pzone) |
214 | if (pzone) |
215 | *pzone = i; |
215 | *pzone = i; |
216 | return z; |
216 | return z; |
217 | } |
217 | } |
218 | spinlock_unlock(&z->lock); |
218 | spinlock_unlock(&z->lock); |
219 | if (++i >= zones.count) |
219 | if (++i >= zones.count) |
220 | i = 0; |
220 | i = 0; |
221 | } while(i != hint); |
221 | } while(i != hint); |
222 | spinlock_unlock(&zones.lock); |
222 | spinlock_unlock(&zones.lock); |
223 | return NULL; |
223 | return NULL; |
224 | } |
224 | } |
225 | 225 | ||
226 | /********************************************/ |
226 | /********************************************/ |
227 | /* Buddy system functions */ |
227 | /* Buddy system functions */ |
228 | 228 | ||
229 | /** Buddy system find_block implementation |
229 | /** Buddy system find_block implementation |
230 | * |
230 | * |
231 | * Find block that is parent of current list. |
231 | * Find block that is parent of current list. |
232 | * That means go to lower addresses, until such block is found |
232 | * That means go to lower addresses, until such block is found |
233 | * |
233 | * |
234 | * @param order - Order of parent must be different then this parameter!! |
234 | * @param order - Order of parent must be different then this parameter!! |
235 | */ |
235 | */ |
236 | static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, |
236 | static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, |
237 | __u8 order) |
237 | __u8 order) |
238 | { |
238 | { |
239 | frame_t * frame; |
239 | frame_t * frame; |
240 | zone_t * zone; |
240 | zone_t * zone; |
241 | index_t index; |
241 | index_t index; |
242 | 242 | ||
243 | frame = list_get_instance(child, frame_t, buddy_link); |
243 | frame = list_get_instance(child, frame_t, buddy_link); |
244 | zone = (zone_t *) b->data; |
244 | zone = (zone_t *) b->data; |
245 | 245 | ||
246 | index = frame_index(zone, frame); |
246 | index = frame_index(zone, frame); |
247 | do { |
247 | do { |
248 | if (zone->frames[index].buddy_order != order) { |
248 | if (zone->frames[index].buddy_order != order) { |
249 | return &zone->frames[index].buddy_link; |
249 | return &zone->frames[index].buddy_link; |
250 | } |
250 | } |
251 | } while(index-- > 0); |
251 | } while(index-- > 0); |
252 | return NULL; |
252 | return NULL; |
253 | } |
253 | } |
254 | 254 | ||
255 | 255 | ||
256 | 256 | ||
257 | /** Buddy system find_buddy implementation |
257 | /** Buddy system find_buddy implementation |
258 | * |
258 | * |
259 | * @param b Buddy system. |
259 | * @param b Buddy system. |
260 | * @param block Block for which buddy should be found |
260 | * @param block Block for which buddy should be found |
261 | * |
261 | * |
262 | * @return Buddy for given block if found |
262 | * @return Buddy for given block if found |
263 | */ |
263 | */ |
264 | static link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) |
264 | static link_t * zone_buddy_find_buddy(buddy_system_t *b, link_t * block) |
265 | { |
265 | { |
266 | frame_t * frame; |
266 | frame_t * frame; |
267 | zone_t * zone; |
267 | zone_t * zone; |
268 | index_t index; |
268 | index_t index; |
269 | bool is_left, is_right; |
269 | bool is_left, is_right; |
270 | 270 | ||
271 | frame = list_get_instance(block, frame_t, buddy_link); |
271 | frame = list_get_instance(block, frame_t, buddy_link); |
272 | zone = (zone_t *) b->data; |
272 | zone = (zone_t *) b->data; |
273 | ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), frame->buddy_order)); |
273 | ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), frame->buddy_order)); |
274 | 274 | ||
275 | is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
275 | is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); |
276 | is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); |
276 | is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); |
277 | 277 | ||
278 | ASSERT(is_left ^ is_right); |
278 | ASSERT(is_left ^ is_right); |
279 | if (is_left) { |
279 | if (is_left) { |
280 | index = (frame_index(zone, frame)) + (1 << frame->buddy_order); |
280 | index = (frame_index(zone, frame)) + (1 << frame->buddy_order); |
281 | } else { // if (is_right) |
281 | } else { // if (is_right) |
282 | index = (frame_index(zone, frame)) - (1 << frame->buddy_order); |
282 | index = (frame_index(zone, frame)) - (1 << frame->buddy_order); |
283 | } |
283 | } |
284 | 284 | ||
285 | 285 | ||
286 | if (frame_index_valid(zone, index)) { |
286 | if (frame_index_valid(zone, index)) { |
287 | if (zone->frames[index].buddy_order == frame->buddy_order && |
287 | if (zone->frames[index].buddy_order == frame->buddy_order && |
288 | zone->frames[index].refcount == 0) { |
288 | zone->frames[index].refcount == 0) { |
289 | return &zone->frames[index].buddy_link; |
289 | return &zone->frames[index].buddy_link; |
290 | } |
290 | } |
291 | } |
291 | } |
292 | 292 | ||
293 | return NULL; |
293 | return NULL; |
294 | } |
294 | } |
295 | 295 | ||
296 | /** Buddy system bisect implementation |
296 | /** Buddy system bisect implementation |
297 | * |
297 | * |
298 | * @param b Buddy system. |
298 | * @param b Buddy system. |
299 | * @param block Block to bisect |
299 | * @param block Block to bisect |
300 | * |
300 | * |
301 | * @return right block |
301 | * @return right block |
302 | */ |
302 | */ |
303 | static link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) { |
303 | static link_t * zone_buddy_bisect(buddy_system_t *b, link_t * block) { |
304 | frame_t * frame_l, * frame_r; |
304 | frame_t * frame_l, * frame_r; |
305 | 305 | ||
306 | frame_l = list_get_instance(block, frame_t, buddy_link); |
306 | frame_l = list_get_instance(block, frame_t, buddy_link); |
307 | frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
307 | frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); |
308 | 308 | ||
309 | return &frame_r->buddy_link; |
309 | return &frame_r->buddy_link; |
310 | } |
310 | } |
311 | 311 | ||
312 | /** Buddy system coalesce implementation |
312 | /** Buddy system coalesce implementation |
313 | * |
313 | * |
314 | * @param b Buddy system. |
314 | * @param b Buddy system. |
315 | * @param block_1 First block |
315 | * @param block_1 First block |
316 | * @param block_2 First block's buddy |
316 | * @param block_2 First block's buddy |
317 | * |
317 | * |
318 | * @return Coalesced block (actually block that represents lower address) |
318 | * @return Coalesced block (actually block that represents lower address) |
319 | */ |
319 | */ |
320 | static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, |
320 | static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, |
321 | link_t * block_2) { |
321 | link_t * block_2) { |
322 | frame_t *frame1, *frame2; |
322 | frame_t *frame1, *frame2; |
323 | 323 | ||
324 | frame1 = list_get_instance(block_1, frame_t, buddy_link); |
324 | frame1 = list_get_instance(block_1, frame_t, buddy_link); |
325 | frame2 = list_get_instance(block_2, frame_t, buddy_link); |
325 | frame2 = list_get_instance(block_2, frame_t, buddy_link); |
326 | 326 | ||
327 | return frame1 < frame2 ? block_1 : block_2; |
327 | return frame1 < frame2 ? block_1 : block_2; |
328 | } |
328 | } |
329 | 329 | ||
330 | /** Buddy system set_order implementation |
330 | /** Buddy system set_order implementation |
331 | * |
331 | * |
332 | * @param b Buddy system. |
332 | * @param b Buddy system. |
333 | * @param block Buddy system block |
333 | * @param block Buddy system block |
334 | * @param order Order to set |
334 | * @param order Order to set |
335 | */ |
335 | */ |
336 | static void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) { |
336 | static void zone_buddy_set_order(buddy_system_t *b, link_t * block, __u8 order) { |
337 | frame_t * frame; |
337 | frame_t * frame; |
338 | frame = list_get_instance(block, frame_t, buddy_link); |
338 | frame = list_get_instance(block, frame_t, buddy_link); |
339 | frame->buddy_order = order; |
339 | frame->buddy_order = order; |
340 | } |
340 | } |
341 | 341 | ||
342 | /** Buddy system get_order implementation |
342 | /** Buddy system get_order implementation |
343 | * |
343 | * |
344 | * @param b Buddy system. |
344 | * @param b Buddy system. |
345 | * @param block Buddy system block |
345 | * @param block Buddy system block |
346 | * |
346 | * |
347 | * @return Order of block |
347 | * @return Order of block |
348 | */ |
348 | */ |
349 | static __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) { |
349 | static __u8 zone_buddy_get_order(buddy_system_t *b, link_t * block) { |
350 | frame_t * frame; |
350 | frame_t * frame; |
351 | frame = list_get_instance(block, frame_t, buddy_link); |
351 | frame = list_get_instance(block, frame_t, buddy_link); |
352 | return frame->buddy_order; |
352 | return frame->buddy_order; |
353 | } |
353 | } |
354 | 354 | ||
355 | /** Buddy system mark_busy implementation |
355 | /** Buddy system mark_busy implementation |
356 | * |
356 | * |
357 | * @param b Buddy system |
357 | * @param b Buddy system |
358 | * @param block Buddy system block |
358 | * @param block Buddy system block |
359 | * |
359 | * |
360 | */ |
360 | */ |
361 | static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { |
361 | static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { |
362 | frame_t * frame; |
362 | frame_t * frame; |
363 | frame = list_get_instance(block, frame_t, buddy_link); |
363 | frame = list_get_instance(block, frame_t, buddy_link); |
364 | frame->refcount = 1; |
364 | frame->refcount = 1; |
365 | } |
365 | } |
366 | 366 | ||
367 | /** Buddy system mark_available implementation |
367 | /** Buddy system mark_available implementation |
368 | * |
368 | * |
369 | * @param b Buddy system |
369 | * @param b Buddy system |
370 | * @param block Buddy system block |
370 | * @param block Buddy system block |
371 | * |
371 | * |
372 | */ |
372 | */ |
373 | static void zone_buddy_mark_available(buddy_system_t *b, link_t * block) { |
373 | static void zone_buddy_mark_available(buddy_system_t *b, link_t * block) { |
374 | frame_t * frame; |
374 | frame_t * frame; |
375 | frame = list_get_instance(block, frame_t, buddy_link); |
375 | frame = list_get_instance(block, frame_t, buddy_link); |
376 | frame->refcount = 0; |
376 | frame->refcount = 0; |
377 | } |
377 | } |
378 | 378 | ||
379 | static struct buddy_system_operations zone_buddy_system_operations = { |
379 | static struct buddy_system_operations zone_buddy_system_operations = { |
380 | .find_buddy = zone_buddy_find_buddy, |
380 | .find_buddy = zone_buddy_find_buddy, |
381 | .bisect = zone_buddy_bisect, |
381 | .bisect = zone_buddy_bisect, |
382 | .coalesce = zone_buddy_coalesce, |
382 | .coalesce = zone_buddy_coalesce, |
383 | .set_order = zone_buddy_set_order, |
383 | .set_order = zone_buddy_set_order, |
384 | .get_order = zone_buddy_get_order, |
384 | .get_order = zone_buddy_get_order, |
385 | .mark_busy = zone_buddy_mark_busy, |
385 | .mark_busy = zone_buddy_mark_busy, |
386 | .mark_available = zone_buddy_mark_available, |
386 | .mark_available = zone_buddy_mark_available, |
387 | .find_block = zone_buddy_find_block |
387 | .find_block = zone_buddy_find_block |
388 | }; |
388 | }; |
389 | 389 | ||
390 | /*************************************/ |
390 | /*************************************/ |
391 | /* Zone functions */ |
391 | /* Zone functions */ |
392 | 392 | ||
393 | /** Allocate frame in particular zone |
393 | /** Allocate frame in particular zone |
394 | * |
394 | * |
395 | * Assume zone is locked |
395 | * Assume zone is locked |
396 | * |
396 | * |
397 | * @return Frame index in zone |
397 | * @return Frame index in zone |
398 | */ |
398 | */ |
399 | static pfn_t zone_frame_alloc(zone_t *zone,__u8 order, int flags, int *status) |
399 | static pfn_t zone_frame_alloc(zone_t *zone,__u8 order, int flags, int *status) |
400 | { |
400 | { |
401 | pfn_t v; |
401 | pfn_t v; |
402 | link_t *tmp; |
402 | link_t *tmp; |
403 | frame_t *frame; |
403 | frame_t *frame; |
404 | 404 | ||
405 | /* Allocate frames from zone buddy system */ |
405 | /* Allocate frames from zone buddy system */ |
406 | tmp = buddy_system_alloc(zone->buddy_system, order); |
406 | tmp = buddy_system_alloc(zone->buddy_system, order); |
407 | 407 | ||
408 | ASSERT(tmp); |
408 | ASSERT(tmp); |
409 | 409 | ||
410 | /* Update zone information. */ |
410 | /* Update zone information. */ |
411 | zone->free_count -= (1 << order); |
411 | zone->free_count -= (1 << order); |
412 | zone->busy_count += (1 << order); |
412 | zone->busy_count += (1 << order); |
413 | 413 | ||
414 | /* Frame will be actually a first frame of the block. */ |
414 | /* Frame will be actually a first frame of the block. */ |
415 | frame = list_get_instance(tmp, frame_t, buddy_link); |
415 | frame = list_get_instance(tmp, frame_t, buddy_link); |
416 | 416 | ||
417 | /* get frame address */ |
417 | /* get frame address */ |
418 | v = make_frame_index(zone, frame); |
418 | v = make_frame_index(zone, frame); |
419 | return v; |
419 | return v; |
420 | } |
420 | } |
421 | 421 | ||
422 | /** Free frame from zone |
422 | /** Free frame from zone |
423 | * |
423 | * |
424 | * Assume zone is locked |
424 | * Assume zone is locked |
425 | */ |
425 | */ |
426 | static void zone_frame_free(zone_t *zone, pfn_t frame_idx) |
426 | static void zone_frame_free(zone_t *zone, index_t frame_idx) |
427 | { |
427 | { |
428 | frame_t *frame; |
428 | frame_t *frame; |
429 | __u8 order; |
429 | __u8 order; |
430 | 430 | ||
431 | frame = &zone->frames[frame_idx]; |
431 | frame = &zone->frames[frame_idx]; |
432 | 432 | ||
433 | /* remember frame order */ |
433 | /* remember frame order */ |
434 | order = frame->buddy_order; |
434 | order = frame->buddy_order; |
435 | 435 | ||
436 | ASSERT(frame->refcount); |
436 | ASSERT(frame->refcount); |
437 | 437 | ||
438 | if (!--frame->refcount) { |
438 | if (!--frame->refcount) { |
439 | buddy_system_free(zone->buddy_system, &frame->buddy_link); |
439 | buddy_system_free(zone->buddy_system, &frame->buddy_link); |
440 | } |
440 | } |
441 | 441 | ||
442 | /* Update zone information. */ |
442 | /* Update zone information. */ |
443 | zone->free_count += (1 << order); |
443 | zone->free_count += (1 << order); |
444 | zone->busy_count -= (1 << order); |
444 | zone->busy_count -= (1 << order); |
445 | } |
445 | } |
446 | 446 | ||
447 | /** Return frame from zone */ |
447 | /** Return frame from zone */ |
448 | static frame_t * zone_get_frame(zone_t *zone, pfn_t frame_idx) |
448 | static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx) |
449 | { |
449 | { |
450 | ASSERT(frame_idx < zone->count); |
450 | ASSERT(frame_idx < zone->count); |
451 | return &zone->frames[frame_idx]; |
451 | return &zone->frames[frame_idx]; |
452 | } |
452 | } |
453 | 453 | ||
454 | /** Mark frame in zone unavailable to allocation */ |
454 | /** Mark frame in zone unavailable to allocation */ |
455 | static void zone_mark_unavailable(zone_t *zone, pfn_t frame_idx) |
455 | static void zone_mark_unavailable(zone_t *zone, index_t frame_idx) |
456 | { |
456 | { |
457 | frame_t *frame; |
457 | frame_t *frame; |
458 | link_t *link; |
458 | link_t *link; |
459 | 459 | ||
460 | frame = zone_get_frame(zone, frame_idx); |
460 | frame = zone_get_frame(zone, frame_idx); |
461 | link = buddy_system_alloc_block(zone->buddy_system, |
461 | link = buddy_system_alloc_block(zone->buddy_system, |
462 | &frame->buddy_link); |
462 | &frame->buddy_link); |
463 | ASSERT(link); |
463 | ASSERT(link); |
464 | zone->free_count--; |
464 | zone->free_count--; |
465 | } |
465 | } |
466 | 466 | ||
467 | /** Create frame zone |
467 | /** Create frame zone |
468 | * |
468 | * |
469 | * Create new frame zone. |
469 | * Create new frame zone. |
470 | * |
470 | * |
471 | * @param start Physical address of the first frame within the zone. |
471 | * @param start Physical address of the first frame within the zone. |
472 | * @param size Size of the zone. Must be a multiple of FRAME_SIZE. |
472 | * @param size Size of the zone. Must be a multiple of FRAME_SIZE. |
473 | * @param conffram Address of configuration frame |
473 | * @param conffram Address of configuration frame |
474 | * @param flags Zone flags. |
474 | * @param flags Zone flags. |
475 | * |
475 | * |
476 | * @return Initialized zone. |
476 | * @return Initialized zone. |
477 | */ |
477 | */ |
478 | static zone_t * zone_construct(pfn_t start, pfn_t count, |
478 | static zone_t * zone_construct(pfn_t start, count_t count, |
479 | zone_t *z, int flags) |
479 | zone_t *z, int flags) |
480 | { |
480 | { |
481 | int i; |
481 | int i; |
482 | __u8 max_order; |
482 | __u8 max_order; |
483 | 483 | ||
484 | spinlock_initialize(&z->lock, "zone_lock"); |
484 | spinlock_initialize(&z->lock, "zone_lock"); |
485 | z->base = start; |
485 | z->base = start; |
486 | z->count = count; |
486 | z->count = count; |
487 | z->flags = flags; |
487 | z->flags = flags; |
488 | z->free_count = count; |
488 | z->free_count = count; |
489 | z->busy_count = 0; |
489 | z->busy_count = 0; |
490 | 490 | ||
491 | /* |
491 | /* |
492 | * Compute order for buddy system, initialize |
492 | * Compute order for buddy system, initialize |
493 | */ |
493 | */ |
494 | for (max_order = 0; count >> max_order; max_order++) |
494 | for (max_order = 0; count >> max_order; max_order++) |
495 | ; |
495 | ; |
496 | z->buddy_system = (buddy_system_t *)&z[1]; |
496 | z->buddy_system = (buddy_system_t *)&z[1]; |
497 | 497 | ||
498 | buddy_system_create(z->buddy_system, max_order, |
498 | buddy_system_create(z->buddy_system, max_order, |
499 | &zone_buddy_system_operations, |
499 | &zone_buddy_system_operations, |
500 | (void *) z); |
500 | (void *) z); |
501 | 501 | ||
502 | /* Allocate frames _after_ the conframe */ |
502 | /* Allocate frames _after_ the conframe */ |
503 | /* Check sizes */ |
503 | /* Check sizes */ |
504 | z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); |
504 | z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); |
505 | 505 | ||
506 | for (i = 0; i<count; i++) { |
506 | for (i = 0; i<count; i++) { |
507 | frame_initialize(&z->frames[i]); |
507 | frame_initialize(&z->frames[i]); |
508 | } |
508 | } |
509 | /* Stuffing frames */ |
509 | /* Stuffing frames */ |
510 | for (i = 0; i < count; i++) { |
510 | for (i = 0; i < count; i++) { |
511 | z->frames[i].refcount = 0; |
511 | z->frames[i].refcount = 0; |
512 | buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); |
512 | buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); |
513 | } |
513 | } |
514 | return z; |
514 | return z; |
515 | } |
515 | } |
516 | 516 | ||
517 | 517 | ||
518 | /** Compute configuration data size for zone */ |
518 | /** Compute configuration data size for zone */ |
519 | __address zone_conf_size(pfn_t start, pfn_t count) |
519 | __address zone_conf_size(pfn_t start, count_t count) |
520 | { |
520 | { |
521 | int size = sizeof(zone_t) + count*sizeof(frame_t); |
521 | int size = sizeof(zone_t) + count*sizeof(frame_t); |
522 | int max_order; |
522 | int max_order; |
523 | 523 | ||
524 | for (max_order = 0; count >> max_order; max_order++) |
524 | for (max_order = 0; count >> max_order; max_order++) |
525 | ; |
525 | ; |
526 | size += buddy_conf_size(max_order); |
526 | size += buddy_conf_size(max_order); |
527 | return size; |
527 | return size; |
528 | } |
528 | } |
529 | 529 | ||
530 | /** Create and add zone to system |
530 | /** Create and add zone to system |
531 | * |
531 | * |
532 | * @param confframe Where configuration frame is supposed to be. |
532 | * @param confframe Where configuration frame is supposed to be. |
533 | * Always check, that we will not disturb kernel pages |
533 | * Always check, that we will not disturb the kernel and possibly init. |
534 | * the kernel and possibly init. |
- | |
535 | * If confframe is given _outside_ this zone, it is expected, |
534 | * If confframe is given _outside_ this zone, it is expected, |
536 | * that the area is already marked BUSY and big enough |
535 | * that the area is already marked BUSY and big enough |
537 | * to contain zone_conf_size() amount of data |
536 | * to contain zone_conf_size() amount of data |
538 | */ |
537 | */ |
539 | void zone_create(pfn_t start, pfn_t count, pfn_t confframe, int flags) |
538 | void zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
540 | { |
539 | { |
541 | zone_t *z; |
540 | zone_t *z; |
542 | __address addr,endaddr; |
541 | __address addr,endaddr; |
543 | pfn_t confcount; |
542 | count_t confcount; |
544 | int i; |
543 | int i; |
545 | 544 | ||
546 | /* Theoretically we could have here 0, practically make sure |
545 | /* Theoretically we could have here 0, practically make sure |
547 | * nobody tries to do that. If some platform requires, remove |
546 | * nobody tries to do that. If some platform requires, remove |
548 | * the assert |
547 | * the assert |
549 | */ |
548 | */ |
550 | ASSERT(confframe); |
549 | ASSERT(confframe); |
551 | /* If conframe is supposed to be inside our zone, then make sure |
550 | /* If conframe is supposed to be inside our zone, then make sure |
552 | * it does not span kernel & init |
551 | * it does not span kernel & init |
553 | */ |
552 | */ |
554 | confcount = SIZE2PFN(zone_conf_size(start,count)); |
553 | confcount = SIZE2FRAMES(zone_conf_size(start,count)); |
555 | if (confframe >= start && confframe < start+count) { |
554 | if (confframe >= start && confframe < start+count) { |
556 | for (;confframe < start+count;confframe++) { |
555 | for (;confframe < start+count;confframe++) { |
557 | addr = PFN2ADDR(confframe); |
556 | addr = PFN2ADDR(confframe); |
558 | endaddr = PFN2ADDR (confframe + confcount); |
557 | endaddr = PFN2ADDR (confframe + confcount); |
559 | if (overlaps(addr, endaddr, KA2PA(config.base), |
558 | if (overlaps(addr, endaddr, KA2PA(config.base), |
560 | KA2PA(config.base+config.kernel_size))) |
559 | KA2PA(config.base+config.kernel_size))) |
561 | continue; |
560 | continue; |
562 | if (config.init_addr) |
561 | if (config.init_addr) |
563 | if (overlaps(addr,endaddr, |
562 | if (overlaps(addr,endaddr, |
564 | KA2PA(config.init_addr), |
563 | KA2PA(config.init_addr), |
565 | KA2PA(config.init_addr+config.init_size))) |
564 | KA2PA(config.init_addr+config.init_size))) |
566 | continue; |
565 | continue; |
567 | break; |
566 | break; |
568 | } |
567 | } |
569 | if (confframe >= start+count) |
568 | if (confframe >= start+count) |
570 | panic("Cannot find configuration data for zone."); |
569 | panic("Cannot find configuration data for zone."); |
571 | } |
570 | } |
572 | 571 | ||
573 | z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags); |
572 | z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags); |
574 | zones_add_zone(z); |
573 | zones_add_zone(z); |
575 | 574 | ||
576 | /* If confdata in zone, mark as unavailable */ |
575 | /* If confdata in zone, mark as unavailable */ |
577 | if (confframe >= start && confframe < start+count) |
576 | if (confframe >= start && confframe < start+count) |
578 | for (i=confframe; i<confframe+confcount; i++) { |
577 | for (i=confframe; i<confframe+confcount; i++) { |
579 | zone_mark_unavailable(z, i - z->base); |
578 | zone_mark_unavailable(z, i - z->base); |
580 | } |
579 | } |
581 | } |
580 | } |
582 | 581 | ||
583 | /***************************************/ |
582 | /***************************************/ |
584 | /* Frame functions */ |
583 | /* Frame functions */ |
585 | 584 | ||
586 | /** Set parent of frame */ |
585 | /** Set parent of frame */ |
587 | void frame_set_parent(pfn_t pfn, void *data, int hint) |
586 | void frame_set_parent(pfn_t pfn, void *data, int hint) |
588 | { |
587 | { |
589 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
588 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
590 | 589 | ||
591 | ASSERT(zone); |
590 | ASSERT(zone); |
592 | 591 | ||
593 | zone_get_frame(zone, pfn-zone->base)->parent = data; |
592 | zone_get_frame(zone, pfn-zone->base)->parent = data; |
594 | spinlock_unlock(&zone->lock); |
593 | spinlock_unlock(&zone->lock); |
595 | } |
594 | } |
596 | 595 | ||
597 | void * frame_get_parent(pfn_t pfn, int hint) |
596 | void * frame_get_parent(pfn_t pfn, int hint) |
598 | { |
597 | { |
599 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
598 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
600 | void *res; |
599 | void *res; |
601 | 600 | ||
602 | ASSERT(zone); |
601 | ASSERT(zone); |
603 | res = zone_get_frame(zone, pfn - zone->base)->parent; |
602 | res = zone_get_frame(zone, pfn - zone->base)->parent; |
604 | 603 | ||
605 | spinlock_unlock(&zone->lock); |
604 | spinlock_unlock(&zone->lock); |
606 | return res; |
605 | return res; |
607 | } |
606 | } |
608 | 607 | ||
609 | /** Allocate power-of-two frames of physical memory. |
608 | /** Allocate power-of-two frames of physical memory. |
610 | * |
609 | * |
611 | * @param flags Flags for host zone selection and address processing. |
610 | * @param flags Flags for host zone selection and address processing. |
612 | * @param order Allocate exactly 2^order frames. |
611 | * @param order Allocate exactly 2^order frames. |
613 | * @param pzone Preferred zone |
612 | * @param pzone Preferred zone |
614 | * |
613 | * |
615 | * @return Allocated frame. |
614 | * @return Allocated frame. |
616 | */ |
615 | */ |
617 | pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone) |
616 | pfn_t frame_alloc_generic(__u8 order, int flags, int * status, int *pzone) |
618 | { |
617 | { |
619 | ipl_t ipl; |
618 | ipl_t ipl; |
620 | int freed; |
619 | int freed; |
621 | pfn_t v; |
620 | pfn_t v; |
622 | zone_t *zone; |
621 | zone_t *zone; |
623 | 622 | ||
624 | loop: |
623 | loop: |
625 | ipl = interrupts_disable(); |
624 | ipl = interrupts_disable(); |
626 | /* |
625 | /* |
627 | * First, find suitable frame zone. |
626 | * First, find suitable frame zone. |
628 | */ |
627 | */ |
629 | zone = find_free_zone_lock(order,pzone); |
628 | zone = find_free_zone_lock(order,pzone); |
630 | /* If no memory, reclaim some slab memory, |
629 | /* If no memory, reclaim some slab memory, |
631 | if it does not help, reclaim all */ |
630 | if it does not help, reclaim all */ |
632 | if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
631 | if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
633 | freed = slab_reclaim(0); |
632 | freed = slab_reclaim(0); |
634 | if (freed) |
633 | if (freed) |
635 | zone = find_free_zone_lock(order,pzone); |
634 | zone = find_free_zone_lock(order,pzone); |
636 | if (!zone) { |
635 | if (!zone) { |
637 | freed = slab_reclaim(SLAB_RECLAIM_ALL); |
636 | freed = slab_reclaim(SLAB_RECLAIM_ALL); |
638 | if (freed) |
637 | if (freed) |
639 | zone = find_free_zone_lock(order,pzone); |
638 | zone = find_free_zone_lock(order,pzone); |
640 | } |
639 | } |
641 | } |
640 | } |
642 | if (!zone) { |
641 | if (!zone) { |
643 | if (flags & FRAME_PANIC) |
642 | if (flags & FRAME_PANIC) |
644 | panic("Can't allocate frame.\n"); |
643 | panic("Can't allocate frame.\n"); |
645 | 644 | ||
646 | /* |
645 | /* |
647 | * TODO: Sleep until frames are available again. |
646 | * TODO: Sleep until frames are available again. |
648 | */ |
647 | */ |
649 | interrupts_restore(ipl); |
648 | interrupts_restore(ipl); |
650 | 649 | ||
651 | if (flags & FRAME_ATOMIC) { |
650 | if (flags & FRAME_ATOMIC) { |
652 | ASSERT(status != NULL); |
651 | ASSERT(status != NULL); |
653 | if (status) |
652 | if (status) |
654 | *status = FRAME_NO_MEMORY; |
653 | *status = FRAME_NO_MEMORY; |
655 | return NULL; |
654 | return NULL; |
656 | } |
655 | } |
657 | 656 | ||
658 | panic("Sleep not implemented.\n"); |
657 | panic("Sleep not implemented.\n"); |
659 | goto loop; |
658 | goto loop; |
660 | } |
659 | } |
661 | v = zone_frame_alloc(zone,order,flags,status); |
660 | v = zone_frame_alloc(zone,order,flags,status); |
662 | v += zone->base; |
661 | v += zone->base; |
663 | 662 | ||
664 | spinlock_unlock(&zone->lock); |
663 | spinlock_unlock(&zone->lock); |
665 | interrupts_restore(ipl); |
664 | interrupts_restore(ipl); |
666 | 665 | ||
667 | if (status) |
666 | if (status) |
668 | *status = FRAME_OK; |
667 | *status = FRAME_OK; |
669 | return v; |
668 | return v; |
670 | } |
669 | } |
671 | 670 | ||
672 | /** Free a frame. |
671 | /** Free a frame. |
673 | * |
672 | * |
674 | * Find respective frame structrue for supplied addr. |
673 | * Find respective frame structrue for supplied addr. |
675 | * Decrement frame reference count. |
674 | * Decrement frame reference count. |
676 | * If it drops to zero, move the frame structure to free list. |
675 | * If it drops to zero, move the frame structure to free list. |
677 | * |
676 | * |
678 | * @param frame Frame no to be freed. |
677 | * @param frame Frame no to be freed. |
679 | */ |
678 | */ |
680 | void frame_free(pfn_t pfn) |
679 | void frame_free(pfn_t pfn) |
681 | { |
680 | { |
682 | ipl_t ipl; |
681 | ipl_t ipl; |
683 | zone_t *zone; |
682 | zone_t *zone; |
684 | 683 | ||
685 | ipl = interrupts_disable(); |
684 | ipl = interrupts_disable(); |
686 | 685 | ||
687 | /* |
686 | /* |
688 | * First, find host frame zone for addr. |
687 | * First, find host frame zone for addr. |
689 | */ |
688 | */ |
690 | zone = find_zone_and_lock(pfn,NULL); |
689 | zone = find_zone_and_lock(pfn,NULL); |
691 | ASSERT(zone); |
690 | ASSERT(zone); |
692 | 691 | ||
693 | zone_frame_free(zone, pfn-zone->base); |
692 | zone_frame_free(zone, pfn-zone->base); |
694 | 693 | ||
695 | spinlock_unlock(&zone->lock); |
694 | spinlock_unlock(&zone->lock); |
696 | interrupts_restore(ipl); |
695 | interrupts_restore(ipl); |
697 | } |
696 | } |
698 | 697 | ||
699 | 698 | ||
700 | 699 | ||
701 | /** Mark given range unavailable in frame zones */ |
700 | /** Mark given range unavailable in frame zones */ |
702 | void frame_mark_unavailable(pfn_t start, pfn_t count) |
701 | void frame_mark_unavailable(pfn_t start, count_t count) |
703 | { |
702 | { |
704 | int i; |
703 | int i; |
705 | zone_t *zone; |
704 | zone_t *zone; |
706 | int prefzone = 0; |
705 | int prefzone = 0; |
707 | 706 | ||
708 | for (i=0; i<count; i++) { |
707 | for (i=0; i<count; i++) { |
709 | zone = find_zone_and_lock(start+i,&prefzone); |
708 | zone = find_zone_and_lock(start+i,&prefzone); |
710 | if (!zone) /* PFN not found */ |
709 | if (!zone) /* PFN not found */ |
711 | continue; |
710 | continue; |
712 | zone_mark_unavailable(zone, start+i-zone->base); |
711 | zone_mark_unavailable(zone, start+i-zone->base); |
713 | 712 | ||
714 | spinlock_unlock(&zone->lock); |
713 | spinlock_unlock(&zone->lock); |
715 | } |
714 | } |
716 | } |
715 | } |
717 | 716 | ||
718 | /** Initialize physical memory management |
717 | /** Initialize physical memory management |
719 | * |
718 | * |
720 | * Initialize physical memory managemnt. |
719 | * Initialize physical memory managemnt. |
721 | */ |
720 | */ |
722 | void frame_init(void) |
721 | void frame_init(void) |
723 | { |
722 | { |
724 | if (config.cpu_active == 1) { |
723 | if (config.cpu_active == 1) { |
725 | zones.count = 0; |
724 | zones.count = 0; |
726 | spinlock_initialize(&zones.lock,"zones_glob_lock"); |
725 | spinlock_initialize(&zones.lock,"zones_glob_lock"); |
727 | } |
726 | } |
728 | /* Tell the architecture to create some memory */ |
727 | /* Tell the architecture to create some memory */ |
729 | frame_arch_init(); |
728 | frame_arch_init(); |
730 | if (config.cpu_active == 1) { |
729 | if (config.cpu_active == 1) { |
731 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), |
730 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), |
732 | SIZE2PFN(config.kernel_size)); |
731 | SIZE2FRAMES(config.kernel_size)); |
733 | if (config.init_size > 0) |
732 | if (config.init_size > 0) |
734 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.init_addr)), |
733 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.init_addr)), |
735 | SIZE2PFN(config.init_size)); |
734 | SIZE2FRAMES(config.init_size)); |
736 | } |
735 | } |
737 | } |
736 | } |
738 | 737 | ||
739 | 738 | ||
740 | 739 | ||
741 | /** Prints list of zones |
740 | /** Prints list of zones |
742 | * |
741 | * |
743 | */ |
742 | */ |
744 | void zone_print_list(void) { |
743 | void zone_print_list(void) { |
745 | zone_t *zone = NULL; |
744 | zone_t *zone = NULL; |
746 | int i; |
745 | int i; |
747 | ipl_t ipl; |
746 | ipl_t ipl; |
748 | 747 | ||
749 | ipl = interrupts_disable(); |
748 | ipl = interrupts_disable(); |
750 | spinlock_lock(&zones.lock); |
749 | spinlock_lock(&zones.lock); |
751 | printf("Base address\tFree Frames\tBusy Frames\n"); |
750 | printf("Base address\tFree Frames\tBusy Frames\n"); |
752 | printf("------------\t-----------\t-----------\n"); |
751 | printf("------------\t-----------\t-----------\n"); |
753 | for (i=0;i<zones.count;i++) { |
752 | for (i=0;i<zones.count;i++) { |
754 | zone = zones.info[i]; |
753 | zone = zones.info[i]; |
755 | spinlock_lock(&zone->lock); |
754 | spinlock_lock(&zone->lock); |
756 | printf("%L\t%d\t\t%d\n",PFN2ADDR(zone->base), |
755 | printf("%L\t%d\t\t%d\n",PFN2ADDR(zone->base), |
757 | zone->free_count, zone->busy_count); |
756 | zone->free_count, zone->busy_count); |
758 | spinlock_unlock(&zone->lock); |
757 | spinlock_unlock(&zone->lock); |
759 | } |
758 | } |
760 | spinlock_unlock(&zones.lock); |
759 | spinlock_unlock(&zones.lock); |
761 | interrupts_restore(ipl); |
760 | interrupts_restore(ipl); |
762 | } |
761 | } |
763 | 762 | ||
764 | /** Prints zone details |
763 | /** Prints zone details |
765 | * |
764 | * |
766 | * @param base Zone base address |
765 | * @param base Zone base address |
767 | */ |
766 | */ |
768 | void zone_print_one(int znum) { |
767 | void zone_print_one(int znum) { |
769 | zone_t *zone = NULL; |
768 | zone_t *zone = NULL; |
770 | ipl_t ipl; |
769 | ipl_t ipl; |
771 | 770 | ||
772 | ipl = interrupts_disable(); |
771 | ipl = interrupts_disable(); |
773 | spinlock_lock(&zones.lock); |
772 | spinlock_lock(&zones.lock); |
774 | 773 | ||
775 | if (znum >= zones.count || znum < 0) { |
774 | if (znum >= zones.count || znum < 0) { |
776 | printf("Zone number out of bounds.\n"); |
775 | printf("Zone number out of bounds.\n"); |
777 | spinlock_unlock(&zones.lock); |
776 | spinlock_unlock(&zones.lock); |
778 | interrupts_restore(ipl); |
777 | interrupts_restore(ipl); |
779 | return; |
778 | return; |
780 | } |
779 | } |
781 | 780 | ||
782 | zone = zones.info[znum]; |
781 | zone = zones.info[znum]; |
783 | 782 | ||
784 | spinlock_lock(&zone->lock); |
783 | spinlock_lock(&zone->lock); |
785 | printf("Memory zone information\n\n"); |
784 | printf("Memory zone information\n\n"); |
786 | printf("Zone base address: %P\n", PFN2ADDR(zone->base)); |
785 | printf("Zone base address: %P\n", PFN2ADDR(zone->base)); |
787 | printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10); |
786 | printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10); |
788 | printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10); |
787 | printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10); |
789 | printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10); |
788 | printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10); |
790 | 789 | ||
791 | printf("\nBuddy allocator structures:\n\n"); |
790 | printf("\nBuddy allocator structures:\n\n"); |
792 | buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
791 | buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
793 | 792 | ||
794 | spinlock_unlock(&zone->lock); |
793 | spinlock_unlock(&zone->lock); |
795 | spinlock_unlock(&zones.lock); |
794 | spinlock_unlock(&zones.lock); |
796 | interrupts_restore(ipl); |
795 | interrupts_restore(ipl); |
797 | } |
796 | } |
798 | 797 | ||
799 | 798 |