Changes in kernel/generic/src/mm/frame.c [905721b:c12f891] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/frame.c
r905721b rc12f891 38 38 * 39 39 * This file contains the physical frame allocator and memory zone management. 40 * The frame allocator is built on top of the buddy allocator. 41 * 42 * @see buddy.c 40 * The frame allocator is built on top of the two-level bitmap structure. 41 * 43 42 */ 44 43 … … 55 54 #include <arch.h> 56 55 #include <print.h> 56 #include <log.h> 57 57 #include <align.h> 58 58 #include <mm/slab.h> … … 61 61 #include <config.h> 62 62 #include <str.h> 63 #include <proc/thread.h> /* THREAD */ 63 64 64 65 zones_t zones; … … 73 74 static size_t mem_avail_gen = 0; /**< Generation counter. */ 74 75 75 /********************/76 /* Helper functions */77 /********************/78 79 NO_TRACE static inline size_t frame_index(zone_t *zone, frame_t *frame)80 {81 return (size_t) (frame - zone->frames);82 }83 84 NO_TRACE static inline size_t frame_index_abs(zone_t *zone, frame_t *frame)85 {86 return (size_t) (frame - zone->frames) + zone->base;87 }88 89 NO_TRACE static inline bool frame_index_valid(zone_t *zone, size_t index)90 {91 return (index < zone->count);92 }93 94 NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)95 {96 return (frame - zone->frames);97 }98 99 76 /** Initialize frame structure. 100 77 * … … 104 81 NO_TRACE static void frame_initialize(frame_t *frame) 105 82 { 106 frame->refcount = 1;107 frame-> buddy_order = 0;83 frame->refcount = 0; 84 frame->parent = NULL; 108 85 } 109 86 … … 127 104 { 128 105 if (zones.count + 1 == ZONES_MAX) { 129 printf("Maximum zone count %u exceeded!\n", ZONES_MAX); 106 log(LF_OTHER, LVL_ERROR, "Maximum zone count %u exceeded!", 107 ZONES_MAX); 130 108 return (size_t) -1; 131 109 } … … 147 125 (!iswithin(zones.info[i].base, zones.info[i].count, 148 126 base, count))) { 149 printf("Zone (%p, %p) overlaps " 150 "with previous zone (%p %p)!\n", 127 log(LF_OTHER, LVL_WARN, 128 "Zone (%p, %p) overlaps " 129 "with previous zone (%p %p)!", 151 130 (void *) PFN2ADDR(base), (void *) PFN2ADDR(count), 152 131 (void *) PFN2ADDR(zones.info[i].base), … … 161 140 162 141 /* Move other zones up */ 163 size_t j; 164 for (j = zones.count; j > i; j--) { 142 for (size_t j = zones.count; j > i; j--) 165 143 zones.info[j] = zones.info[j - 1]; 166 if (zones.info[j].buddy_system != NULL)167 zones.info[j].buddy_system->data =168 (void *) &zones.info[j];169 }170 144 171 145 zones.count++; … … 237 211 } 238 212 239 /** @return True if zone can allocate specified order */ 240 NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order) 241 { 213 /** @return True if zone can allocate specified number of frames */ 214 NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count, 215 pfn_t constraint) 216 { 217 /* 218 * The function bitmap_allocate_range() does not modify 219 * the bitmap if the last argument is NULL. 220 */ 221 242 222 return ((zone->flags & ZONE_AVAILABLE) && 243 buddy_system_can_alloc(zone->buddy_system, order)); 244 } 245 246 /** Find a zone that can allocate order frames. 223 bitmap_allocate_range(&zone->bitmap, count, zone->base, 224 FRAME_LOWPRIO, constraint, NULL)); 225 } 226 227 /** Find a zone that can allocate specified number of frames 228 * 229 * This function searches among all zones. Assume interrupts are 230 * disabled and zones lock is locked. 231 * 232 * @param count Number of free frames we are trying to find. 233 * @param flags Required flags of the zone. 234 * @param constraint Indication of bits that cannot be set in the 235 * physical frame number of the first allocated frame. 236 * @param hint Preferred zone. 237 * 238 * @return Zone that can allocate specified number of frames. 239 * @return -1 if no zone can satisfy the request. 240 * 241 */ 242 NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags, 243 pfn_t constraint, size_t hint) 244 { 245 for (size_t pos = 0; pos < zones.count; pos++) { 246 size_t i = (pos + hint) % zones.count; 247 248 /* Check whether the zone meets the search criteria. */ 249 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) 250 continue; 251 252 /* Check if the zone can satisfy the allocation request. */ 253 if (zone_can_alloc(&zones.info[i], count, constraint)) 254 return i; 255 } 256 257 return (size_t) -1; 258 } 259 260 /** Check if frame range priority memory 261 * 262 * @param pfn Starting frame. 263 * @param count Number of frames. 264 * 265 * @return True if the range contains only priority memory. 266 * 267 */ 268 NO_TRACE static bool is_high_priority(pfn_t base, size_t count) 269 { 270 return (base + count <= FRAME_LOWPRIO); 271 } 272 273 /** Find a zone that can allocate specified number of frames 274 * 275 * This function ignores zones that contain only high-priority 276 * memory. Assume interrupts are disabled and zones lock is locked. 277 * 278 * @param count Number of free frames we are trying to find. 279 * @param flags Required flags of the zone. 280 * @param constraint Indication of bits that cannot be set in the 281 * physical frame number of the first allocated frame. 282 * @param hint Preferred zone. 283 * 284 * @return Zone that can allocate specified number of frames. 285 * @return -1 if no low-priority zone can satisfy the request. 286 * 287 */ 288 NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags, 289 pfn_t constraint, size_t hint) 290 { 291 for (size_t pos = 0; pos < zones.count; pos++) { 292 size_t i = (pos + hint) % zones.count; 293 294 /* Skip zones containing only high-priority memory. */ 295 if (is_high_priority(zones.info[i].base, zones.info[i].count)) 296 continue; 297 298 /* Check whether the zone meets the search criteria. */ 299 if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) 300 continue; 301 302 /* Check if the zone can satisfy the allocation request. */ 303 if (zone_can_alloc(&zones.info[i], count, constraint)) 304 return i; 305 } 306 307 return (size_t) -1; 308 } 309 310 /** Find a zone that can allocate specified number of frames 247 311 * 248 312 * Assume interrupts are disabled and zones lock is 249 313 * locked. 250 314 * 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 NO_TRACE static size_t find_free_zone(uint8_t order, zone_flags_t flags, 257 size_t hint) 315 * @param count Number of free frames we are trying to find. 316 * @param flags Required flags of the target zone. 317 * @param constraint Indication of bits that cannot be set in the 318 * physical frame number of the first allocated frame. 319 * @param hint Preferred zone. 320 * 321 * @return Zone that can allocate specified number of frames. 322 * @return -1 if no zone can satisfy the request. 323 * 324 */ 325 NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags, 326 pfn_t constraint, size_t hint) 258 327 { 259 328 if (hint >= zones.count) 260 329 hint = 0; 261 330 262 size_t i = hint; 263 do { 264 /* 265 * Check whether the zone meets the search criteria. 266 */ 267 if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) { 268 /* 269 * Check if the zone has 2^order frames area available. 270 */ 271 if (zone_can_alloc(&zones.info[i], order)) 272 return i; 273 } 274 275 i++; 276 if (i >= zones.count) 277 i = 0; 278 279 } while (i != hint); 280 281 return (size_t) -1; 282 } 283 284 /**************************/ 285 /* Buddy system functions */ 286 /**************************/ 287 288 /** Buddy system find_block implementation. 289 * 290 * Find block that is parent of current list. 291 * That means go to lower addresses, until such block is found 292 * 293 * @param order Order of parent must be different then this 294 * parameter!! 295 * 296 */ 297 NO_TRACE static link_t *zone_buddy_find_block(buddy_system_t *buddy, 298 link_t *child, uint8_t order) 299 { 300 frame_t *frame = list_get_instance(child, frame_t, buddy_link); 301 zone_t *zone = (zone_t *) buddy->data; 302 303 size_t index = frame_index(zone, frame); 304 do { 305 if (zone->frames[index].buddy_order != order) 306 return &zone->frames[index].buddy_link; 307 } while (index-- > 0); 308 309 return NULL; 310 } 311 312 /** Buddy system find_buddy implementation. 313 * 314 * @param buddy Buddy system. 315 * @param block Block for which buddy should be found. 316 * 317 * @return Buddy for given block if found. 318 * 319 */ 320 NO_TRACE static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, 321 link_t *block) 322 { 323 frame_t *frame = list_get_instance(block, frame_t, buddy_link); 324 zone_t *zone = (zone_t *) buddy->data; 325 ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame), 326 frame->buddy_order)); 327 328 bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame); 329 330 size_t index; 331 if (is_left) { 332 index = (frame_index(zone, frame)) + 333 (1 << frame->buddy_order); 334 } else { /* is_right */ 335 index = (frame_index(zone, frame)) - 336 (1 << frame->buddy_order); 337 } 338 339 if (frame_index_valid(zone, index)) { 340 if ((zone->frames[index].buddy_order == frame->buddy_order) && 341 (zone->frames[index].refcount == 0)) { 342 return &zone->frames[index].buddy_link; 343 } 344 } 345 346 return NULL; 347 } 348 349 /** Buddy system bisect implementation. 350 * 351 * @param buddy Buddy system. 352 * @param block Block to bisect. 353 * 354 * @return Right block. 355 * 356 */ 357 NO_TRACE 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))); 361 362 return &frame_r->buddy_link; 363 } 364 365 /** Buddy system coalesce implementation. 366 * 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 NO_TRACE static link_t *zone_buddy_coalesce(buddy_system_t *buddy, 376 link_t *block_1, 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); 382 } 383 384 /** Buddy system set_order implementation. 385 * 386 * @param buddy Buddy system. 387 * @param block Buddy system block. 388 * @param order Order to set. 389 * 390 */ 391 NO_TRACE static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block, 392 uint8_t order) 393 { 394 list_get_instance(block, frame_t, buddy_link)->buddy_order = order; 395 } 396 397 /** Buddy system get_order implementation. 398 * 399 * @param buddy Buddy system. 400 * @param block Buddy system block. 401 * 402 * @return Order of block. 403 * 404 */ 405 NO_TRACE static uint8_t zone_buddy_get_order(buddy_system_t *buddy, 406 link_t *block) 407 { 408 return list_get_instance(block, frame_t, buddy_link)->buddy_order; 409 } 410 411 /** Buddy system mark_busy implementation. 412 * 413 * @param buddy Buddy system. 414 * @param block Buddy system block. 415 * 416 */ 417 NO_TRACE static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t *block) 418 { 419 list_get_instance(block, frame_t, buddy_link)->refcount = 1; 420 } 421 422 /** Buddy system mark_available implementation. 423 * 424 * @param buddy Buddy system. 425 * @param block Buddy system block. 426 * 427 */ 428 NO_TRACE static void zone_buddy_mark_available(buddy_system_t *buddy, 429 link_t *block) 430 { 431 list_get_instance(block, frame_t, buddy_link)->refcount = 0; 432 } 433 434 static buddy_system_operations_t zone_buddy_system_operations = { 435 .find_buddy = zone_buddy_find_buddy, 436 .bisect = zone_buddy_bisect, 437 .coalesce = zone_buddy_coalesce, 438 .set_order = zone_buddy_set_order, 439 .get_order = zone_buddy_get_order, 440 .mark_busy = zone_buddy_mark_busy, 441 .mark_available = zone_buddy_mark_available, 442 .find_block = zone_buddy_find_block 443 }; 331 /* 332 * Prefer zones with low-priority memory over 333 * zones with high-priority memory. 334 */ 335 336 size_t znum = find_free_zone_lowprio(count, flags, constraint, hint); 337 if (znum != (size_t) -1) 338 return znum; 339 340 /* Take all zones into account */ 341 return find_free_zone_all(count, flags, constraint, hint); 342 } 444 343 445 344 /******************/ … … 447 346 /******************/ 448 347 348 /** Return frame from zone. */ 349 NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index) 350 { 351 ASSERT(index < zone->count); 352 353 return &zone->frames[index]; 354 } 355 449 356 /** Allocate frame in particular zone. 450 357 * … … 452 359 * Panics if allocation is impossible. 453 360 * 454 * @param zone Zone to allocate from. 455 * @param order Allocate exactly 2^order frames. 361 * @param zone Zone to allocate from. 362 * @param count Number of frames to allocate 363 * @param constraint Indication of bits that cannot be set in the 364 * physical frame number of the first allocated frame. 456 365 * 457 366 * @return Frame index in zone. 458 367 * 459 368 */ 460 NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order) 369 NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count, 370 pfn_t constraint) 461 371 { 462 372 ASSERT(zone->flags & ZONE_AVAILABLE); 463 373 464 /* Allocate frames from zone buddy system */ 465 link_t *link = buddy_system_alloc(zone->buddy_system, order); 466 467 ASSERT(link); 374 /* Allocate frames from zone */ 375 size_t index = (size_t) -1; 376 int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base, 377 FRAME_LOWPRIO, constraint, &index); 378 379 ASSERT(avail); 380 ASSERT(index != (size_t) -1); 381 382 /* Update frame reference count */ 383 for (size_t i = 0; i < count; i++) { 384 frame_t *frame = zone_get_frame(zone, index + i); 385 386 ASSERT(frame->refcount == 0); 387 frame->refcount = 1; 388 } 468 389 469 390 /* Update zone information. */ 470 zone->free_count -= (1 << order); 471 zone->busy_count += (1 << order); 472 473 /* Frame will be actually a first frame of the block. */ 474 frame_t *frame = list_get_instance(link, frame_t, buddy_link); 475 476 /* Get frame address */ 477 return make_frame_index(zone, frame); 391 zone->free_count -= count; 392 zone->busy_count += count; 393 394 return index; 478 395 } 479 396 … … 482 399 * Assume zone is locked and is available for deallocation. 483 400 * 484 * @param zone 485 * @param frame_idx Frame index relative to zone.486 * 487 * @return 488 * 489 */ 490 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)401 * @param zone Pointer to zone from which the frame is to be freed. 402 * @param index Frame index relative to zone. 403 * 404 * @return Number of freed frames. 405 * 406 */ 407 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index) 491 408 { 492 409 ASSERT(zone->flags & ZONE_AVAILABLE); 493 410 494 frame_t *frame = &zone->frames[frame_idx]; 495 size_t size = 0; 496 497 ASSERT(frame->refcount); 411 frame_t *frame = zone_get_frame(zone, index); 412 413 ASSERT(frame->refcount > 0); 498 414 499 415 if (!--frame->refcount) { 500 size = 1 << frame->buddy_order;501 buddy_system_free(zone->buddy_system, &frame->buddy_link);416 bitmap_set(&zone->bitmap, index, 0); 417 502 418 /* Update zone information. */ 503 zone->free_count += size; 504 zone->busy_count -= size; 505 } 506 507 return size; 508 } 509 510 /** Return frame from zone. */ 511 NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx) 512 { 513 ASSERT(frame_idx < zone->count); 514 return &zone->frames[frame_idx]; 419 zone->free_count++; 420 zone->busy_count--; 421 422 return 1; 423 } 424 425 return 0; 515 426 } 516 427 517 428 /** Mark frame in zone unavailable to allocation. */ 518 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)429 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index) 519 430 { 520 431 ASSERT(zone->flags & ZONE_AVAILABLE); 521 432 522 frame_t *frame = zone_get_frame(zone, frame_idx);523 if (frame->refcount )433 frame_t *frame = zone_get_frame(zone, index); 434 if (frame->refcount > 0) 524 435 return; 525 436 526 link_t *link __attribute__ ((unused)); 527 528 link = buddy_system_alloc_block(zone->buddy_system, 529 &frame->buddy_link); 530 531 ASSERT(link); 437 frame->refcount = 1; 438 bitmap_set_range(&zone->bitmap, index, 1); 439 532 440 zone->free_count--; 533 441 reserve_force_alloc(1); … … 536 444 /** Merge two zones. 537 445 * 538 * Expect buddy to point to space at least zone_conf_size large.539 446 * Assume z1 & z2 are locked and compatible and zones lock is 540 447 * locked. 541 448 * 542 * @param z1 First zone to merge.543 * @param z2 Second zone to merge.544 * @param old_z1 Original dateof the first zone.545 * @param buddy Merged zone buddy.449 * @param z1 First zone to merge. 450 * @param z2 Second zone to merge. 451 * @param old_z1 Original data of the first zone. 452 * @param confdata Merged zone configuration data. 546 453 * 547 454 */ 548 455 NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1, 549 buddy_system_t *buddy)456 void *confdata) 550 457 { 551 458 ASSERT(zones.info[z1].flags & ZONE_AVAILABLE); … … 562 469 zones.info[z1].free_count += zones.info[z2].free_count; 563 470 zones.info[z1].busy_count += zones.info[z2].busy_count; 564 zones.info[z1].buddy_system = buddy; 565 566 uint8_t order = fnzb(zones.info[z1].count); 567 buddy_system_create(zones.info[z1].buddy_system, order, 568 &zone_buddy_system_operations, (void *) &zones.info[z1]); 569 570 zones.info[z1].frames = 571 (frame_t *) ((uint8_t *) zones.info[z1].buddy_system 572 + buddy_conf_size(order)); 573 574 /* This marks all frames busy */ 575 size_t i; 576 for (i = 0; i < zones.info[z1].count; i++) 577 frame_initialize(&zones.info[z1].frames[i]); 578 579 /* Copy frames from both zones to preserve full frame orders, 580 * parents etc. Set all free frames with refcount = 0 to 1, because 581 * we add all free frames to buddy allocator later again, clearing 582 * order to 0. Don't set busy frames with refcount = 0, as they 583 * will not be reallocated during merge and it would make later 584 * problems with allocation/free. 471 472 bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count, 473 confdata + (sizeof(frame_t) * zones.info[z1].count)); 474 bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count); 475 476 zones.info[z1].frames = (frame_t *) confdata; 477 478 /* 479 * Copy frames and bits from both zones to preserve parents, etc. 585 480 */ 586 for (i = 0; i < old_z1->count; i++) 481 482 for (size_t i = 0; i < old_z1->count; i++) { 483 bitmap_set(&zones.info[z1].bitmap, i, 484 bitmap_get(&old_z1->bitmap, i)); 587 485 zones.info[z1].frames[i] = old_z1->frames[i]; 588 589 for (i = 0; i < zones.info[z2].count; i++) 590 zones.info[z1].frames[base_diff + i] 591 = zones.info[z2].frames[i]; 592 593 i = 0; 594 while (i < zones.info[z1].count) { 595 if (zones.info[z1].frames[i].refcount) { 596 /* Skip busy frames */ 597 i += 1 << zones.info[z1].frames[i].buddy_order; 598 } else { 599 /* Free frames, set refcount = 1 600 * (all free frames have refcount == 0, we need not 601 * to check the order) 602 */ 603 zones.info[z1].frames[i].refcount = 1; 604 zones.info[z1].frames[i].buddy_order = 0; 605 i++; 606 } 607 } 608 609 /* Add free blocks from the original zone z1 */ 610 while (zone_can_alloc(old_z1, 0)) { 611 /* Allocate from the original zone */ 612 pfn_t frame_idx = zone_frame_alloc(old_z1, 0); 613 614 /* Free the frame from the merged zone */ 615 frame_t *frame = &zones.info[z1].frames[frame_idx]; 616 frame->refcount = 0; 617 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 618 } 619 620 /* Add free blocks from the original zone z2 */ 621 while (zone_can_alloc(&zones.info[z2], 0)) { 622 /* Allocate from the original zone */ 623 pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0); 624 625 /* Free the frame from the merged zone */ 626 frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx]; 627 frame->refcount = 0; 628 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 486 } 487 488 for (size_t i = 0; i < zones.info[z2].count; i++) { 489 bitmap_set(&zones.info[z1].bitmap, base_diff + i, 490 bitmap_get(&zones.info[z2].bitmap, i)); 491 zones.info[z1].frames[base_diff + i] = 492 zones.info[z2].frames[i]; 629 493 } 630 494 } … … 649 513 size_t cframes = SIZE2FRAMES(zone_conf_size(count)); 650 514 651 if ((pfn < zones.info[znum].base) 652 ||(pfn >= zones.info[znum].base + zones.info[znum].count))515 if ((pfn < zones.info[znum].base) || 516 (pfn >= zones.info[znum].base + zones.info[znum].count)) 653 517 return; 654 518 655 frame_t *frame __attribute__ ((unused)); 656 657 frame = &zones.info[znum].frames[pfn - zones.info[znum].base]; 658 ASSERT(!frame->buddy_order); 659 660 size_t i; 661 for (i = 0; i < cframes; i++) { 662 zones.info[znum].busy_count++; 519 for (size_t i = 0; i < cframes; i++) 663 520 (void) zone_frame_free(&zones.info[znum], 664 521 pfn - zones.info[znum].base + i); 665 }666 }667 668 /** Reduce allocated block to count of order 0 frames.669 *670 * The allocated block needs 2^order frames. Reduce all frames671 * in the block to order 0 and free the unneeded frames. This means that672 * when freeing the previously allocated block starting with frame_idx,673 * you have to free every frame.674 *675 * @param znum Zone.676 * @param frame_idx Index the first frame of the block.677 * @param count Allocated frames in block.678 *679 */680 NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,681 size_t count)682 {683 ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);684 ASSERT(frame_idx + count < zones.info[znum].count);685 686 uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;687 ASSERT((size_t) (1 << order) >= count);688 689 /* Reduce all blocks to order 0 */690 size_t i;691 for (i = 0; i < (size_t) (1 << order); i++) {692 frame_t *frame = &zones.info[znum].frames[i + frame_idx];693 frame->buddy_order = 0;694 if (!frame->refcount)695 frame->refcount = 1;696 ASSERT(frame->refcount == 1);697 }698 699 /* Free unneeded frames */700 for (i = count; i < (size_t) (1 << order); i++)701 (void) zone_frame_free(&zones.info[znum], i + frame_idx);702 522 } 703 523 … … 719 539 bool ret = true; 720 540 721 /* We can join only 2 zones with none existing inbetween, 541 /* 542 * We can join only 2 zones with none existing inbetween, 722 543 * the zones have to be available and with the same 723 544 * set of flags … … 733 554 + zones.info[z2].count)); 734 555 735 uint8_t order;736 if (cframes == 1)737 order = 0;738 else739 order = fnzb(cframes - 1) + 1;740 741 556 /* Allocate merged zone data inside one of the zones */ 742 557 pfn_t pfn; 743 if (zone_can_alloc(&zones.info[z1], order)) { 744 pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order); 745 } else if (zone_can_alloc(&zones.info[z2], order)) { 746 pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order); 558 if (zone_can_alloc(&zones.info[z1], cframes, 0)) { 559 pfn = zones.info[z1].base + 560 zone_frame_alloc(&zones.info[z1], cframes, 0); 561 } else if (zone_can_alloc(&zones.info[z2], cframes, 0)) { 562 pfn = zones.info[z2].base + 563 zone_frame_alloc(&zones.info[z2], cframes, 0); 747 564 } else { 748 565 ret = false; … … 752 569 /* Preserve original data from z1 */ 753 570 zone_t old_z1 = zones.info[z1]; 754 old_z1.buddy_system->data = (void *) &old_z1;755 571 756 572 /* Do zone merging */ 757 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn)); 758 zone_merge_internal(z1, z2, &old_z1, buddy); 759 760 /* Free unneeded config frames */ 761 zone_reduce_region(z1, pfn - zones.info[z1].base, cframes); 573 zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn))); 762 574 763 575 /* Subtract zone information from busy frames */ … … 772 584 773 585 /* Move zones down */ 774 size_t i; 775 for (i = z2 + 1; i < zones.count; i++) { 586 for (size_t i = z2 + 1; i < zones.count; i++) 776 587 zones.info[i - 1] = zones.info[i]; 777 if (zones.info[i - 1].buddy_system != NULL)778 zones.info[i - 1].buddy_system->data =779 (void *) &zones.info[i - 1];780 }781 588 782 589 zones.count--; … … 797 604 void zone_merge_all(void) 798 605 { 799 size_t i = 0; 606 size_t i = 1; 607 800 608 while (i < zones.count) { 801 if (!zone_merge(i , i + 1))609 if (!zone_merge(i - 1, i)) 802 610 i++; 803 611 } … … 806 614 /** Create new frame zone. 807 615 * 808 * @param zone Zone to construct.809 * @param buddy Address of buddy system configuration information.810 * @param start Physical address of the first frame within thezone.811 * @param count Count of frames in zone.812 * @param flags Zone flags.616 * @param zone Zone to construct. 617 * @param start Physical address of the first frame within the zone. 618 * @param count Count of frames in zone. 619 * @param flags Zone flags. 620 * @param confdata Configuration data of the zone. 813 621 * 814 622 * @return Initialized zone. 815 623 * 816 624 */ 817 NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,818 pfn_t start, size_t count, zone_flags_t flags)625 NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count, 626 zone_flags_t flags, void *confdata) 819 627 { 820 628 zone->base = start; … … 823 631 zone->free_count = count; 824 632 zone->busy_count = 0; 825 zone->buddy_system = buddy;826 633 827 634 if (flags & ZONE_AVAILABLE) { 828 635 /* 829 * Compute order for buddy system and initialize 636 * Initialize frame bitmap (located after the array of 637 * frame_t structures in the configuration space). 830 638 */ 831 uint8_t order = fnzb(count);832 b uddy_system_create(zone->buddy_system, order,833 &zone_buddy_system_operations, (void *) zone);834 835 /* Allocate frames _after_ the confframe */836 837 /* Check sizes */838 zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +839 buddy_conf_size(order));840 841 size_t i;842 for ( i = 0; i < count; i++)639 640 bitmap_initialize(&zone->bitmap, count, confdata + 641 (sizeof(frame_t) * count)); 642 bitmap_clear_range(&zone->bitmap, 0, count); 643 644 /* 645 * Initialize the array of frame_t structures. 646 */ 647 648 zone->frames = (frame_t *) confdata; 649 650 for (size_t i = 0; i < count; i++) 843 651 frame_initialize(&zone->frames[i]); 844 845 /* Stuffing frames */ 846 for (i = 0; i < count; i++) { 847 zone->frames[i].refcount = 0; 848 buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link); 849 } 850 } else 652 } else { 653 bitmap_initialize(&zone->bitmap, 0, NULL); 851 654 zone->frames = NULL; 655 } 852 656 } 853 657 … … 861 665 size_t zone_conf_size(size_t count) 862 666 { 863 return (count * sizeof(frame_t) + b uddy_conf_size(fnzb(count)));667 return (count * sizeof(frame_t) + bitmap_size(count)); 864 668 } 865 669 … … 867 671 pfn_t zone_external_conf_alloc(size_t count) 868 672 { 869 size_t size = zone_conf_size(count); 870 size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1); 871 872 return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH, 873 FRAME_LOWMEM | FRAME_ATOMIC)); 673 size_t frames = SIZE2FRAMES(zone_conf_size(count)); 674 675 return ADDR2PFN((uintptr_t) 676 frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0)); 874 677 } 875 678 … … 879 682 * @param count Size of zone in frames. 880 683 * @param confframe Where configuration frames are supposed to be. 881 * Automatically checks ,that we will not disturb the684 * Automatically checks that we will not disturb the 882 685 * kernel and possibly init. If confframe is given 883 686 * _outside_ this zone, it is expected, that the area is … … 896 699 897 700 if (flags & ZONE_AVAILABLE) { /* Create available zone */ 898 /* Theoretically we could have NULL here, practically make sure 701 /* 702 * Theoretically we could have NULL here, practically make sure 899 703 * nobody tries to do that. If some platform requires, remove 900 704 * the assert 901 705 */ 902 706 ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL)); 903 707 904 708 /* Update the known end of physical memory. */ 905 709 config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count)); 906 710 907 /* If confframe is supposed to be inside our zone, then make sure 711 /* 712 * If confframe is supposed to be inside our zone, then make sure 908 713 * it does not span kernel & init 909 714 */ 910 715 size_t confcount = SIZE2FRAMES(zone_conf_size(count)); 716 911 717 if ((confframe >= start) && (confframe < start + count)) { 912 718 for (; confframe < start + count; confframe++) { … … 921 727 922 728 bool overlap = false; 923 size_t i; 924 for (i = 0; i < init.cnt; i++) 729 for (size_t i = 0; i < init.cnt; i++) { 925 730 if (overlaps(addr, PFN2ADDR(confcount), 926 731 init.tasks[i].paddr, … … 929 734 break; 930 735 } 736 } 737 931 738 if (overlap) 932 739 continue; … … 945 752 } 946 753 947 buddy_system_t *buddy = (buddy_system_t*) PA2KA(PFN2ADDR(confframe));948 zone_construct(&zones.info[znum], buddy, start, count, flags);754 void *confdata = (void *) PA2KA(PFN2ADDR(confframe)); 755 zone_construct(&zones.info[znum], start, count, flags, confdata); 949 756 950 757 /* If confdata in zone, mark as unavailable */ 951 758 if ((confframe >= start) && (confframe < start + count)) { 952 size_t i; 953 for (i = confframe; i < confframe + confcount; i++) 759 for (size_t i = confframe; i < confframe + confcount; i++) 954 760 zone_mark_unavailable(&zones.info[znum], 955 761 i - zones.info[znum].base); … … 967 773 return (size_t) -1; 968 774 } 969 zone_construct(&zones.info[znum], NULL, start, count, flags); 775 776 zone_construct(&zones.info[znum], start, count, flags, NULL); 970 777 971 778 irq_spinlock_unlock(&zones.lock, true); … … 1009 816 } 1010 817 1011 /** Allocate power-of-two frames of physical memory. 1012 * 1013 * @param order Allocate exactly 2^order frames. 1014 * @param flags Flags for host zone selection and address processing. 1015 * @param pzone Preferred zone. 818 /** Allocate frames of physical memory. 819 * 820 * @param count Number of continuous frames to allocate. 821 * @param flags Flags for host zone selection and address processing. 822 * @param constraint Indication of physical address bits that cannot be 823 * set in the address of the first allocated frame. 824 * @param pzone Preferred zone. 1016 825 * 1017 826 * @return Physical address of the allocated frame. 1018 827 * 1019 828 */ 1020 void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone) 1021 { 1022 size_t size = ((size_t) 1) << order; 829 uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags, 830 uintptr_t constraint, size_t *pzone) 831 { 832 ASSERT(count > 0); 833 1023 834 size_t hint = pzone ? (*pzone) : 0; 835 pfn_t frame_constraint = ADDR2PFN(constraint); 1024 836 1025 837 /* 1026 838 * If not told otherwise, we must first reserve the memory. 1027 839 */ 1028 if (!(flags & FRAME_NO_RESERVE)) 1029 reserve_force_alloc( size);1030 840 if (!(flags & FRAME_NO_RESERVE)) 841 reserve_force_alloc(count); 842 1031 843 loop: 1032 844 irq_spinlock_lock(&zones.lock, true); … … 1035 847 * First, find suitable frame zone. 1036 848 */ 1037 size_t znum = find_free_zone(order, 1038 FRAME_TO_ZONE_FLAGS(flags), hint); 1039 1040 /* If no memory, reclaim some slab memory, 1041 if it does not help, reclaim all */ 849 size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), 850 frame_constraint, hint); 851 852 /* 853 * If no memory, reclaim some slab memory, 854 * if it does not help, reclaim all. 855 */ 1042 856 if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { 1043 857 irq_spinlock_unlock(&zones.lock, true); … … 1046 860 1047 861 if (freed > 0) 1048 znum = find_free_zone( order,1049 FRAME_TO_ZONE_FLAGS(flags), hint);862 znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), 863 frame_constraint, hint); 1050 864 1051 865 if (znum == (size_t) -1) { … … 1055 869 1056 870 if (freed > 0) 1057 znum = find_free_zone( order,1058 FRAME_TO_ZONE_FLAGS(flags), hint);871 znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), 872 frame_constraint, hint); 1059 873 } 1060 874 } … … 1063 877 if (flags & FRAME_ATOMIC) { 1064 878 irq_spinlock_unlock(&zones.lock, true); 879 1065 880 if (!(flags & FRAME_NO_RESERVE)) 1066 reserve_free(size); 1067 return NULL; 881 reserve_free(count); 882 883 return 0; 1068 884 } 1069 885 1070 #ifdef CONFIG_DEBUG1071 886 size_t avail = frame_total_free_get_internal(); 1072 #endif1073 887 1074 888 irq_spinlock_unlock(&zones.lock, true); 1075 889 1076 890 if (!THREAD) 1077 panic("Cannot wait for memory to become available."); 891 panic("Cannot wait for %zu frames to become available " 892 "(%zu available).", count, avail); 1078 893 1079 894 /* … … 1082 897 1083 898 #ifdef CONFIG_DEBUG 1084 printf("Thread %" PRIu64 " waiting for %zu frames, " 1085 "%zu available.\n", THREAD->tid, size, avail); 899 log(LF_OTHER, LVL_DEBUG, 900 "Thread %" PRIu64 " waiting for %zu frames " 901 "%zu available.", THREAD->tid, count, avail); 1086 902 #endif 1087 903 1088 904 /* 1089 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts1090 * to prevent deadlock with TLB shootdown.905 * Since the mem_avail_mtx is an active mutex, we need to 906 * disable interrupts to prevent deadlock with TLB shootdown. 1091 907 */ 1092 908 ipl_t ipl = interrupts_disable(); … … 1094 910 1095 911 if (mem_avail_req > 0) 1096 mem_avail_req = min(mem_avail_req, size);912 mem_avail_req = min(mem_avail_req, count); 1097 913 else 1098 mem_avail_req = size; 914 mem_avail_req = count; 915 1099 916 size_t gen = mem_avail_gen; 1100 917 … … 1106 923 1107 924 #ifdef CONFIG_DEBUG 1108 printf("Thread %" PRIu64 " woken up.\n", THREAD->tid); 925 log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " woken up.", 926 THREAD->tid); 1109 927 #endif 1110 928 … … 1112 930 } 1113 931 1114 pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)1115 + zones.info[znum].base;932 pfn_t pfn = zone_frame_alloc(&zones.info[znum], count, 933 frame_constraint) + zones.info[znum].base; 1116 934 1117 935 irq_spinlock_unlock(&zones.lock, true); … … 1120 938 *pzone = znum; 1121 939 1122 if (flags & FRAME_KA) 1123 return (void *) PA2KA(PFN2ADDR(pfn)); 1124 1125 return (void *) PFN2ADDR(pfn); 1126 } 1127 1128 void *frame_alloc(uint8_t order, frame_flags_t flags) 1129 { 1130 return frame_alloc_generic(order, flags, NULL); 1131 } 1132 1133 void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags) 1134 { 1135 return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL); 1136 } 1137 1138 /** Free a frame. 1139 * 1140 * Find respective frame structure for supplied physical frame address. 1141 * Decrement frame reference count. If it drops to zero, move the frame 1142 * structure to free list. 1143 * 1144 * @param frame Physical Address of of the frame to be freed. 940 return PFN2ADDR(pfn); 941 } 942 943 uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint) 944 { 945 return frame_alloc_generic(count, flags, constraint, NULL); 946 } 947 948 /** Free frames of physical memory. 949 * 950 * Find respective frame structures for supplied physical frames. 951 * Decrement each frame reference count. If it drops to zero, mark 952 * the frames as available. 953 * 954 * @param start Physical Address of the first frame to be freed. 955 * @param count Number of frames to free. 1145 956 * @param flags Flags to control memory reservation. 1146 957 * 1147 958 */ 1148 void frame_free_generic(uintptr_t frame, frame_flags_t flags)1149 { 1150 size_t size;959 void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags) 960 { 961 size_t freed = 0; 1151 962 1152 963 irq_spinlock_lock(&zones.lock, true); 1153 964 1154 /* 1155 * First, find host frame zone for addr. 1156 */ 1157 pfn_t pfn = ADDR2PFN(frame); 1158 size_t znum = find_zone(pfn, 1, 0); 1159 1160 ASSERT(znum != (size_t) -1); 1161 1162 size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); 965 for (size_t i = 0; i < count; i++) { 966 /* 967 * First, find host frame zone for addr. 968 */ 969 pfn_t pfn = ADDR2PFN(start) + i; 970 size_t znum = find_zone(pfn, 1, 0); 971 972 ASSERT(znum != (size_t) -1); 973 974 freed += zone_frame_free(&zones.info[znum], 975 pfn - zones.info[znum].base); 976 } 1163 977 1164 978 irq_spinlock_unlock(&zones.lock, true); … … 1166 980 /* 1167 981 * Signal that some memory has been freed. 982 * Since the mem_avail_mtx is an active mutex, 983 * we need to disable interruptsto prevent deadlock 984 * with TLB shootdown. 1168 985 */ 1169 1170 1171 /* 1172 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts 1173 * to prevent deadlock with TLB shootdown. 1174 */ 986 1175 987 ipl_t ipl = interrupts_disable(); 1176 988 mutex_lock(&mem_avail_mtx); 989 1177 990 if (mem_avail_req > 0) 1178 mem_avail_req -= min(mem_avail_req, size);991 mem_avail_req -= min(mem_avail_req, freed); 1179 992 1180 993 if (mem_avail_req == 0) { … … 1182 995 condvar_broadcast(&mem_avail_cv); 1183 996 } 997 1184 998 mutex_unlock(&mem_avail_mtx); 1185 999 interrupts_restore(ipl); 1186 1000 1187 1001 if (!(flags & FRAME_NO_RESERVE)) 1188 reserve_free( size);1189 } 1190 1191 void frame_free(uintptr_t frame )1192 { 1193 frame_free_generic(frame, 0);1194 } 1195 1196 void frame_free_noreserve(uintptr_t frame )1197 { 1198 frame_free_generic(frame, FRAME_NO_RESERVE);1002 reserve_free(freed); 1003 } 1004 1005 void frame_free(uintptr_t frame, size_t count) 1006 { 1007 frame_free_generic(frame, count, 0); 1008 } 1009 1010 void frame_free_noreserve(uintptr_t frame, size_t count) 1011 { 1012 frame_free_generic(frame, count, FRAME_NO_RESERVE); 1199 1013 } 1200 1014 … … 1230 1044 irq_spinlock_lock(&zones.lock, true); 1231 1045 1232 size_t i; 1233 for (i = 0; i < count; i++) { 1046 for (size_t i = 0; i < count; i++) { 1234 1047 size_t znum = find_zone(start + i, 1, 0); 1048 1235 1049 if (znum == (size_t) -1) /* PFN not found */ 1236 1050 continue; … … 1257 1071 /* Tell the architecture to create some memory */ 1258 1072 frame_low_arch_init(); 1073 1259 1074 if (config.cpu_active == 1) { 1260 1075 frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), … … 1263 1078 SIZE2FRAMES(config.stack_size)); 1264 1079 1265 size_t i; 1266 for (i = 0; i < init.cnt; i++) { 1267 pfn_t pfn = ADDR2PFN(init.tasks[i].paddr); 1268 frame_mark_unavailable(pfn, 1080 for (size_t i = 0; i < init.cnt; i++) 1081 frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr), 1269 1082 SIZE2FRAMES(init.tasks[i].size)); 1270 }1271 1083 1272 1084 if (ballocs.size) … … 1274 1086 SIZE2FRAMES(ballocs.size)); 1275 1087 1276 /* Black list first frame, as allocating NULL would 1088 /* 1089 * Blacklist first frame, as allocating NULL would 1277 1090 * fail in some places 1278 1091 */ 1279 1092 frame_mark_unavailable(0, 1); 1280 1093 } 1094 1281 1095 frame_high_arch_init(); 1282 1096 } … … 1284 1098 /** Adjust bounds of physical memory region according to low/high memory split. 1285 1099 * 1286 * @param low[in] If true, the adjustment is performed to make the region 1287 * fit in the low memory. Otherwise the adjustment is 1288 * performed to make the region fit in the high memory. 1289 * @param basep[inout] Pointer to a variable which contains the region's base 1290 * address and which may receive the adjusted base address. 1291 * @param sizep[inout] Pointer to a variable which contains the region's size 1292 * and which may receive the adjusted size. 1293 * @retun True if the region still exists even after the 1294 * adjustment, false otherwise. 1100 * @param low[in] If true, the adjustment is performed to make the region 1101 * fit in the low memory. Otherwise the adjustment is 1102 * performed to make the region fit in the high memory. 1103 * @param basep[inout] Pointer to a variable which contains the region's base 1104 * address and which may receive the adjusted base address. 1105 * @param sizep[inout] Pointer to a variable which contains the region's size 1106 * and which may receive the adjusted size. 1107 * 1108 * @return True if the region still exists even after the adjustment. 1109 * @return False otherwise. 1110 * 1295 1111 */ 1296 1112 bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep) 1297 1113 { 1298 1114 uintptr_t limit = KA2PA(config.identity_base) + config.identity_size; 1299 1115 1300 1116 if (low) { 1301 1117 if (*basep > limit) 1302 1118 return false; 1119 1303 1120 if (*basep + *sizep > limit) 1304 1121 *sizep = limit - *basep; … … 1306 1123 if (*basep + *sizep <= limit) 1307 1124 return false; 1125 1308 1126 if (*basep <= limit) { 1309 1127 *sizep -= limit - *basep; … … 1311 1129 } 1312 1130 } 1131 1313 1132 return true; 1314 1133 } … … 1322 1141 1323 1142 uint64_t total = 0; 1324 size_t i;1325 for ( i = 0; i < zones.count; i++)1143 1144 for (size_t i = 0; i < zones.count; i++) 1326 1145 total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1327 1146 … … 1346 1165 *free = 0; 1347 1166 1348 size_t i; 1349 for (i = 0; i < zones.count; i++) { 1167 for (size_t i = 0; i < zones.count; i++) { 1350 1168 *total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1351 1169 … … 1375 1193 /* 1376 1194 * Because printing may require allocation of memory, we may not hold 1377 * the frame allocator locks when printing zone statistics. 1195 * the frame allocator locks when printing zone statistics. Therefore, 1378 1196 * we simply gather the statistics under the protection of the locks and 1379 1197 * print the statistics when the locks have been released. … … 1384 1202 */ 1385 1203 1386 size_t i; 1387 for (i = 0;; i++) { 1204 size_t free_lowmem = 0; 1205 size_t free_highmem = 0; 1206 size_t free_highprio = 0; 1207 1208 for (size_t i = 0;; i++) { 1388 1209 irq_spinlock_lock(&zones.lock, true); 1389 1210 … … 1393 1214 } 1394 1215 1395 uintptr_t base = PFN2ADDR(zones.info[i].base); 1216 pfn_t fbase = zones.info[i].base; 1217 uintptr_t base = PFN2ADDR(fbase); 1396 1218 size_t count = zones.info[i].count; 1397 1219 zone_flags_t flags = zones.info[i].flags; … … 1399 1221 size_t busy_count = zones.info[i].busy_count; 1400 1222 1223 bool available = ((flags & ZONE_AVAILABLE) != 0); 1224 bool lowmem = ((flags & ZONE_LOWMEM) != 0); 1225 bool highmem = ((flags & ZONE_HIGHMEM) != 0); 1226 bool highprio = is_high_priority(fbase, count); 1227 1228 if (available) { 1229 if (lowmem) 1230 free_lowmem += free_count; 1231 1232 if (highmem) 1233 free_highmem += free_count; 1234 1235 if (highprio) { 1236 free_highprio += free_count; 1237 } else { 1238 /* 1239 * Walk all frames of the zone and examine 1240 * all high priority memory to get accurate 1241 * statistics. 1242 */ 1243 1244 for (size_t index = 0; index < count; index++) { 1245 if (is_high_priority(fbase + index, 0)) { 1246 if (!bitmap_get(&zones.info[i].bitmap, index)) 1247 free_highprio++; 1248 } else 1249 break; 1250 } 1251 } 1252 } 1253 1401 1254 irq_spinlock_unlock(&zones.lock, true); 1402 1403 bool available = ((flags & ZONE_AVAILABLE) != 0);1404 1255 1405 1256 printf("%-4zu", i); … … 1426 1277 printf("\n"); 1427 1278 } 1279 1280 printf("\n"); 1281 1282 uint64_t size; 1283 const char *size_suffix; 1284 1285 bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix, 1286 false); 1287 printf("Available low memory: %zu frames (%" PRIu64 " %s)\n", 1288 free_lowmem, size, size_suffix); 1289 1290 bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix, 1291 false); 1292 printf("Available high memory: %zu frames (%" PRIu64 " %s)\n", 1293 free_highmem, size, size_suffix); 1294 1295 bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix, 1296 false); 1297 printf("Available high priority: %zu frames (%" PRIu64 " %s)\n", 1298 free_highprio, size, size_suffix); 1428 1299 } 1429 1300 … … 1438 1309 size_t znum = (size_t) -1; 1439 1310 1440 size_t i; 1441 for (i = 0; i < zones.count; i++) { 1311 for (size_t i = 0; i < zones.count; i++) { 1442 1312 if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) { 1443 1313 znum = i; … … 1452 1322 } 1453 1323 1454 uintptr_t base = PFN2ADDR(zones.info[i].base); 1455 zone_flags_t flags = zones.info[i].flags; 1456 size_t count = zones.info[i].count; 1457 size_t free_count = zones.info[i].free_count; 1458 size_t busy_count = zones.info[i].busy_count; 1324 size_t free_lowmem = 0; 1325 size_t free_highmem = 0; 1326 size_t free_highprio = 0; 1327 1328 pfn_t fbase = zones.info[znum].base; 1329 uintptr_t base = PFN2ADDR(fbase); 1330 zone_flags_t flags = zones.info[znum].flags; 1331 size_t count = zones.info[znum].count; 1332 size_t free_count = zones.info[znum].free_count; 1333 size_t busy_count = zones.info[znum].busy_count; 1334 1335 bool available = ((flags & ZONE_AVAILABLE) != 0); 1336 bool lowmem = ((flags & ZONE_LOWMEM) != 0); 1337 bool highmem = ((flags & ZONE_HIGHMEM) != 0); 1338 bool highprio = is_high_priority(fbase, count); 1339 1340 if (available) { 1341 if (lowmem) 1342 free_lowmem = free_count; 1343 1344 if (highmem) 1345 free_highmem = free_count; 1346 1347 if (highprio) { 1348 free_highprio = free_count; 1349 } else { 1350 /* 1351 * Walk all frames of the zone and examine 1352 * all high priority memory to get accurate 1353 * statistics. 1354 */ 1355 1356 for (size_t index = 0; index < count; index++) { 1357 if (is_high_priority(fbase + index, 0)) { 1358 if (!bitmap_get(&zones.info[znum].bitmap, index)) 1359 free_highprio++; 1360 } else 1361 break; 1362 } 1363 } 1364 } 1459 1365 1460 1366 irq_spinlock_unlock(&zones.lock, true); 1461 1462 bool available = ((flags & ZONE_AVAILABLE) != 0);1463 1367 1464 1368 uint64_t size; 1465 1369 const char *size_suffix; 1370 1466 1371 bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false); 1467 1372 1468 printf("Zone number: %zu\n", znum);1469 printf("Zone base address: %p\n", (void *) base);1470 printf("Zone size: %zu frames (%" PRIu64 " %s)\n", count,1373 printf("Zone number: %zu\n", znum); 1374 printf("Zone base address: %p\n", (void *) base); 1375 printf("Zone size: %zu frames (%" PRIu64 " %s)\n", count, 1471 1376 size, size_suffix); 1472 printf("Zone flags: %c%c%c%c%c\n",1377 printf("Zone flags: %c%c%c%c%c\n", 1473 1378 available ? 'A' : '-', 1474 1379 (flags & ZONE_RESERVED) ? 'R' : '-', … … 1480 1385 bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix, 1481 1386 false); 1482 printf("Allocated space: %zu frames (%" PRIu64 " %s)\n",1387 printf("Allocated space: %zu frames (%" PRIu64 " %s)\n", 1483 1388 busy_count, size, size_suffix); 1389 1484 1390 bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix, 1485 1391 false); 1486 printf("Available space: %zu frames (%" PRIu64 " %s)\n",1392 printf("Available space: %zu frames (%" PRIu64 " %s)\n", 1487 1393 free_count, size, size_suffix); 1394 1395 bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix, 1396 false); 1397 printf("Available low memory: %zu frames (%" PRIu64 " %s)\n", 1398 free_lowmem, size, size_suffix); 1399 1400 bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix, 1401 false); 1402 printf("Available high memory: %zu frames (%" PRIu64 " %s)\n", 1403 free_highmem, size, size_suffix); 1404 1405 bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix, 1406 false); 1407 printf("Available high priority: %zu frames (%" PRIu64 " %s)\n", 1408 free_highprio, size, size_suffix); 1488 1409 } 1489 1410 }
Note:
See TracChangeset
for help on using the changeset viewer.