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