Changeset 5f0f29ce in mainline
- Timestamp:
- 2009-02-26T23:34:27Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e49e234
- Parents:
- 6b1de7a
- Location:
- kernel
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/mm/frame.c
r6b1de7a r5f0f29ce 58 58 pfn_t start, conf; 59 59 size_t size; 60 60 61 61 for (i = 0; i < e820counter; i++) { 62 62 if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) { -
kernel/arch/ia32/src/smp/smp.c
r6b1de7a r5f0f29ce 155 155 * Prepare new GDT for CPU in question. 156 156 */ 157 158 /* XXX Flag FRAME_LOW_4_GiB was removed temporarily, 159 * it needs to be replaced by a generic fuctionality of 160 * the memory subsystem 161 */ 157 162 gdt_new = (struct descriptor *) malloc(GDT_ITEMS * 158 sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);163 sizeof(struct descriptor), FRAME_ATOMIC); 159 164 if (!gdt_new) 160 165 panic("Cannot allocate memory for GDT."); -
kernel/generic/include/mm/buddy.h
r6b1de7a r5f0f29ce 83 83 extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t); 84 84 extern void buddy_system_free(buddy_system_t *, link_t *); 85 extern size_t buddy_conf_size( int);85 extern size_t buddy_conf_size(size_t); 86 86 extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *); 87 87 -
kernel/generic/include/mm/frame.h
r6b1de7a r5f0f29ce 39 39 #include <arch/types.h> 40 40 #include <adt/list.h> 41 #include <synch/spinlock.h>42 41 #include <mm/buddy.h> 43 42 #include <arch/mm/page.h> 44 43 #include <arch/mm/frame.h> 45 44 46 #define ONE_FRAME 47 #define TWO_FRAMES 48 #define FOUR_FRAMES 45 #define ONE_FRAME 0 46 #define TWO_FRAMES 1 47 #define FOUR_FRAMES 2 49 48 50 49 51 50 #ifdef ARCH_STACK_FRAMES 52 #define STACK_FRAMESARCH_STACK_FRAMES51 #define STACK_FRAMES ARCH_STACK_FRAMES 53 52 #else 54 #define STACK_FRAMESONE_FRAME53 #define STACK_FRAMES ONE_FRAME 55 54 #endif 56 55 57 /** Maximum number of zones in system. */58 #define ZONES_MAX 1656 /** Maximum number of zones in the system. */ 57 #define ZONES_MAX 32 59 58 60 /** Convert the frame address to kernel va. */ 61 #define FRAME_KA 0x1 59 typedef uint8_t frame_flags_t; 60 61 /** Convert the frame address to kernel VA. */ 62 #define FRAME_KA 0x01 62 63 /** Do not panic and do not sleep on failure. */ 63 #define FRAME_ATOMIC 0x264 #define FRAME_ATOMIC 0x02 64 65 /** Do not start reclaiming when no free memory. */ 65 #define FRAME_NO_RECLAIM 0x4 66 /** Do not allocate above 4 GiB. */ 67 #define FRAME_LOW_4_GiB 0x8 66 #define FRAME_NO_RECLAIM 0x04 67 68 typedef uint8_t zone_flags_t; 69 70 /** Zone is reserved (not available for allocation) */ 71 #define ZONE_RESERVED 0x08 72 /** Zone is used by firmware (not available for allocation) */ 73 #define ZONE_FIRMWARE 0x10 74 75 /** Currently there is no equivalent zone flags 76 for frame flags */ 77 #define FRAME_TO_ZONE_FLAGS(frame_flags) 0 68 78 69 79 static inline uintptr_t PFN2ADDR(pfn_t frame) … … 89 99 } 90 100 91 #define IS_BUDDY_ORDER_OK(index, order) 101 #define IS_BUDDY_ORDER_OK(index, order) \ 92 102 ((~(((unative_t) -1) << (order)) & (index)) == 0) 93 #define IS_BUDDY_LEFT_BLOCK(zone, frame) 94 (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x 1) == 0)95 #define IS_BUDDY_RIGHT_BLOCK(zone, frame) 96 (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x 1) == 1)97 #define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) 98 (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x 1) == 0)99 #define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) 100 (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x 1) == 1)103 #define IS_BUDDY_LEFT_BLOCK(zone, frame) \ 104 (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0) 105 #define IS_BUDDY_RIGHT_BLOCK(zone, frame) \ 106 (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1) 107 #define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \ 108 (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0) 109 #define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \ 110 (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1) 101 111 102 #define frame_alloc(order, flags) 112 #define frame_alloc(order, flags) \ 103 113 frame_alloc_generic(order, flags, NULL) 104 114 105 115 extern void frame_init(void); 106 extern void *frame_alloc_generic(uint8_t, int, unsigned int *);116 extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *); 107 117 extern void frame_free(uintptr_t); 108 118 extern void frame_reference_add(pfn_t); 109 119 110 extern int zone_create(pfn_t, count_t, pfn_t, int);111 extern void *frame_get_parent(pfn_t, unsigned int);112 extern void frame_set_parent(pfn_t, void *, unsigned int);120 extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t); 121 extern void *frame_get_parent(pfn_t, count_t); 122 extern void frame_set_parent(pfn_t, void *, count_t); 113 123 extern void frame_mark_unavailable(pfn_t, count_t); 114 124 extern uintptr_t zone_conf_size(count_t); 115 extern void zone_merge(unsigned int, unsigned int);125 extern bool zone_merge(count_t, count_t); 116 126 extern void zone_merge_all(void); 117 127 extern uint64_t zone_total_size(void); … … 121 131 */ 122 132 extern void zone_print_list(void); 123 extern void zone_print_one( unsigned int);133 extern void zone_print_one(count_t); 124 134 125 135 #endif -
kernel/generic/include/mm/slab.h
r6b1de7a r5f0f29ce 60 60 61 61 /** Reclaim all possible memory, because we are in memory stress */ 62 #define SLAB_RECLAIM_ALL 0x 162 #define SLAB_RECLAIM_ALL 0x01 63 63 64 64 /* cache_create flags */ -
kernel/generic/src/mm/buddy.c
r6b1de7a r5f0f29ce 47 47 48 48 /** Return size needed for the buddy configuration data. */ 49 size_t buddy_conf_size( int max_order)49 size_t buddy_conf_size(size_t max_order) 50 50 { 51 51 return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t); -
kernel/generic/src/mm/frame.c
r6b1de7a r5f0f29ce 2 2 * Copyright (c) 2001-2005 Jakub Jermar 3 3 * Copyright (c) 2005 Sergey Bondari 4 * Copyright (c) 2009 Martin Decky 4 5 * All rights reserved. 5 6 * … … 34 35 /** 35 36 * @file 36 * @brief 37 * @brief Physical frame allocator. 37 38 * 38 39 * This file contains the physical frame allocator and memory zone management. … … 40 41 * 41 42 * @see buddy.c 42 */43 44 /*45 * Locking order46 *47 * In order to access particular zone, the process must first lock48 * the zones.lock, then lock the zone and then unlock the zones.lock.49 * This insures, that we can fiddle with the zones in runtime without50 * affecting the processes.51 *52 43 */ 53 44 … … 71 62 72 63 typedef struct { 73 count_t refcount; /**< tracking of shared frames*/74 uint8_t buddy_order; /**< buddy system block order */75 link_t buddy_link; /**< link to the next free block inside one76 77 void *parent; 64 count_t refcount; /**< Tracking of shared frames */ 65 uint8_t buddy_order; /**< Buddy system block order */ 66 link_t buddy_link; /**< Link to the next free block inside 67 one order */ 68 void *parent; /**< If allocated by slab, this points there */ 78 69 } frame_t; 79 70 80 71 typedef struct { 81 SPINLOCK_DECLARE(lock); /**< this lock protects everything below */82 pfn_t base; /**< frame_no of the first frame in the frames 83 array*/84 count_t count; /**< Size of zone */85 86 frame_t *frames; /**< array of frame_t structures in this87 zone*/88 count_t free_count; /**< number of free frame_t structures*/89 count_t busy_count; /**< number of busy frame_t structures */90 91 buddy_system_t *buddy_system; /**< buddy system for thezone */92 int flags;72 pfn_t base; /**< Frame_no of the first frame 73 in the frames array */ 74 count_t count; /**< Size of zone */ 75 count_t free_count; /**< Number of free frame_t 76 structures */ 77 count_t busy_count; /**< Number of busy frame_t 78 structures */ 79 zone_flags_t flags; /**< Type of the zone */ 80 81 frame_t *frames; /**< Array of frame_t structures 82 in this zone */ 83 buddy_system_t *buddy_system; /**< Buddy system for the zone */ 93 84 } zone_t; 94 85 … … 97 88 * Some of the attributes in zone_t structures are 'read-only' 98 89 */ 99 100 90 typedef struct { 101 91 SPINLOCK_DECLARE(lock); 102 unsigned int count;103 zone_t *info[ZONES_MAX];92 count_t count; 93 zone_t info[ZONES_MAX]; 104 94 } zones_t; 105 95 … … 112 102 mutex_t mem_avail_mtx; 113 103 condvar_t mem_avail_cv; 114 unsigned long mem_avail_frames = 0; /**< Number of available frames. */115 unsigned long mem_avail_gen = 0;/**< Generation counter. */104 count_t mem_avail_req = 0; /**< Number of frames requested. */ 105 count_t mem_avail_gen = 0; /**< Generation counter. */ 116 106 117 107 /********************/ … … 129 119 } 130 120 131 static inline intframe_index_valid(zone_t *zone, index_t index)121 static inline bool frame_index_valid(zone_t *zone, index_t index) 132 122 { 133 123 return (index < zone->count); 134 124 } 135 125 136 /** Compute pfn_t from frame_t pointer & zone pointer */ 137 static index_t make_frame_index(zone_t *zone, frame_t *frame) 126 static inline index_t make_frame_index(zone_t *zone, frame_t *frame) 138 127 { 139 128 return (frame - zone->frames); 140 129 } 141 130 131 static inline bool zone_flags_available(zone_flags_t flags) 132 { 133 return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0); 134 } 135 142 136 /** Initialize frame structure. 143 137 * 144 * @param frame Frame structure to be initialized. 138 * @param frame Frame structure to be initialized. 139 * 145 140 */ 146 141 static void frame_initialize(frame_t *frame) … … 150 145 } 151 146 152 /******************* ***/153 /* Zone infofunctions */154 /******************* ***/147 /*******************/ 148 /* Zones functions */ 149 /*******************/ 155 150 156 151 /** Insert-sort zone into zones list. 157 152 * 158 * @param newzone New zone to be inserted into zone list. 159 * @return Zone number on success, -1 on error. 160 */ 161 static int zones_add_zone(zone_t *newzone) 162 { 163 unsigned int i, j; 164 ipl_t ipl; 165 zone_t *z; 166 167 ipl = interrupts_disable(); 168 spinlock_lock(&zones.lock); 169 170 /* Try to merge */ 153 * Assume interrupts are disabled and zones lock is 154 * locked. 155 * 156 * @param base Base frame of the newly inserted zone. 157 * @param count Number of frames of the newly inserted zone. 158 * 159 * @return Zone number on success, -1 on error. 160 * 161 */ 162 static count_t zones_insert_zone(pfn_t base, count_t count) 163 { 171 164 if (zones.count + 1 == ZONES_MAX) { 172 165 printf("Maximum zone count %u exceeded!\n", ZONES_MAX); 173 spinlock_unlock(&zones.lock); 174 interrupts_restore(ipl); 175 return -1; 176 } 177 166 return (count_t) -1; 167 } 168 169 count_t i; 178 170 for (i = 0; i < zones.count; i++) { 179 /* Check for overflow */ 180 z = zones.info[i]; 181 if (overlaps(newzone->base, newzone->count, z->base, 182 z->count)) { 171 /* Check for overlap */ 172 if (overlaps(base, count, 173 zones.info[i].base, zones.info[i].count)) { 183 174 printf("Zones overlap!\n"); 184 return -1;175 return (count_t) -1; 185 176 } 186 if ( newzone->base < z->base)177 if (base < zones.info[i].base) 187 178 break; 188 179 } 189 180 190 181 /* Move other zones up */ 182 count_t j; 191 183 for (j = i; j < zones.count; j++) 192 184 zones.info[j + 1] = zones.info[j]; 193 185 194 zones.info[i] = newzone;195 186 zones.count++; 196 187 197 spinlock_unlock(&zones.lock);198 interrupts_restore(ipl);199 200 188 return i; 201 189 } 202 190 203 /** Try to find a zone where can we find the frame. 204 * 205 * Assume interrupts are disabled. 206 * 207 * @param frame Frame number contained in zone. 208 * @param pzone If not null, it is used as zone hint. Zone index is 209 * filled into the variable on success. 210 * @return Pointer to locked zone containing frame. 211 */ 212 static zone_t *find_zone_and_lock(pfn_t frame, unsigned int *pzone) 213 { 214 unsigned int i; 215 unsigned int hint = pzone ? *pzone : 0; 216 zone_t *z; 217 218 spinlock_lock(&zones.lock); 219 191 /** Get total available frames. 192 * 193 * Assume interrupts are disabled and zones lock is 194 * locked. 195 * 196 * @return Total number of available frames. 197 * 198 */ 199 static count_t total_frames_free(void) 200 { 201 count_t total = 0; 202 count_t i; 203 for (i = 0; i < zones.count; i++) 204 total += zones.info[i].free_count; 205 206 return total; 207 } 208 209 /** Find a zone with a given frame. 210 * 211 * Assume interrupts are disabled and zones lock is 212 * locked. 213 * 214 * @param frame Frame number contained in zone. 215 * @param hint Used as zone hint. 216 * 217 * @return Zone index or -1 if not found. 218 * 219 */ 220 static count_t find_zone(pfn_t frame, count_t hint) 221 { 220 222 if (hint >= zones.count) 221 223 hint = 0; 222 224 223 i = hint;225 count_t i = hint; 224 226 do { 225 z = zones.info[i]; 226 spinlock_lock(&z->lock); 227 if (z->base <= frame && z->base + z->count > frame) { 228 /* Unlock the global lock */ 229 spinlock_unlock(&zones.lock); 230 if (pzone) 231 *pzone = i; 232 return z; 233 } 234 spinlock_unlock(&z->lock); 235 227 if ((zones.info[i].base <= frame) 228 && (zones.info[i].base + zones.info[i].count > frame)) 229 return i; 230 236 231 i++; 237 232 if (i >= zones.count) 238 233 i = 0; 239 234 } while (i != hint); 240 241 spinlock_unlock(&zones.lock); 242 return NULL; 235 236 return (count_t) -1; 243 237 } 244 238 245 239 /** @return True if zone can allocate specified order */ 246 static int zone_can_alloc(zone_t *z, uint8_t order) 247 { 248 return buddy_system_can_alloc(z->buddy_system, order); 249 } 250 251 /** Find and lock zone that can allocate order frames. 252 * 253 * Assume interrupts are disabled. 254 * 255 * @param order Size (2^order) of free space we are trying to find. 256 * @param flags Required flags of the target zone. 257 * @param pzone Pointer to preferred zone or NULL, on return contains 258 * zone number. 259 */ 260 static zone_t * 261 find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone) 262 { 263 unsigned int i; 264 zone_t *z; 265 unsigned int hint = pzone ? *pzone : 0; 266 267 /* Mask off flags that are not applicable. */ 268 flags &= FRAME_LOW_4_GiB; 269 270 spinlock_lock(&zones.lock); 240 static bool zone_can_alloc(zone_t *zone, uint8_t order) 241 { 242 return (zone_flags_available(zone->flags) 243 && buddy_system_can_alloc(zone->buddy_system, order)); 244 } 245 246 /** Find a zone that can allocate order frames. 247 * 248 * Assume interrupts are disabled and zones lock is 249 * locked. 250 * 251 * @param order Size (2^order) of free space we are trying to find. 252 * @param flags Required flags of the target zone. 253 * @param hind Preferred zone. 254 * 255 */ 256 static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint) 257 { 271 258 if (hint >= zones.count) 272 259 hint = 0; 273 i = hint; 260 261 count_t i = hint; 274 262 do { 275 z = zones.info[i];276 277 spinlock_lock(&z->lock);278 279 263 /* 280 264 * Check whether the zone meets the search criteria. 281 265 */ 282 if ((z ->flags & flags) == flags) {266 if ((zones.info[i].flags & flags) == flags) { 283 267 /* 284 268 * Check if the zone has 2^order frames area available. 285 269 */ 286 if (zone_can_alloc(z, order)) { 287 spinlock_unlock(&zones.lock); 288 if (pzone) 289 *pzone = i; 290 return z; 291 } 270 if (zone_can_alloc(&zones.info[i], order)) 271 return i; 292 272 } 293 spinlock_unlock(&z->lock); 294 if (++i >= zones.count) 273 274 i++; 275 if (i >= zones.count) 295 276 i = 0; 296 277 } while (i != hint); 297 spinlock_unlock(&zones.lock);298 return NULL;278 279 return (count_t) -1; 299 280 } 300 281 … … 308 289 * That means go to lower addresses, until such block is found 309 290 * 310 * @param order Order of parent must be different then this 311 * parameter!! 312 */ 313 static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child, 291 * @param order Order of parent must be different then this 292 * parameter!! 293 * 294 */ 295 static link_t *zone_buddy_find_block(buddy_system_t *buddy, link_t *child, 314 296 uint8_t order) 315 297 { 316 frame_t *frame; 317 zone_t *zone; 318 index_t index; 319 320 frame = list_get_instance(child, frame_t, buddy_link); 321 zone = (zone_t *) b->data; 322 323 index = frame_index(zone, frame); 298 frame_t *frame = list_get_instance(child, frame_t, buddy_link); 299 zone_t *zone = (zone_t *) buddy->data; 300 301 index_t index = frame_index(zone, frame); 324 302 do { 325 if (zone->frames[index].buddy_order != order) {303 if (zone->frames[index].buddy_order != order) 326 304 return &zone->frames[index].buddy_link; 327 }328 } while(index-- > 0);305 } while (index-- > 0); 306 329 307 return NULL; 330 308 } … … 332 310 /** Buddy system find_buddy implementation. 333 311 * 334 * @param b Buddy system. 335 * @param block Block for which buddy should be found. 336 * 337 * @return Buddy for given block if found. 338 */ 339 static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block) 340 { 341 frame_t *frame; 342 zone_t *zone; 343 index_t index; 344 bool is_left, is_right; 345 346 frame = list_get_instance(block, frame_t, buddy_link); 347 zone = (zone_t *) b->data; 312 * @param buddy Buddy system. 313 * @param block Block for which buddy should be found. 314 * 315 * @return Buddy for given block if found. 316 * 317 */ 318 static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, link_t *block) 319 { 320 frame_t *frame = list_get_instance(block, frame_t, buddy_link); 321 zone_t *zone = (zone_t *) buddy->data; 348 322 ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), 349 323 frame->buddy_order)); 350 324 351 is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);352 is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);353 325 bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); 326 bool is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame); 327 354 328 ASSERT(is_left ^ is_right); 329 330 index_t index; 355 331 if (is_left) { 356 332 index = (frame_index(zone, frame)) + 357 333 (1 << frame->buddy_order); 358 } else { 334 } else { /* if (is_right) */ 359 335 index = (frame_index(zone, frame)) - 360 336 (1 << frame->buddy_order); … … 362 338 363 339 if (frame_index_valid(zone, index)) { 364 if ( zone->frames[index].buddy_order == frame->buddy_order &&365 zone->frames[index].refcount == 0) {340 if ((zone->frames[index].buddy_order == frame->buddy_order) && 341 (zone->frames[index].refcount == 0)) { 366 342 return &zone->frames[index].buddy_link; 367 343 } 368 344 } 369 370 return NULL; 345 346 return NULL; 371 347 } 372 348 373 349 /** Buddy system bisect implementation. 374 350 * 375 * @param b Buddy system. 376 * @param block Block to bisect. 377 * 378 * @return Right block. 379 */ 380 static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block) 381 { 382 frame_t *frame_l, *frame_r; 383 384 frame_l = list_get_instance(block, frame_t, buddy_link); 385 frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); 351 * @param buddy Buddy system. 352 * @param block Block to bisect. 353 * 354 * @return Right block. 355 * 356 */ 357 static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block) 358 { 359 frame_t *frame_l = list_get_instance(block, frame_t, buddy_link); 360 frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1))); 386 361 387 362 return &frame_r->buddy_link; … … 390 365 /** Buddy system coalesce implementation. 391 366 * 392 * @param b Buddy system. 393 * @param block_1 First block. 394 * @param block_2 First block's buddy. 395 * 396 * @return Coalesced block (actually block that represents lower 397 * address). 398 */ 399 static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1, 400 link_t *block_2) 401 { 402 frame_t *frame1, *frame2; 403 404 frame1 = list_get_instance(block_1, frame_t, buddy_link); 405 frame2 = list_get_instance(block_2, frame_t, buddy_link); 406 407 return frame1 < frame2 ? block_1 : block_2; 367 * @param buddy Buddy system. 368 * @param block_1 First block. 369 * @param block_2 First block's buddy. 370 * 371 * @return Coalesced block (actually block that represents lower 372 * address). 373 * 374 */ 375 static link_t *zone_buddy_coalesce(buddy_system_t *buddy, link_t *block_1, 376 link_t *block_2) 377 { 378 frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link); 379 frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link); 380 381 return ((frame1 < frame2) ? block_1 : block_2); 408 382 } 409 383 410 384 /** Buddy system set_order implementation. 411 385 * 412 * @param b Buddy system. 413 * @param block Buddy system block. 414 * @param order Order to set. 415 */ 416 static void zone_buddy_set_order(buddy_system_t *b, link_t *block, 386 * @param buddy Buddy system. 387 * @param block Buddy system block. 388 * @param order Order to set. 389 * 390 */ 391 static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block, 417 392 uint8_t order) 418 393 { 419 frame_t *frame; 420 frame = list_get_instance(block, frame_t, buddy_link); 421 frame->buddy_order = order; 394 list_get_instance(block, frame_t, buddy_link)->buddy_order = order; 422 395 } 423 396 424 397 /** Buddy system get_order implementation. 425 398 * 426 * @param b Buddy system. 427 * @param block Buddy system block. 428 * 429 * @return Order of block. 430 */ 431 static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) 432 { 433 frame_t *frame; 434 frame = list_get_instance(block, frame_t, buddy_link); 435 return frame->buddy_order; 399 * @param buddy Buddy system. 400 * @param block Buddy system block. 401 * 402 * @return Order of block. 403 * 404 */ 405 static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block) 406 { 407 return list_get_instance(block, frame_t, buddy_link)->buddy_order; 436 408 } 437 409 438 410 /** Buddy system mark_busy implementation. 439 411 * 440 * @param b Buddy system. 441 * @param block Buddy system block. 442 */ 443 static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) 444 { 445 frame_t * frame; 446 447 frame = list_get_instance(block, frame_t, buddy_link); 448 frame->refcount = 1; 412 * @param buddy Buddy system. 413 * @param block Buddy system block. 414 * 415 */ 416 static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block) 417 { 418 list_get_instance(block, frame_t, buddy_link)->refcount = 1; 449 419 } 450 420 451 421 /** Buddy system mark_available implementation. 452 422 * 453 * @param b Buddy system. 454 * @param block Buddy system block. 455 */ 456 static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) 457 { 458 frame_t *frame; 459 frame = list_get_instance(block, frame_t, buddy_link); 460 frame->refcount = 0; 423 * @param buddy Buddy system. 424 * @param block Buddy system block. 425 */ 426 static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block) 427 { 428 list_get_instance(block, frame_t, buddy_link)->refcount = 0; 461 429 } 462 430 … … 478 446 /** Allocate frame in particular zone. 479 447 * 480 * Assume zone is locked .448 * Assume zone is locked and is available for allocation. 481 449 * Panics if allocation is impossible. 482 450 * 483 * @param zone 484 * @param order 485 * 486 * @return 451 * @param zone Zone to allocate from. 452 * @param order Allocate exactly 2^order frames. 453 * 454 * @return Frame index in zone. 487 455 * 488 456 */ 489 457 static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order) 490 458 { 491 pfn_t v; 492 link_t *tmp; 493 frame_t *frame; 494 459 ASSERT(zone_flags_available(zone->flags)); 460 495 461 /* Allocate frames from zone buddy system */ 496 tmp= buddy_system_alloc(zone->buddy_system, order);497 498 ASSERT( tmp);462 link_t *link = buddy_system_alloc(zone->buddy_system, order); 463 464 ASSERT(link); 499 465 500 466 /* Update zone information. */ 501 467 zone->free_count -= (1 << order); 502 468 zone->busy_count += (1 << order); 503 469 504 470 /* Frame will be actually a first frame of the block. */ 505 frame = list_get_instance(tmp, frame_t, buddy_link); 506 507 /* get frame address */ 508 v = make_frame_index(zone, frame); 509 return v; 471 frame_t *frame = list_get_instance(link, frame_t, buddy_link); 472 473 /* Get frame address */ 474 return make_frame_index(zone, frame); 510 475 } 511 476 512 477 /** Free frame from zone. 513 478 * 514 * Assume zone is locked. 515 * 516 * @param zone Pointer to zone from which the frame is to be freed. 517 * @param frame_idx Frame index relative to zone. 479 * Assume zone is locked and is available for deallocation. 480 * 481 * @param zone Pointer to zone from which the frame is to be freed. 482 * @param frame_idx Frame index relative to zone. 483 * 518 484 */ 519 485 static void zone_frame_free(zone_t *zone, index_t frame_idx) 520 486 { 521 frame_t *frame; 522 uint8_t order; 523 524 frame = &zone->frames[frame_idx]; 525 526 /* remember frame order */ 527 order = frame->buddy_order; 528 487 ASSERT(zone_flags_available(zone->flags)); 488 489 frame_t *frame = &zone->frames[frame_idx]; 490 491 /* Remember frame order */ 492 uint8_t order = frame->buddy_order; 493 529 494 ASSERT(frame->refcount); 530 495 531 496 if (!--frame->refcount) { 532 497 buddy_system_free(zone->buddy_system, &frame->buddy_link); 533 498 534 499 /* Update zone information. */ 535 500 zone->free_count += (1 << order); … … 548 513 static void zone_mark_unavailable(zone_t *zone, index_t frame_idx) 549 514 { 550 frame_t *frame; 551 link_t *link; 552 553 frame = zone_get_frame(zone, frame_idx); 515 ASSERT(zone_flags_available(zone->flags)); 516 517 frame_t *frame = zone_get_frame(zone, frame_idx); 554 518 if (frame->refcount) 555 519 return; 556 link = buddy_system_alloc_block(zone->buddy_system, 520 521 link_t *link = buddy_system_alloc_block(zone->buddy_system, 557 522 &frame->buddy_link); 523 558 524 ASSERT(link); 559 525 zone->free_count--; 560 561 mutex_lock(&mem_avail_mtx); 562 mem_avail_frames--; 563 mutex_unlock(&mem_avail_mtx); 564 } 565 566 /** Join two zones. 567 * 568 * Expect zone_t *z to point to space at least zone_conf_size large. 569 * 570 * Assume z1 & z2 are locked. 571 * 572 * @param z Target zone structure pointer. 573 * @param z1 Zone to merge. 574 * @param z2 Zone to merge. 575 */ 576 static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) 577 { 578 uint8_t max_order; 579 unsigned int i; 580 int z2idx; 581 pfn_t frame_idx; 582 frame_t *frame; 583 584 ASSERT(!overlaps(z1->base, z1->count, z2->base, z2->count)); 585 ASSERT(z1->base < z2->base); 586 587 spinlock_initialize(&z->lock, "zone_lock"); 588 z->base = z1->base; 589 z->count = z2->base + z2->count - z1->base; 590 z->flags = z1->flags & z2->flags; 591 592 z->free_count = z1->free_count + z2->free_count; 593 z->busy_count = z1->busy_count + z2->busy_count; 594 595 max_order = fnzb(z->count); 596 597 z->buddy_system = (buddy_system_t *) &z[1]; 598 buddy_system_create(z->buddy_system, max_order, 599 &zone_buddy_system_operations, (void *) z); 600 601 z->frames = (frame_t *)((uint8_t *) z->buddy_system + 602 buddy_conf_size(max_order)); 603 for (i = 0; i < z->count; i++) { 604 /* This marks all frames busy */ 605 frame_initialize(&z->frames[i]); 606 } 526 } 527 528 /** Merge two zones. 529 * 530 * Expect buddy to point to space at least zone_conf_size large. 531 * Assume z1 & z2 are locked and compatible and zones lock is 532 * locked. 533 * 534 * @param z1 First zone to merge. 535 * @param z2 Second zone to merge. 536 * @param old_z1 Original date of the first zone. 537 * @param buddy Merged zone buddy. 538 * 539 */ 540 static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy) 541 { 542 ASSERT(zone_flags_available(zones.info[z1].flags)); 543 ASSERT(zone_flags_available(zones.info[z2].flags)); 544 ASSERT(zones.info[z1].flags == zones.info[z2].flags); 545 ASSERT(zones.info[z1].base < zones.info[z2].base); 546 ASSERT(!overlaps(zones.info[z1].base, zones.info[z1].count, 547 zones.info[z2].base, zones.info[z2].count)); 548 549 /* Difference between zone bases */ 550 pfn_t base_diff = zones.info[z2].base - zones.info[z1].base; 551 552 zones.info[z1].count = base_diff + zones.info[z2].count; 553 zones.info[z1].free_count += zones.info[z2].free_count; 554 zones.info[z1].busy_count += zones.info[z2].busy_count; 555 zones.info[z1].buddy_system = buddy; 556 557 uint8_t order = fnzb(zones.info[z1].count); 558 buddy_system_create(zones.info[z1].buddy_system, order, 559 &zone_buddy_system_operations, (void *) &zones.info[z1]); 560 561 zones.info[z1].frames = 562 (frame_t *) ((uint8_t *) zones.info[z1].buddy_system 563 + buddy_conf_size(order)); 564 565 /* This marks all frames busy */ 566 count_t i; 567 for (i = 0; i < zones.info[z1].count; i++) 568 frame_initialize(&zones.info[z1].frames[i]); 569 607 570 /* Copy frames from both zones to preserve full frame orders, 608 * parents etc. Set all free frames with refcount =0 to 1, because609 * we add all free frames to buddy allocator later again, clear 610 * order to 0. Don't set busy frames with refcount =0, as they571 * parents etc. Set all free frames with refcount = 0 to 1, because 572 * we add all free frames to buddy allocator later again, clearing 573 * order to 0. Don't set busy frames with refcount = 0, as they 611 574 * will not be reallocated during merge and it would make later 612 575 * problems with allocation/free. 613 576 */ 614 for (i = 0; i < z1->count; i++) 615 z->frames[i] = z1->frames[i]; 616 for (i = 0; i < z2->count; i++) { 617 z2idx = i + (z2->base - z1->base); 618 z->frames[z2idx] = z2->frames[i]; 619 } 577 for (i = 0; i < old_z1->count; i++) 578 zones.info[z1].frames[i] = old_z1->frames[i]; 579 580 for (i = 0; i < zones.info[z2].count; i++) 581 zones.info[z1].frames[base_diff + i] 582 = zones.info[z2].frames[i]; 583 620 584 i = 0; 621 while (i < z->count) { 622 if (z->frames[i].refcount) { 623 /* skip busy frames */ 624 i += 1 << z->frames[i].buddy_order; 625 } else { /* Free frames, set refcount=1 */ 626 /* All free frames have refcount=0, we need not 627 * to check the order */ 628 z->frames[i].refcount = 1; 629 z->frames[i].buddy_order = 0; 585 while (i < zones.info[z1].count) { 586 if (zones.info[z1].frames[i].refcount) { 587 /* Skip busy frames */ 588 i += 1 << zones.info[z1].frames[i].buddy_order; 589 } else { 590 /* Free frames, set refcount = 1 591 * (all free frames have refcount == 0, we need not 592 * to check the order) 593 */ 594 zones.info[z1].frames[i].refcount = 1; 595 zones.info[z1].frames[i].buddy_order = 0; 630 596 i++; 631 597 } 632 598 } 633 /* Add free blocks from the 2 original zones */ 634 while (zone_can_alloc(z1, 0)) { 635 frame_idx = zone_frame_alloc(z1, 0); 636 frame = &z->frames[frame_idx]; 599 600 /* Add free blocks from the original zone z1 */ 601 while (zone_can_alloc(old_z1, 0)) { 602 /* Allocate from the original zone */ 603 pfn_t frame_idx = zone_frame_alloc(old_z1, 0); 604 605 /* Free the frame from the merged zone */ 606 frame_t *frame = &zones.info[z1].frames[frame_idx]; 637 607 frame->refcount = 0; 638 buddy_system_free(z->buddy_system, &frame->buddy_link); 639 } 640 while (zone_can_alloc(z2, 0)) { 641 frame_idx = zone_frame_alloc(z2, 0); 642 frame = &z->frames[frame_idx + (z2->base - z1->base)]; 608 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 609 } 610 611 /* Add free blocks from the original zone z2 */ 612 while (zone_can_alloc(&zones.info[z2], 0)) { 613 /* Allocate from the original zone */ 614 pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0); 615 616 /* Free the frame from the merged zone */ 617 frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx]; 643 618 frame->refcount = 0; 644 buddy_system_free(z ->buddy_system, &frame->buddy_link);619 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 645 620 } 646 621 } … … 648 623 /** Return old configuration frames into the zone. 649 624 * 650 * We have several cases 651 * - the conf. data is outside of zone -> exit, shall we call frame_free?? 652 * - the conf. data was created by zone_create or 653 * updated with reduce_region -> free every frame 654 * 655 * @param newzone The actual zone where freeing should occur. 656 * @param oldzone Pointer to old zone configuration data that should 657 * be freed from new zone. 658 */ 659 static void return_config_frames(zone_t *newzone, zone_t *oldzone) 660 { 661 pfn_t pfn; 662 frame_t *frame; 663 count_t cframes; 664 unsigned int i; 665 666 pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone)); 667 cframes = SIZE2FRAMES(zone_conf_size(oldzone->count)); 668 669 if (pfn < newzone->base || pfn >= newzone->base + newzone->count) 625 * We have two cases: 626 * - The configuration data is outside the zone 627 * -> do nothing (perhaps call frame_free?) 628 * - The configuration data was created by zone_create 629 * or updated by reduce_region -> free every frame 630 * 631 * @param znum The actual zone where freeing should occur. 632 * @param pfn Old zone configuration frame. 633 * @param count Old zone frame count. 634 * 635 */ 636 static void return_config_frames(count_t znum, pfn_t pfn, count_t count) 637 { 638 ASSERT(zone_flags_available(zones.info[znum].flags)); 639 640 count_t cframes = SIZE2FRAMES(zone_conf_size(count)); 641 642 if ((pfn < zones.info[znum].base) 643 || (pfn >= zones.info[znum].base + zones.info[znum].count)) 670 644 return; 671 672 frame = &newzone->frames[pfn - newzone->base]; 645 646 frame_t *frame 647 = &zones.info[znum].frames[pfn - zones.info[znum].base]; 673 648 ASSERT(!frame->buddy_order); 674 649 650 count_t i; 675 651 for (i = 0; i < cframes; i++) { 676 newzone->busy_count++; 677 zone_frame_free(newzone, pfn+i-newzone->base); 652 zones.info[znum].busy_count++; 653 zone_frame_free(&zones.info[znum], 654 pfn - zones.info[znum].base + i); 678 655 } 679 656 } … … 681 658 /** Reduce allocated block to count of order 0 frames. 682 659 * 683 * The allocated block need 2^order frames of space. Reduce all frames684 * in block to order 0 and free the unneeded frames. This means, that685 * when freeing the previously allocated block starting with frame_idx, 660 * The allocated block needs 2^order frames. Reduce all frames 661 * in the block to order 0 and free the unneeded frames. This means that 662 * when freeing the previously allocated block starting with frame_idx, 686 663 * you have to free every frame. 687 664 * 688 * @param zone 689 * @param frame_idx Index to block. 690 * @param count Allocated space in block. 691 */ 692 static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count) 693 { 665 * @param znum Zone. 666 * @param frame_idx Index the first frame of the block. 667 * @param count Allocated frames in block. 668 * 669 */ 670 static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count) 671 { 672 ASSERT(zone_flags_available(zones.info[znum].flags)); 673 ASSERT(frame_idx + count < zones.info[znum].count); 674 675 uint8_t order = zones.info[znum].frames[frame_idx].buddy_order; 676 ASSERT((count_t) (1 << order) >= count); 677 678 /* Reduce all blocks to order 0 */ 694 679 count_t i; 695 uint8_t order;696 frame_t *frame;697 698 ASSERT(frame_idx + count < zone->count);699 700 order = zone->frames[frame_idx].buddy_order;701 ASSERT((count_t) (1 << order) >= count);702 703 /* Reduce all blocks to order 0 */704 680 for (i = 0; i < (count_t) (1 << order); i++) { 705 frame = &zone->frames[i + frame_idx];681 frame_t *frame = &zones.info[znum].frames[i + frame_idx]; 706 682 frame->buddy_order = 0; 707 683 if (!frame->refcount) … … 709 685 ASSERT(frame->refcount == 1); 710 686 } 687 711 688 /* Free unneeded frames */ 712 for (i = count; i < (count_t) (1 << order); i++) { 713 zone_frame_free(zone, i + frame_idx); 714 } 689 for (i = count; i < (count_t) (1 << order); i++) 690 zone_frame_free(&zones.info[znum], i + frame_idx); 715 691 } 716 692 717 693 /** Merge zones z1 and z2. 718 694 * 719 * - the zones must be 2 zones with no zone existing in between, 720 * which means that z2 = z1+1 721 * 722 * - When you create a new zone, the frame allocator configuration does 723 * not to be 2^order size. Once the allocator is running it is no longer 724 * possible, merged configuration data occupies more space :-/ 725 */ 726 void zone_merge(unsigned int z1, unsigned int z2) 727 { 728 ipl_t ipl; 729 zone_t *zone1, *zone2, *newzone; 730 unsigned int cframes; 695 * The merged zones must be 2 zones with no zone existing in between 696 * (which means that z2 = z1 + 1). Both zones must be available zones 697 * with the same flags. 698 * 699 * When you create a new zone, the frame allocator configuration does 700 * not to be 2^order size. Once the allocator is running it is no longer 701 * possible, merged configuration data occupies more space :-/ 702 * 703 * The function uses 704 * 705 */ 706 bool zone_merge(count_t z1, count_t z2) 707 { 708 ipl_t ipl = interrupts_disable(); 709 spinlock_lock(&zones.lock); 710 711 bool ret = true; 712 713 /* We can join only 2 zones with none existing inbetween, 714 * the zones have to be available and with the same 715 * set of flags 716 */ 717 if ((z1 >= zones.count) || (z2 >= zones.count) 718 || (z2 - z1 != 1) 719 || (!zone_flags_available(zones.info[z1].flags)) 720 || (!zone_flags_available(zones.info[z2].flags)) 721 || (zones.info[z1].flags != zones.info[z2].flags)) { 722 ret = false; 723 goto errout; 724 } 725 726 pfn_t cframes = SIZE2FRAMES(zone_conf_size( 727 zones.info[z2].base - zones.info[z1].base 728 + zones.info[z2].count)); 729 731 730 uint8_t order; 732 unsigned int i;733 pfn_t pfn;734 735 ipl = interrupts_disable();736 spinlock_lock(&zones.lock);737 738 if ((z1 >= zones.count) || (z2 >= zones.count))739 goto errout;740 /* We can join only 2 zones with none existing inbetween */741 if (z2 - z1 != 1)742 goto errout;743 744 zone1 = zones.info[z1];745 zone2 = zones.info[z2];746 spinlock_lock(&zone1->lock);747 spinlock_lock(&zone2->lock);748 749 cframes = SIZE2FRAMES(zone_conf_size(zone2->base + zone2->count -750 zone1->base));751 731 if (cframes == 1) 752 732 order = 0; 753 else 733 else 754 734 order = fnzb(cframes - 1) + 1; 755 756 /* Allocate zonedata inside one of the zones */ 757 if (zone_can_alloc(zone1, order)) 758 pfn = zone1->base + zone_frame_alloc(zone1, order); 759 else if (zone_can_alloc(zone2, order)) 760 pfn = zone2->base + zone_frame_alloc(zone2, order); 761 else 762 goto errout2; 763 764 newzone = (zone_t *) PA2KA(PFN2ADDR(pfn)); 765 766 _zone_merge(newzone, zone1, zone2); 767 735 736 /* Allocate merged zone data inside one of the zones */ 737 pfn_t pfn; 738 if (zone_can_alloc(&zones.info[z1], order)) { 739 pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order); 740 } else if (zone_can_alloc(&zones.info[z2], order)) { 741 pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order); 742 } else { 743 ret = false; 744 goto errout; 745 } 746 747 /* Preserve original data from z1 */ 748 zone_t old_z1 = zones.info[z1]; 749 old_z1.buddy_system->data = (void *) &old_z1; 750 751 /* Do zone merging */ 752 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn)); 753 zone_merge_internal(z1, z2, &old_z1, buddy); 754 768 755 /* Free unneeded config frames */ 769 zone_reduce_region(newzone, pfn - newzone->base, cframes); 756 zone_reduce_region(z1, pfn - zones.info[z1].base, cframes); 757 770 758 /* Subtract zone information from busy frames */ 771 newzone->busy_count -= cframes; 772 773 /* Replace existing zones in zoneinfo list */ 774 zones.info[z1] = newzone; 759 zones.info[z1].busy_count -= cframes; 760 761 /* Free old zone information */ 762 return_config_frames(z1, 763 ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count); 764 return_config_frames(z1, 765 ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)), 766 zones.info[z2].count); 767 768 /* Shift existing zones */ 769 count_t i; 775 770 for (i = z2 + 1; i < zones.count; i++) 776 771 zones.info[i - 1] = zones.info[i]; 777 772 zones.count--; 778 779 /* Free old zone information */ 780 return_config_frames(newzone, zone1); 781 return_config_frames(newzone, zone2); 782 errout2: 783 /* Nobody is allowed to enter to zone, so we are safe 784 * to touch the spinlocks last time */ 785 spinlock_unlock(&zone1->lock); 786 spinlock_unlock(&zone2->lock); 773 787 774 errout: 788 775 spinlock_unlock(&zones.lock); 789 776 interrupts_restore(ipl); 790 } 791 792 /** Merge all zones into one big zone. 793 * 794 * It is reasonable to do this on systems whose bios reports parts in chunks, 795 * so that we could have 1 zone (it's faster). 777 778 return ret; 779 } 780 781 /** Merge all mergeable zones into one big zone. 782 * 783 * It is reasonable to do this on systems where 784 * BIOS reports parts in chunks, so that we could 785 * have 1 zone (it's faster). 786 * 796 787 */ 797 788 void zone_merge_all(void) 798 789 { 799 int count = zones.count; 800 801 while (zones.count > 1 && --count) { 802 zone_merge(0, 1); 803 break; 790 count_t i = 0; 791 while (i < zones.count) { 792 if (!zone_merge(i, i + 1)) 793 i++; 804 794 } 805 795 } … … 807 797 /** Create new frame zone. 808 798 * 809 * @param start Physical address of the first frame within the zone. 810 * @param count Count of frames in zone. 811 * @param z Address of configuration information of zone. 812 * @param flags Zone flags. 813 * 814 * @return Initialized zone. 815 */ 816 static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) 817 { 818 unsigned int i; 819 uint8_t max_order; 820 821 spinlock_initialize(&z->lock, "zone_lock"); 822 z->base = start; 823 z->count = count; 824 825 /* Mask off flags that are calculated automatically. */ 826 flags &= ~FRAME_LOW_4_GiB; 827 /* Determine calculated flags. */ 828 if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */ 829 flags |= FRAME_LOW_4_GiB; 830 831 z->flags = flags; 832 833 z->free_count = count; 834 z->busy_count = 0; 835 836 /* 837 * Compute order for buddy system, initialize 838 */ 839 max_order = fnzb(count); 840 z->buddy_system = (buddy_system_t *)&z[1]; 841 842 buddy_system_create(z->buddy_system, max_order, 843 &zone_buddy_system_operations, (void *) z); 844 845 /* Allocate frames _after_ the conframe */ 846 /* Check sizes */ 847 z->frames = (frame_t *)((uint8_t *) z->buddy_system + 848 buddy_conf_size(max_order)); 849 for (i = 0; i < count; i++) { 850 frame_initialize(&z->frames[i]); 851 } 852 853 /* Stuffing frames */ 854 for (i = 0; i < count; i++) { 855 z->frames[i].refcount = 0; 856 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); 857 } 799 * @param zone Zone to construct. 800 * @param buddy Address of buddy system configuration information. 801 * @param start Physical address of the first frame within the zone. 802 * @param count Count of frames in zone. 803 * @param flags Zone flags. 804 * 805 * @return Initialized zone. 806 * 807 */ 808 static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags) 809 { 810 zone->base = start; 811 zone->count = count; 812 zone->flags = flags; 813 zone->free_count = count; 814 zone->busy_count = 0; 815 zone->buddy_system = buddy; 816 817 if (zone_flags_available(flags)) { 818 /* 819 * Compute order for buddy system and initialize 820 */ 821 uint8_t order = fnzb(count); 822 buddy_system_create(zone->buddy_system, order, 823 &zone_buddy_system_operations, (void *) zone); 824 825 /* Allocate frames _after_ the confframe */ 826 827 /* Check sizes */ 828 zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system + 829 buddy_conf_size(order)); 830 831 count_t i; 832 for (i = 0; i < count; i++) 833 frame_initialize(&zone->frames[i]); 834 835 /* Stuffing frames */ 836 for (i = 0; i < count; i++) { 837 zone->frames[i].refcount = 0; 838 buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link); 839 } 840 } else 841 zone->frames = NULL; 858 842 } 859 843 860 844 /** Compute configuration data size for zone. 861 845 * 862 * @param count Size of zone in frames. 863 * @return Size of zone configuration info (in bytes). 846 * @param count Size of zone in frames. 847 * 848 * @return Size of zone configuration info (in bytes). 849 * 864 850 */ 865 851 uintptr_t zone_conf_size(count_t count) 866 852 { 867 int size = sizeof(zone_t) + count * sizeof(frame_t); 868 int max_order; 869 870 max_order = fnzb(count); 871 size += buddy_conf_size(max_order); 872 return size; 853 return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count))); 873 854 } 874 855 875 856 /** Create and add zone to system. 876 857 * 877 * @param start First frame number (absolute). 878 * @param count Size of zone in frames. 879 * @param confframe Where configuration frames are supposed to be. 880 * Automatically checks, that we will not disturb the 881 * kernel and possibly init. If confframe is given 882 * _outside_ this zone, it is expected, that the area is 883 * already marked BUSY and big enough to contain 884 * zone_conf_size() amount of data. If the confframe is 885 * inside the area, the zone free frame information is 886 * modified not to include it. 887 * 888 * @return Zone number or -1 on error. 889 */ 890 int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) 891 { 892 zone_t *z; 893 uintptr_t addr; 894 count_t confcount; 895 unsigned int i; 896 int znum; 897 898 /* Theoretically we could have here 0, practically make sure 899 * nobody tries to do that. If some platform requires, remove 900 * the assert 901 */ 902 ASSERT(confframe); 903 /* If conframe is supposed to be inside our zone, then make sure 904 * it does not span kernel & init 905 */ 906 confcount = SIZE2FRAMES(zone_conf_size(count)); 907 if (confframe >= start && confframe < start + count) { 908 for (; confframe < start + count; confframe++) { 909 addr = PFN2ADDR(confframe); 910 if (overlaps(addr, PFN2ADDR(confcount), 911 KA2PA(config.base), config.kernel_size)) 912 continue; 858 * @param start First frame number (absolute). 859 * @param count Size of zone in frames. 860 * @param confframe Where configuration frames are supposed to be. 861 * Automatically checks, that we will not disturb the 862 * kernel and possibly init. If confframe is given 863 * _outside_ this zone, it is expected, that the area is 864 * already marked BUSY and big enough to contain 865 * zone_conf_size() amount of data. If the confframe is 866 * inside the area, the zone free frame information is 867 * modified not to include it. 868 * 869 * @return Zone number or -1 on error. 870 * 871 */ 872 count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags) 873 { 874 ipl_t ipl = interrupts_disable(); 875 spinlock_lock(&zones.lock); 876 877 if (zone_flags_available(flags)) { /* Create available zone */ 878 /* Theoretically we could have NULL here, practically make sure 879 * nobody tries to do that. If some platform requires, remove 880 * the assert 881 */ 882 ASSERT(confframe != NULL); 883 884 /* If confframe is supposed to be inside our zone, then make sure 885 * it does not span kernel & init 886 */ 887 count_t confcount = SIZE2FRAMES(zone_conf_size(count)); 888 if ((confframe >= start) && (confframe < start + count)) { 889 for (; confframe < start + count; confframe++) { 890 uintptr_t addr = PFN2ADDR(confframe); 891 if (overlaps(addr, PFN2ADDR(confcount), 892 KA2PA(config.base), config.kernel_size)) 893 continue; 894 895 if (overlaps(addr, PFN2ADDR(confcount), 896 KA2PA(config.stack_base), config.stack_size)) 897 continue; 898 899 bool overlap = false; 900 count_t i; 901 for (i = 0; i < init.cnt; i++) 902 if (overlaps(addr, PFN2ADDR(confcount), 903 KA2PA(init.tasks[i].addr), 904 init.tasks[i].size)) { 905 overlap = true; 906 break; 907 } 908 if (overlap) 909 continue; 910 911 break; 912 } 913 913 914 if (overlaps(addr, PFN2ADDR(confcount), 915 KA2PA(config.stack_base), config.stack_size)) 916 continue; 917 918 bool overlap = false; 914 if (confframe >= start + count) 915 panic("Cannot find configuration data for zone."); 916 } 917 918 count_t znum = zones_insert_zone(start, count); 919 if (znum == (count_t) -1) { 920 spinlock_unlock(&zones.lock); 921 interrupts_restore(ipl); 922 return (count_t) -1; 923 } 924 925 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe)); 926 zone_construct(&zones.info[znum], buddy, start, count, flags); 927 928 /* If confdata in zone, mark as unavailable */ 929 if ((confframe >= start) && (confframe < start + count)) { 919 930 count_t i; 920 for (i = 0; i < init.cnt; i++) 921 if (overlaps(addr, PFN2ADDR(confcount), 922 KA2PA(init.tasks[i].addr), 923 init.tasks[i].size)) { 924 overlap = true; 925 break; 926 } 927 if (overlap) 928 continue; 929 930 break; 931 for (i = confframe; i < confframe + confcount; i++) 932 zone_mark_unavailable(&zones.info[znum], 933 i - zones.info[znum].base); 931 934 } 932 if (confframe >= start + count) 933 panic("Cannot find configuration data for zone."); 934 } 935 936 z = (zone_t *) PA2KA(PFN2ADDR(confframe)); 937 zone_construct(start, count, z, flags); 938 znum = zones_add_zone(z); 939 if (znum == -1) 940 return -1; 941 942 mutex_lock(&mem_avail_mtx); 943 mem_avail_frames += count; 944 mutex_unlock(&mem_avail_mtx); 945 946 /* If confdata in zone, mark as unavailable */ 947 if (confframe >= start && confframe < start + count) 948 for (i = confframe; i < confframe + confcount; i++) { 949 zone_mark_unavailable(z, i - z->base); 950 } 935 936 spinlock_unlock(&zones.lock); 937 interrupts_restore(ipl); 938 939 return znum; 940 } 941 942 /* Non-available zone */ 943 count_t znum = zones_insert_zone(start, count); 944 if (znum == (count_t) -1) { 945 spinlock_unlock(&zones.lock); 946 interrupts_restore(ipl); 947 return (count_t) -1; 948 } 949 zone_construct(&zones.info[znum], NULL, start, count, flags); 950 951 spinlock_unlock(&zones.lock); 952 interrupts_restore(ipl); 951 953 952 954 return znum; 953 955 } 954 956 955 /******************* ********************/957 /*******************/ 956 958 /* Frame functions */ 959 /*******************/ 957 960 958 961 /** Set parent of frame. */ 959 void frame_set_parent(pfn_t pfn, void *data, unsigned int hint) 960 { 961 zone_t *zone = find_zone_and_lock(pfn, &hint); 962 963 ASSERT(zone); 964 965 zone_get_frame(zone, pfn - zone->base)->parent = data; 966 spinlock_unlock(&zone->lock); 967 } 968 969 void *frame_get_parent(pfn_t pfn, unsigned int hint) 970 { 971 zone_t *zone = find_zone_and_lock(pfn, &hint); 972 void *res; 973 974 ASSERT(zone); 975 res = zone_get_frame(zone, pfn - zone->base)->parent; 976 977 spinlock_unlock(&zone->lock); 962 void frame_set_parent(pfn_t pfn, void *data, count_t hint) 963 { 964 ipl_t ipl = interrupts_disable(); 965 spinlock_lock(&zones.lock); 966 967 count_t znum = find_zone(pfn, hint); 968 969 ASSERT(znum != (count_t) -1); 970 971 zone_get_frame(&zones.info[znum], 972 pfn - zones.info[znum].base)->parent = data; 973 974 spinlock_unlock(&zones.lock); 975 interrupts_restore(ipl); 976 } 977 978 void *frame_get_parent(pfn_t pfn, count_t hint) 979 { 980 ipl_t ipl = interrupts_disable(); 981 spinlock_lock(&zones.lock); 982 983 count_t znum = find_zone(pfn, hint); 984 985 ASSERT(znum != (count_t) -1); 986 987 void *res = zone_get_frame(&zones.info[znum], 988 pfn - zones.info[znum].base)->parent; 989 990 spinlock_unlock(&zones.lock); 991 interrupts_restore(ipl); 992 978 993 return res; 979 994 } … … 981 996 /** Allocate power-of-two frames of physical memory. 982 997 * 983 * @param order Allocate exactly 2^order frames. 984 * @param flags Flags for host zone selection and address processing. 985 * @param pzone Preferred zone. 986 * 987 * @return Physical address of the allocated frame. 988 * 989 */ 990 void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone) 991 { 998 * @param order Allocate exactly 2^order frames. 999 * @param flags Flags for host zone selection and address processing. 1000 * @param pzone Preferred zone. 1001 * 1002 * @return Physical address of the allocated frame. 1003 * 1004 */ 1005 void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone) 1006 { 1007 count_t size = ((count_t) 1) << order; 992 1008 ipl_t ipl; 993 int freed; 994 pfn_t v; 995 zone_t *zone; 996 unsigned long gen = 0; 1009 count_t hint = pzone ? (*pzone) : 0; 997 1010 998 1011 loop: 999 1012 ipl = interrupts_disable(); 1013 spinlock_lock(&zones.lock); 1000 1014 1001 1015 /* 1002 1016 * First, find suitable frame zone. 1003 1017 */ 1004 zone = find_free_zone_and_lock(order, flags, pzone); 1018 count_t znum = find_free_zone(order, 1019 FRAME_TO_ZONE_FLAGS(flags), hint); 1005 1020 1006 1021 /* If no memory, reclaim some slab memory, 1007 1022 if it does not help, reclaim all */ 1008 if (!zone && !(flags & FRAME_NO_RECLAIM)) { 1009 freed = slab_reclaim(0); 1010 if (freed) 1011 zone = find_free_zone_and_lock(order, flags, pzone); 1012 if (!zone) { 1023 if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { 1024 count_t freed = slab_reclaim(0); 1025 1026 if (freed > 0) 1027 znum = find_free_zone(order, 1028 FRAME_TO_ZONE_FLAGS(flags), hint); 1029 1030 if (znum == (count_t) -1) { 1013 1031 freed = slab_reclaim(SLAB_RECLAIM_ALL); 1014 if (freed )1015 z one = find_free_zone_and_lock(order, flags,1016 pzone);1032 if (freed > 0) 1033 znum = find_free_zone(order, 1034 FRAME_TO_ZONE_FLAGS(flags), hint); 1017 1035 } 1018 1036 } 1019 if (!zone) { 1037 1038 if (znum == (count_t) -1) { 1039 if (flags & FRAME_ATOMIC) { 1040 spinlock_unlock(&zones.lock); 1041 interrupts_restore(ipl); 1042 return NULL; 1043 } 1044 1045 #ifdef CONFIG_DEBUG 1046 count_t avail = total_frames_free(); 1047 #endif 1048 1049 spinlock_unlock(&zones.lock); 1050 interrupts_restore(ipl); 1051 1020 1052 /* 1021 1053 * Sleep until some frames are available again. 1022 1054 */ 1023 if (flags & FRAME_ATOMIC) {1024 interrupts_restore(ipl);1025 return 0;1026 }1027 1055 1028 1056 #ifdef CONFIG_DEBUG 1029 unsigned long avail; 1030 1057 printf("Thread %" PRIu64 " waiting for %" PRIc " frames, " 1058 "%" PRIc " available.\n", THREAD->tid, size, avail); 1059 #endif 1060 1031 1061 mutex_lock(&mem_avail_mtx); 1032 avail = mem_avail_frames; 1062 1063 if (mem_avail_req > 0) 1064 mem_avail_req = min(mem_avail_req, size); 1065 else 1066 mem_avail_req = size; 1067 count_t gen = mem_avail_gen; 1068 1069 while (gen == mem_avail_gen) 1070 condvar_wait(&mem_avail_cv, &mem_avail_mtx); 1071 1033 1072 mutex_unlock(&mem_avail_mtx); 1034 1035 printf("Thread %" PRIu64 " waiting for %u frames, " 1036 "%u available.\n", THREAD->tid, 1ULL << order, avail);1073 1074 #ifdef CONFIG_DEBUG 1075 printf("Thread %" PRIu64 " woken up.\n", THREAD->tid); 1037 1076 #endif 1038 1039 mutex_lock(&mem_avail_mtx); 1040 while ((mem_avail_frames < (1ULL << order)) || 1041 gen == mem_avail_gen) 1042 condvar_wait(&mem_avail_cv, &mem_avail_mtx); 1043 gen = mem_avail_gen; 1044 mutex_unlock(&mem_avail_mtx); 1045 1046 #ifdef CONFIG_DEBUG 1047 mutex_lock(&mem_avail_mtx); 1048 avail = mem_avail_frames; 1049 mutex_unlock(&mem_avail_mtx); 1050 1051 printf("Thread %" PRIu64 " woken up, %u frames available.\n", 1052 THREAD->tid, avail); 1053 #endif 1054 1055 interrupts_restore(ipl); 1077 1056 1078 goto loop; 1057 1079 } 1058 1080 1059 v = zone_frame_alloc(zone, order); 1060 v += zone->base; 1061 1062 spinlock_unlock(&zone->lock); 1063 1064 mutex_lock(&mem_avail_mtx); 1065 mem_avail_frames -= (1ULL << order); 1066 mutex_unlock(&mem_avail_mtx); 1067 1081 pfn_t pfn = zone_frame_alloc(&zones.info[znum], order) 1082 + zones.info[znum].base; 1083 1084 spinlock_unlock(&zones.lock); 1068 1085 interrupts_restore(ipl); 1069 1086 1087 if (pzone) 1088 *pzone = znum; 1089 1070 1090 if (flags & FRAME_KA) 1071 return (void *)PA2KA(PFN2ADDR(v)); 1072 return (void *)PFN2ADDR(v); 1091 return (void *) PA2KA(PFN2ADDR(pfn)); 1092 1093 return (void *) PFN2ADDR(pfn); 1073 1094 } 1074 1095 … … 1076 1097 * 1077 1098 * Find respective frame structure for supplied physical frame address. 1078 * Decrement frame reference count. 1079 * If it drops to zero, move the frame structure to free list. 1080 * 1081 * @param frame Physical Address of of the frame to be freed. 1099 * Decrement frame reference count. If it drops to zero, move the frame 1100 * structure to free list. 1101 * 1102 * @param frame Physical Address of of the frame to be freed. 1103 * 1082 1104 */ 1083 1105 void frame_free(uintptr_t frame) 1084 1106 { 1085 ipl_t ipl; 1086 zone_t *zone; 1087 pfn_t pfn = ADDR2PFN(frame); 1088 1089 ipl = interrupts_disable(); 1090 1107 ipl_t ipl = interrupts_disable(); 1108 spinlock_lock(&zones.lock); 1109 1091 1110 /* 1092 1111 * First, find host frame zone for addr. 1093 1112 */ 1094 zone = find_zone_and_lock(pfn, NULL); 1095 ASSERT(zone); 1096 1097 zone_frame_free(zone, pfn - zone->base); 1098 1099 spinlock_unlock(&zone->lock); 1113 pfn_t pfn = ADDR2PFN(frame); 1114 count_t znum = find_zone(pfn, NULL); 1115 1116 ASSERT(znum != (count_t) -1); 1117 1118 zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); 1119 1120 spinlock_unlock(&zones.lock); 1121 interrupts_restore(ipl); 1100 1122 1101 1123 /* … … 1103 1125 */ 1104 1126 mutex_lock(&mem_avail_mtx); 1105 mem_avail_frames++; 1106 mem_avail_gen++; 1107 condvar_broadcast(&mem_avail_cv); 1127 if (mem_avail_req > 0) 1128 mem_avail_req--; 1129 1130 if (mem_avail_req == 0) { 1131 mem_avail_gen++; 1132 condvar_broadcast(&mem_avail_cv); 1133 } 1108 1134 mutex_unlock(&mem_avail_mtx); 1109 1110 interrupts_restore(ipl);1111 1135 } 1112 1136 … … 1116 1140 * increment frame reference count. 1117 1141 * 1118 * @param pfn Frame number of the frame to be freed. 1142 * @param pfn Frame number of the frame to be freed. 1143 * 1119 1144 */ 1120 1145 void frame_reference_add(pfn_t pfn) 1121 1146 { 1122 ipl_t ipl; 1123 zone_t *zone; 1124 frame_t *frame; 1125 1126 ipl = interrupts_disable(); 1147 ipl_t ipl = interrupts_disable(); 1148 spinlock_lock(&zones.lock); 1127 1149 1128 1150 /* 1129 1151 * First, find host frame zone for addr. 1130 1152 */ 1131 zone = find_zone_and_lock(pfn, NULL);1132 ASSERT(zone);1133 1134 frame = &zone->frames[pfn - zone->base];1135 frame->refcount++;1136 1137 spinlock_unlock(&zone ->lock);1153 count_t znum = find_zone(pfn, NULL); 1154 1155 ASSERT(znum != (count_t) -1); 1156 1157 zones.info[znum].frames[pfn - zones.info[znum].base].refcount++; 1158 1159 spinlock_unlock(&zones.lock); 1138 1160 interrupts_restore(ipl); 1139 1161 } … … 1142 1164 void frame_mark_unavailable(pfn_t start, count_t count) 1143 1165 { 1144 unsigned int i;1145 zone_t *zone;1146 unsigned int prefzone = 0;1147 1166 ipl_t ipl = interrupts_disable(); 1167 spinlock_lock(&zones.lock); 1168 1169 count_t i; 1148 1170 for (i = 0; i < count; i++) { 1149 zone = find_zone_and_lock(start + i, &prefzone);1150 if ( !zone)/* PFN not found */1171 count_t znum = find_zone(start + i, 0); 1172 if (znum == (count_t) -1) /* PFN not found */ 1151 1173 continue; 1152 zone_mark_unavailable(zone, start + i - zone->base); 1153 1154 spinlock_unlock(&zone->lock); 1155 } 1174 1175 zone_mark_unavailable(&zones.info[znum], 1176 start + i - zones.info[znum].base); 1177 } 1178 1179 spinlock_unlock(&zones.lock); 1180 interrupts_restore(ipl); 1156 1181 } 1157 1182 … … 1165 1190 condvar_initialize(&mem_avail_cv); 1166 1191 } 1192 1167 1193 /* Tell the architecture to create some memory */ 1168 1194 frame_arch_init(); … … 1179 1205 SIZE2FRAMES(init.tasks[i].size)); 1180 1206 } 1181 1207 1182 1208 if (ballocs.size) 1183 1209 frame_mark_unavailable(ADDR2PFN(KA2PA(ballocs.base)), 1184 1210 SIZE2FRAMES(ballocs.size)); 1185 1211 1186 1212 /* Black list first frame, as allocating NULL would 1187 * fail in some places */ 1213 * fail in some places 1214 */ 1188 1215 frame_mark_unavailable(0, 1); 1189 1216 } 1190 1217 } 1191 1192 1218 1193 1219 /** Return total size of all zones. */ 1194 1220 uint64_t zone_total_size(void) 1195 1221 { 1196 zone_t *zone = NULL;1197 unsigned int i;1198 ipl_t ipl;1222 ipl_t ipl = interrupts_disable(); 1223 spinlock_lock(&zones.lock); 1224 1199 1225 uint64_t total = 0; 1200 1201 ipl = interrupts_disable(); 1202 spinlock_lock(&zones.lock); 1203 1204 for (i = 0; i < zones.count; i++) { 1205 zone = zones.info[i]; 1206 spinlock_lock(&zone->lock); 1207 total += (uint64_t) FRAMES2SIZE(zone->count); 1208 spinlock_unlock(&zone->lock); 1209 } 1226 count_t i; 1227 for (i = 0; i < zones.count; i++) 1228 total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1210 1229 1211 1230 spinlock_unlock(&zones.lock); … … 1218 1237 void zone_print_list(void) 1219 1238 { 1220 zone_t *zone = NULL; 1221 unsigned int i; 1222 ipl_t ipl; 1223 1224 #ifdef __32_BITS__ 1225 printf("# base address free frames busy frames\n"); 1226 printf("-- ------------ ------------ ------------\n"); 1239 #ifdef __32_BITS__ 1240 printf("# base address flags free frames busy frames\n"); 1241 printf("-- ------------ -------- ------------ ------------\n"); 1227 1242 #endif 1228 1243 1229 1244 #ifdef __64_BITS__ 1230 printf("# base address f ree frames busy frames\n");1231 printf("-- -------------------- -------- ---- ------------\n");1245 printf("# base address flags free frames busy frames\n"); 1246 printf("-- -------------------- -------- ------------ ------------\n"); 1232 1247 #endif 1233 1248 … … 1242 1257 * the listing). 1243 1258 */ 1244 1245 for (i = 0; ; i++) { 1246 uintptr_t base; 1247 count_t free_count; 1248 count_t busy_count; 1249 1250 ipl = interrupts_disable(); 1259 1260 count_t i; 1261 for (i = 0;; i++) { 1262 ipl_t ipl = interrupts_disable(); 1251 1263 spinlock_lock(&zones.lock); 1252 1264 … … 1256 1268 break; 1257 1269 } 1258 1259 zone = zones.info[i]; 1260 spinlock_lock(&zone->lock); 1261 1262 base = PFN2ADDR(zone->base); 1263 free_count = zone->free_count; 1264 busy_count = zone->busy_count; 1265 1266 spinlock_unlock(&zone->lock); 1270 1271 uintptr_t base = PFN2ADDR(zones.info[i].base); 1272 zone_flags_t flags = zones.info[i].flags; 1273 count_t free_count = zones.info[i].free_count; 1274 count_t busy_count = zones.info[i].busy_count; 1267 1275 1268 1276 spinlock_unlock(&zones.lock); 1269 1277 interrupts_restore(ipl); 1270 1278 1279 bool available = zone_flags_available(flags); 1280 1271 1281 #ifdef __32_BITS__ 1272 printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base, 1273 free_count, busy_count); 1282 printf("%-2" PRIc " %10p %c%c%c ", i, base, 1283 available ? 'A' : ' ', 1284 (flags & ZONE_RESERVED) ? 'R' : ' ', 1285 (flags & ZONE_FIRMWARE) ? 'F' : ' '); 1274 1286 #endif 1275 1287 1276 1288 #ifdef __64_BITS__ 1277 printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base, 1278 free_count, busy_count); 1289 printf("%-2" PRIc " %18p %c%c%c ", i, base, 1290 available ? 'A' : ' ', 1291 (flags & ZONE_RESERVED) ? 'R' : ' ', 1292 (flags & ZONE_FIRMWARE) ? 'F' : ' '); 1279 1293 #endif 1280 1294 1295 if (available) 1296 printf("%12" PRIc " %12" PRIc, 1297 free_count, busy_count); 1298 printf("\n"); 1281 1299 } 1282 1300 } … … 1284 1302 /** Prints zone details. 1285 1303 * 1286 * @param num Zone base address or zone number. 1287 */ 1288 void zone_print_one(unsigned int num) 1289 { 1290 zone_t *zone = NULL; 1291 ipl_t ipl; 1292 unsigned int i; 1293 uintptr_t base; 1294 count_t count; 1295 count_t busy_count; 1296 count_t free_count; 1297 1298 ipl = interrupts_disable(); 1304 * @param num Zone base address or zone number. 1305 * 1306 */ 1307 void zone_print_one(count_t num) 1308 { 1309 ipl_t ipl = interrupts_disable(); 1299 1310 spinlock_lock(&zones.lock); 1300 1311 count_t znum = (count_t) -1; 1312 1313 count_t i; 1301 1314 for (i = 0; i < zones.count; i++) { 1302 if ((i == num) || (PFN2ADDR(zones.info[i] ->base) == num)) {1303 z one = zones.info[i];1315 if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) { 1316 znum = i; 1304 1317 break; 1305 1318 } 1306 1319 } 1307 if (!zone) { 1320 1321 if (znum == (count_t) -1) { 1308 1322 spinlock_unlock(&zones.lock); 1309 1323 interrupts_restore(ipl); … … 1312 1326 } 1313 1327 1314 spinlock_lock(&zone->lock);1315 base = PFN2ADDR(zone->base);1316 count = zone->count;1317 busy_count = zone->busy_count;1318 free_count = zone->free_count;1319 spinlock_unlock(&zone->lock);1328 uintptr_t base = PFN2ADDR(zones.info[i].base); 1329 zone_flags_t flags = zones.info[i].flags; 1330 count_t count = zones.info[i].count; 1331 count_t free_count = zones.info[i].free_count; 1332 count_t busy_count = zones.info[i].busy_count; 1333 1320 1334 spinlock_unlock(&zones.lock); 1321 1335 interrupts_restore(ipl); 1322 1336 1337 bool available = zone_flags_available(flags); 1338 1339 printf("Zone number: %" PRIc "\n", znum); 1323 1340 printf("Zone base address: %p\n", base); 1324 printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,1341 printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count, 1325 1342 SIZE2KB(FRAMES2SIZE(count))); 1326 printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", 1327 busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); 1328 printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", 1329 free_count, SIZE2KB(FRAMES2SIZE(free_count))); 1343 printf("Zone flags: %c%c%c\n", 1344 available ? 'A' : ' ', 1345 (flags & ZONE_RESERVED) ? 'R' : ' ', 1346 (flags & ZONE_FIRMWARE) ? 'F' : ' '); 1347 1348 if (available) { 1349 printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", 1350 busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); 1351 printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", 1352 free_count, SIZE2KB(FRAMES2SIZE(free_count))); 1353 } 1330 1354 } 1331 1355 1332 1356 /** @} 1333 1357 */ 1334 -
kernel/generic/src/mm/slab.c
r6b1de7a r5f0f29ce 174 174 size_t fsize; 175 175 unsigned int i; 176 unsigned int zone = 0;176 count_t zone = 0; 177 177 178 178 data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
Note:
See TracChangeset
for help on using the changeset viewer.