Changes in kernel/generic/src/mm/frame.c [c5396c1:8cbf1c3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/mm/frame.c
rc5396c1 r8cbf1c3 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 two-level bitmap structure. 41 * 40 * The frame allocator is built on top of the buddy allocator. 41 * 42 * @see buddy.c 42 43 */ 43 44 … … 91 92 } 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 93 99 /** Initialize frame structure. 94 100 * … … 98 104 NO_TRACE static void frame_initialize(frame_t *frame) 99 105 { 100 frame->refcount = 0;101 frame-> parent = NULL;106 frame->refcount = 1; 107 frame->buddy_order = 0; 102 108 } 103 109 … … 155 161 156 162 /* Move other zones up */ 157 for (size_t j = zones.count; j > i; j--) 163 size_t j; 164 for (j = zones.count; j > i; j--) { 158 165 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 } 159 170 160 171 zones.count++; … … 226 237 } 227 238 228 /** @return True if zone can allocate specified number of frames */ 229 NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count, 230 pfn_t constraint) 231 { 232 /* 233 * The function bitmap_allocate_range() does not modify 234 * the bitmap if the last argument is NULL. 235 */ 239 /** @return True if zone can allocate specified order */ 240 NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order) 241 { 236 242 return ((zone->flags & ZONE_AVAILABLE) && 237 bitmap_allocate_range(&zone->bitmap, count, zone->base, 238 constraint, NULL)); 239 } 240 241 /** Find a zone that can allocate specified number of frames 243 buddy_system_can_alloc(zone->buddy_system, order)); 244 } 245 246 /** Find a zone that can allocate order frames. 242 247 * 243 248 * Assume interrupts are disabled and zones lock is 244 249 * locked. 245 250 * 246 * @param count Number of free frames we are trying to find. 247 * @param flags Required flags of the target zone. 248 * @param constraint Indication of bits that cannot be set in the 249 * physical frame number of the first allocated frame. 250 * @param hind Preferred zone. 251 * 252 */ 253 NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags, 254 pfn_t constraint, size_t hint) 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) 255 258 { 256 259 if (hint >= zones.count) … … 264 267 if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) { 265 268 /* 266 * Check if the zone can satisfy the allocation request.269 * Check if the zone has 2^order frames area available. 267 270 */ 268 if (zone_can_alloc(&zones.info[i], count, constraint))271 if (zone_can_alloc(&zones.info[i], order)) 269 272 return i; 270 273 } … … 279 282 } 280 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 }; 444 281 445 /******************/ 282 446 /* Zone functions */ 283 447 /******************/ 284 448 285 /** Return frame from zone. */286 NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)287 {288 ASSERT(index < zone->count);289 290 return &zone->frames[index];291 }292 293 449 /** Allocate frame in particular zone. 294 450 * … … 296 452 * Panics if allocation is impossible. 297 453 * 298 * @param zone Zone to allocate from. 299 * @param count Number of frames to allocate 300 * @param constraint Indication of bits that cannot be set in the 301 * physical frame number of the first allocated frame. 454 * @param zone Zone to allocate from. 455 * @param order Allocate exactly 2^order frames. 302 456 * 303 457 * @return Frame index in zone. 304 458 * 305 459 */ 306 NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count, 307 pfn_t constraint) 460 NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order) 308 461 { 309 462 ASSERT(zone->flags & ZONE_AVAILABLE); 310 463 311 /* Allocate frames from zone */ 312 size_t index; 313 int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base, 314 constraint, &index); 315 316 ASSERT(avail); 317 318 /* Update frame reference count */ 319 for (size_t i = 0; i < count; i++) { 320 frame_t *frame = zone_get_frame(zone, index + i); 321 322 ASSERT(frame->refcount == 0); 323 frame->refcount = 1; 324 } 464 /* Allocate frames from zone buddy system */ 465 link_t *link = buddy_system_alloc(zone->buddy_system, order); 466 467 ASSERT(link); 325 468 326 469 /* Update zone information. */ 327 zone->free_count -= count; 328 zone->busy_count += count; 329 330 return index; 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); 331 478 } 332 479 … … 335 482 * Assume zone is locked and is available for deallocation. 336 483 * 337 * @param zone Pointer to zone from which the frame is to be freed.338 * @param index Frame index relative to zone.339 * 340 * @return Number of freed frames.341 * 342 */ 343 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)484 * @param zone Pointer to zone from which the frame is to be freed. 485 * @param frame_idx Frame index relative to zone. 486 * 487 * @return Number of freed frames. 488 * 489 */ 490 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx) 344 491 { 345 492 ASSERT(zone->flags & ZONE_AVAILABLE); 346 493 347 frame_t *frame = zone_get_frame(zone, index); 348 349 ASSERT(frame->refcount > 0); 494 frame_t *frame = &zone->frames[frame_idx]; 495 size_t size = 0; 496 497 ASSERT(frame->refcount); 350 498 351 499 if (!--frame->refcount) { 352 bitmap_set(&zone->bitmap, index, 0);353 500 size = 1 << frame->buddy_order; 501 buddy_system_free(zone->buddy_system, &frame->buddy_link); 354 502 /* Update zone information. */ 355 zone->free_count++; 356 zone->busy_count--; 357 358 return 1; 359 } 360 361 return 0; 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]; 362 515 } 363 516 364 517 /** Mark frame in zone unavailable to allocation. */ 365 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)518 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx) 366 519 { 367 520 if (!(zone->flags & ZONE_AVAILABLE)) 368 521 return; 369 370 frame_t *frame = zone_get_frame(zone, index); 371 if (frame->refcount > 0) 522 // ASSERT(zone->flags & ZONE_AVAILABLE); 523 524 frame_t *frame = zone_get_frame(zone, frame_idx); 525 if (frame->refcount) 372 526 return; 373 527 374 frame->refcount = 1; 375 bitmap_set_range(&zone->bitmap, index, 1); 376 528 link_t *link __attribute__ ((unused)); 529 530 link = buddy_system_alloc_block(zone->buddy_system, 531 &frame->buddy_link); 532 533 ASSERT(link); 377 534 zone->free_count--; 378 535 reserve_force_alloc(1); … … 381 538 /** Merge two zones. 382 539 * 540 * Expect buddy to point to space at least zone_conf_size large. 383 541 * Assume z1 & z2 are locked and compatible and zones lock is 384 542 * locked. 385 543 * 386 * @param z1 387 * @param z2 388 * @param old_z1 Original dataof the first zone.389 * @param confdata Merged zone configuration data.544 * @param z1 First zone to merge. 545 * @param z2 Second zone to merge. 546 * @param old_z1 Original date of the first zone. 547 * @param buddy Merged zone buddy. 390 548 * 391 549 */ 392 550 NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1, 393 void *confdata)551 buddy_system_t *buddy) 394 552 { 395 553 ASSERT(zones.info[z1].flags & ZONE_AVAILABLE); … … 406 564 zones.info[z1].free_count += zones.info[z2].free_count; 407 565 zones.info[z1].busy_count += zones.info[z2].busy_count; 408 409 bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count, 410 confdata + (sizeof(frame_t) * zones.info[z1].count)); 411 bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count); 412 413 zones.info[z1].frames = (frame_t *) confdata; 414 415 /* 416 * Copy frames and bits from both zones to preserve parents, etc. 566 zones.info[z1].buddy_system = buddy; 567 568 uint8_t order = fnzb(zones.info[z1].count); 569 buddy_system_create(zones.info[z1].buddy_system, order, 570 &zone_buddy_system_operations, (void *) &zones.info[z1]); 571 572 zones.info[z1].frames = 573 (frame_t *) ((uint8_t *) zones.info[z1].buddy_system 574 + buddy_conf_size(order)); 575 576 /* This marks all frames busy */ 577 size_t i; 578 for (i = 0; i < zones.info[z1].count; i++) 579 frame_initialize(&zones.info[z1].frames[i]); 580 581 /* Copy frames from both zones to preserve full frame orders, 582 * parents etc. Set all free frames with refcount = 0 to 1, because 583 * we add all free frames to buddy allocator later again, clearing 584 * order to 0. Don't set busy frames with refcount = 0, as they 585 * will not be reallocated during merge and it would make later 586 * problems with allocation/free. 417 587 */ 418 419 for (size_t i = 0; i < old_z1->count; i++) { 420 bitmap_set(&zones.info[z1].bitmap, i, 421 bitmap_get(&old_z1->bitmap, i)); 588 for (i = 0; i < old_z1->count; i++) 422 589 zones.info[z1].frames[i] = old_z1->frames[i]; 423 } 424 425 for (size_t i = 0; i < zones.info[z2].count; i++) { 426 bitmap_set(&zones.info[z1].bitmap, base_diff + i, 427 bitmap_get(&zones.info[z2].bitmap, i)); 428 zones.info[z1].frames[base_diff + i] = 429 zones.info[z2].frames[i]; 590 591 for (i = 0; i < zones.info[z2].count; i++) 592 zones.info[z1].frames[base_diff + i] 593 = zones.info[z2].frames[i]; 594 595 i = 0; 596 while (i < zones.info[z1].count) { 597 if (zones.info[z1].frames[i].refcount) { 598 /* Skip busy frames */ 599 i += 1 << zones.info[z1].frames[i].buddy_order; 600 } else { 601 /* Free frames, set refcount = 1 602 * (all free frames have refcount == 0, we need not 603 * to check the order) 604 */ 605 zones.info[z1].frames[i].refcount = 1; 606 zones.info[z1].frames[i].buddy_order = 0; 607 i++; 608 } 609 } 610 611 /* Add free blocks from the original zone z1 */ 612 while (zone_can_alloc(old_z1, 0)) { 613 /* Allocate from the original zone */ 614 pfn_t frame_idx = zone_frame_alloc(old_z1, 0); 615 616 /* Free the frame from the merged zone */ 617 frame_t *frame = &zones.info[z1].frames[frame_idx]; 618 frame->refcount = 0; 619 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 620 } 621 622 /* Add free blocks from the original zone z2 */ 623 while (zone_can_alloc(&zones.info[z2], 0)) { 624 /* Allocate from the original zone */ 625 pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0); 626 627 /* Free the frame from the merged zone */ 628 frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx]; 629 frame->refcount = 0; 630 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link); 430 631 } 431 632 } … … 450 651 size_t cframes = SIZE2FRAMES(zone_conf_size(count)); 451 652 452 if ((pfn < zones.info[znum].base) ||453 (pfn >= zones.info[znum].base + zones.info[znum].count))653 if ((pfn < zones.info[znum].base) 654 || (pfn >= zones.info[znum].base + zones.info[znum].count)) 454 655 return; 455 656 456 for (size_t i = 0; i < cframes; i++) 657 frame_t *frame __attribute__ ((unused)); 658 659 frame = &zones.info[znum].frames[pfn - zones.info[znum].base]; 660 ASSERT(!frame->buddy_order); 661 662 size_t i; 663 for (i = 0; i < cframes; i++) { 664 zones.info[znum].busy_count++; 457 665 (void) zone_frame_free(&zones.info[znum], 458 666 pfn - zones.info[znum].base + i); 667 } 668 } 669 670 /** Reduce allocated block to count of order 0 frames. 671 * 672 * The allocated block needs 2^order frames. Reduce all frames 673 * in the block to order 0 and free the unneeded frames. This means that 674 * when freeing the previously allocated block starting with frame_idx, 675 * you have to free every frame. 676 * 677 * @param znum Zone. 678 * @param frame_idx Index the first frame of the block. 679 * @param count Allocated frames in block. 680 * 681 */ 682 NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx, 683 size_t count) 684 { 685 ASSERT(zones.info[znum].flags & ZONE_AVAILABLE); 686 ASSERT(frame_idx + count < zones.info[znum].count); 687 688 uint8_t order = zones.info[znum].frames[frame_idx].buddy_order; 689 ASSERT((size_t) (1 << order) >= count); 690 691 /* Reduce all blocks to order 0 */ 692 size_t i; 693 for (i = 0; i < (size_t) (1 << order); i++) { 694 frame_t *frame = &zones.info[znum].frames[i + frame_idx]; 695 frame->buddy_order = 0; 696 if (!frame->refcount) 697 frame->refcount = 1; 698 ASSERT(frame->refcount == 1); 699 } 700 701 /* Free unneeded frames */ 702 for (i = count; i < (size_t) (1 << order); i++) 703 (void) zone_frame_free(&zones.info[znum], i + frame_idx); 459 704 } 460 705 … … 476 721 bool ret = true; 477 722 478 /* 479 * We can join only 2 zones with none existing inbetween, 723 /* We can join only 2 zones with none existing inbetween, 480 724 * the zones have to be available and with the same 481 725 * set of flags … … 491 735 + zones.info[z2].count)); 492 736 737 uint8_t order; 738 if (cframes == 1) 739 order = 0; 740 else 741 order = fnzb(cframes - 1) + 1; 742 493 743 /* Allocate merged zone data inside one of the zones */ 494 744 pfn_t pfn; 495 if (zone_can_alloc(&zones.info[z1], cframes, 0)) { 496 pfn = zones.info[z1].base + 497 zone_frame_alloc(&zones.info[z1], cframes, 0); 498 } else if (zone_can_alloc(&zones.info[z2], cframes, 0)) { 499 pfn = zones.info[z2].base + 500 zone_frame_alloc(&zones.info[z2], cframes, 0); 745 if (zone_can_alloc(&zones.info[z1], order)) { 746 pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order); 747 } else if (zone_can_alloc(&zones.info[z2], order)) { 748 pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order); 501 749 } else { 502 750 ret = false; … … 506 754 /* Preserve original data from z1 */ 507 755 zone_t old_z1 = zones.info[z1]; 756 old_z1.buddy_system->data = (void *) &old_z1; 508 757 509 758 /* Do zone merging */ 510 zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn))); 759 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn)); 760 zone_merge_internal(z1, z2, &old_z1, buddy); 761 762 /* Free unneeded config frames */ 763 zone_reduce_region(z1, pfn - zones.info[z1].base, cframes); 511 764 512 765 /* Subtract zone information from busy frames */ … … 521 774 522 775 /* Move zones down */ 523 for (size_t i = z2 + 1; i < zones.count; i++) 776 size_t i; 777 for (i = z2 + 1; i < zones.count; i++) { 524 778 zones.info[i - 1] = zones.info[i]; 779 if (zones.info[i - 1].buddy_system != NULL) 780 zones.info[i - 1].buddy_system->data = 781 (void *) &zones.info[i - 1]; 782 } 525 783 526 784 zones.count--; … … 541 799 void zone_merge_all(void) 542 800 { 543 size_t i = 1; 544 801 size_t i = 0; 545 802 while (i < zones.count) { 546 if (!zone_merge(i - 1, i))803 if (!zone_merge(i, i + 1)) 547 804 i++; 548 805 } … … 551 808 /** Create new frame zone. 552 809 * 553 * @param zone 554 * @param start Physical address of the first frame within the zone.555 * @param count Count of frames inzone.556 * @param flags Zone flags.557 * @param confdata Configuration data of the zone.810 * @param zone Zone to construct. 811 * @param buddy Address of buddy system configuration information. 812 * @param start Physical address of the first frame within the zone. 813 * @param count Count of frames in zone. 814 * @param flags Zone flags. 558 815 * 559 816 * @return Initialized zone. 560 817 * 561 818 */ 562 NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,563 zone_flags_t flags, void *confdata)819 NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy, 820 pfn_t start, size_t count, zone_flags_t flags) 564 821 { 565 822 zone->base = start; … … 568 825 zone->free_count = count; 569 826 zone->busy_count = 0; 827 zone->buddy_system = buddy; 570 828 571 829 if (flags & ZONE_AVAILABLE) { 572 830 /* 573 * Initialize frame bitmap (located after the array of 574 * frame_t structures in the configuration space). 831 * Compute order for buddy system and initialize 575 832 */ 576 577 b itmap_initialize(&zone->bitmap, count, confdata +578 (sizeof(frame_t) * count));579 bitmap_clear_range(&zone->bitmap, 0, count);580 581 /*582 * Initialize the array of frame_t structures.583 */584 585 zone->frames = (frame_t *) confdata;586 587 for ( size_ti = 0; i < count; i++)833 uint8_t order = fnzb(count); 834 buddy_system_create(zone->buddy_system, order, 835 &zone_buddy_system_operations, (void *) zone); 836 837 /* Allocate frames _after_ the confframe */ 838 839 /* Check sizes */ 840 zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system + 841 buddy_conf_size(order)); 842 843 size_t i; 844 for (i = 0; i < count; i++) 588 845 frame_initialize(&zone->frames[i]); 589 } else { 590 bitmap_initialize(&zone->bitmap, 0, NULL); 846 847 /* Stuffing frames */ 848 for (i = 0; i < count; i++) { 849 zone->frames[i].refcount = 0; 850 buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link); 851 } 852 } else 591 853 zone->frames = NULL; 592 }593 854 } 594 855 … … 602 863 size_t zone_conf_size(size_t count) 603 864 { 604 return (count * sizeof(frame_t) + b itmap_size(count));865 return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count))); 605 866 } 606 867 … … 608 869 pfn_t zone_external_conf_alloc(size_t count) 609 870 { 610 size_t frames = SIZE2FRAMES(zone_conf_size(count)); 611 612 return ADDR2PFN((uintptr_t) 613 frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0)); 871 size_t size = zone_conf_size(count); 872 size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1); 873 874 return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH, 875 FRAME_LOWMEM | FRAME_ATOMIC, 0)); 614 876 } 615 877 … … 619 881 * @param count Size of zone in frames. 620 882 * @param confframe Where configuration frames are supposed to be. 621 * Automatically checks that we will not disturb the883 * Automatically checks, that we will not disturb the 622 884 * kernel and possibly init. If confframe is given 623 885 * _outside_ this zone, it is expected, that the area is … … 636 898 637 899 if (flags & ZONE_AVAILABLE) { /* Create available zone */ 638 /* 639 * Theoretically we could have NULL here, practically make sure 900 /* Theoretically we could have NULL here, practically make sure 640 901 * nobody tries to do that. If some platform requires, remove 641 902 * the assert 642 903 */ 643 904 ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL)); 644 905 645 906 /* Update the known end of physical memory. */ 646 907 config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count)); 647 908 648 /* 649 * If confframe is supposed to be inside our zone, then make sure 909 /* If confframe is supposed to be inside our zone, then make sure 650 910 * it does not span kernel & init 651 911 */ 652 912 size_t confcount = SIZE2FRAMES(zone_conf_size(count)); 653 654 913 if ((confframe >= start) && (confframe < start + count)) { 655 914 for (; confframe < start + count; confframe++) { … … 664 923 665 924 bool overlap = false; 666 for (size_t i = 0; i < init.cnt; i++) { 925 size_t i; 926 for (i = 0; i < init.cnt; i++) 667 927 if (overlaps(addr, PFN2ADDR(confcount), 668 928 init.tasks[i].paddr, … … 671 931 break; 672 932 } 673 }674 675 933 if (overlap) 676 934 continue; … … 679 937 } 680 938 681 if (confframe >= start + count) 682 panic("Cannot find configuration data for zone."); 939 if (confframe >= start + count) { 940 flags &= ~ZONE_AVAILABLE; 941 goto nonavail; 942 // panic("Cannot find configuration data for zone."); 943 } 683 944 } 684 945 … … 689 950 } 690 951 691 void *confdata = (void*) PA2KA(PFN2ADDR(confframe));692 zone_construct(&zones.info[znum], start, count, flags, confdata);952 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe)); 953 zone_construct(&zones.info[znum], buddy, start, count, flags); 693 954 694 955 /* If confdata in zone, mark as unavailable */ 695 956 if ((confframe >= start) && (confframe < start + count)) { 696 for (size_t i = confframe; i < confframe + confcount; i++) 957 size_t i; 958 for (i = confframe; i < confframe + confcount; i++) 697 959 zone_mark_unavailable(&zones.info[znum], 698 960 i - zones.info[znum].base); … … 703 965 return znum; 704 966 } 705 967 nonavail: 968 (void)0; // label trick 706 969 /* Non-available zone */ 707 970 size_t znum = zones_insert_zone(start, count, flags); … … 710 973 return (size_t) -1; 711 974 } 712 713 zone_construct(&zones.info[znum], start, count, flags, NULL); 975 zone_construct(&zones.info[znum], NULL, start, count, flags); 714 976 715 977 irq_spinlock_unlock(&zones.lock, true); … … 753 1015 } 754 1016 755 /** Allocate frames of physical memory. 756 * 757 * @param count Number of continuous frames to allocate. 758 * @param flags Flags for host zone selection and address processing. 759 * @param constraint Indication of physical address bits that cannot be 760 * set in the address of the first allocated frame. 761 * @param pzone Preferred zone. 1017 /** Allocate power-of-two frames of physical memory. 1018 * 1019 * @param order Allocate exactly 2^order frames. 1020 * @param flags Flags for host zone selection and address processing. 1021 * @param pzone Preferred zone. 762 1022 * 763 1023 * @return Physical address of the allocated frame. 764 1024 * 765 1025 */ 766 uintptr_t frame_alloc_generic( size_t count, frame_flags_t flags,1026 uintptr_t frame_alloc_generic(uint8_t order, frame_flags_t flags, 767 1027 uintptr_t constraint, size_t *pzone) 768 1028 { 769 ASSERT(count > 0); 770 1029 size_t size = ((size_t) 1) << order; 771 1030 size_t hint = pzone ? (*pzone) : 0; 772 pfn_t frame_constraint = ADDR2PFN(constraint);773 1031 774 1032 /* 775 1033 * If not told otherwise, we must first reserve the memory. 776 1034 */ 777 if (!(flags & FRAME_NO_RESERVE)) 778 reserve_force_alloc( count);779 1035 if (!(flags & FRAME_NO_RESERVE)) 1036 reserve_force_alloc(size); 1037 780 1038 loop: 781 1039 irq_spinlock_lock(&zones.lock, true); … … 784 1042 * First, find suitable frame zone. 785 1043 */ 786 size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags), 787 frame_constraint, hint); 788 789 /* 790 * If no memory, reclaim some slab memory, 791 * if it does not help, reclaim all. 792 */ 1044 size_t znum = find_free_zone(order, 1045 FRAME_TO_ZONE_FLAGS(flags), hint); 1046 1047 /* If no memory, reclaim some slab memory, 1048 if it does not help, reclaim all */ 793 1049 if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) { 794 1050 irq_spinlock_unlock(&zones.lock, true); … … 797 1053 798 1054 if (freed > 0) 799 znum = find_free_zone( count, FRAME_TO_ZONE_FLAGS(flags),800 frame_constraint, hint);1055 znum = find_free_zone(order, 1056 FRAME_TO_ZONE_FLAGS(flags), hint); 801 1057 802 1058 if (znum == (size_t) -1) { … … 806 1062 807 1063 if (freed > 0) 808 znum = find_free_zone( count, FRAME_TO_ZONE_FLAGS(flags),809 frame_constraint, hint);1064 znum = find_free_zone(order, 1065 FRAME_TO_ZONE_FLAGS(flags), hint); 810 1066 } 811 1067 } … … 814 1070 if (flags & FRAME_ATOMIC) { 815 1071 irq_spinlock_unlock(&zones.lock, true); 816 817 1072 if (!(flags & FRAME_NO_RESERVE)) 818 reserve_free(count); 819 1073 reserve_free(size); 820 1074 return 0; 821 1075 } … … 828 1082 829 1083 if (!THREAD) 830 panic("Cannot wait for %zu frames to become available " 831 "(%zu available).", count, avail); 1084 panic("Cannot wait for memory to become available."); 832 1085 833 1086 /* … … 836 1089 837 1090 #ifdef CONFIG_DEBUG 838 printf("Thread %" PRIu64 " waiting for %zu frames "839 " (%zu available).\n", THREAD->tid, count, avail);1091 printf("Thread %" PRIu64 " waiting for %zu frames, " 1092 "%zu available.\n", THREAD->tid, size, avail); 840 1093 #endif 841 1094 842 1095 /* 843 * Since the mem_avail_mtx is an active mutex, we need to 844 * disable interruptsto prevent deadlock with TLB shootdown.1096 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts 1097 * to prevent deadlock with TLB shootdown. 845 1098 */ 846 1099 ipl_t ipl = interrupts_disable(); … … 848 1101 849 1102 if (mem_avail_req > 0) 850 mem_avail_req = min(mem_avail_req, count);1103 mem_avail_req = min(mem_avail_req, size); 851 1104 else 852 mem_avail_req = count; 853 1105 mem_avail_req = size; 854 1106 size_t gen = mem_avail_gen; 855 1107 … … 867 1119 } 868 1120 869 pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,870 frame_constraint)+ zones.info[znum].base;1121 pfn_t pfn = zone_frame_alloc(&zones.info[znum], order) 1122 + zones.info[znum].base; 871 1123 872 1124 irq_spinlock_unlock(&zones.lock, true); … … 878 1130 } 879 1131 880 uintptr_t frame_alloc( size_t count, frame_flags_t flags, uintptr_t constraint)881 { 882 return frame_alloc_generic( count, flags, constraint, NULL);883 } 884 885 uintptr_t frame_alloc_noreserve( size_t count, frame_flags_t flags,1132 uintptr_t frame_alloc(uint8_t order, frame_flags_t flags, uintptr_t constraint) 1133 { 1134 return frame_alloc_generic(order, flags, constraint, NULL); 1135 } 1136 1137 uintptr_t frame_alloc_noreserve(uint8_t order, frame_flags_t flags, 886 1138 uintptr_t constraint) 887 1139 { 888 return frame_alloc_generic( count, flags | FRAME_NO_RESERVE, constraint,1140 return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, constraint, 889 1141 NULL); 890 1142 } 891 1143 892 /** Free frames of physical memory. 893 * 894 * Find respective frame structures for supplied physical frames. 895 * Decrement each frame reference count. If it drops to zero, mark 896 * the frames as available. 897 * 898 * @param start Physical Address of the first frame to be freed. 899 * @param count Number of frames to free. 1144 /** Free a frame. 1145 * 1146 * Find respective frame structure for supplied physical frame address. 1147 * Decrement frame reference count. If it drops to zero, move the frame 1148 * structure to free list. 1149 * 1150 * @param frame Physical Address of of the frame to be freed. 900 1151 * @param flags Flags to control memory reservation. 901 1152 * 902 1153 */ 903 void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)904 { 905 size_t freed = 0;1154 void frame_free_generic(uintptr_t frame, frame_flags_t flags) 1155 { 1156 size_t size; 906 1157 907 1158 irq_spinlock_lock(&zones.lock, true); 908 1159 909 for (size_t i = 0; i < count; i++) { 910 /* 911 * First, find host frame zone for addr. 912 */ 913 pfn_t pfn = ADDR2PFN(start) + i; 914 size_t znum = find_zone(pfn, 1, 0); 915 916 ASSERT(znum != (size_t) -1); 917 918 freed += zone_frame_free(&zones.info[znum], 919 pfn - zones.info[znum].base); 920 } 1160 /* 1161 * First, find host frame zone for addr. 1162 */ 1163 pfn_t pfn = ADDR2PFN(frame); 1164 size_t znum = find_zone(pfn, 1, 0); 1165 1166 ASSERT(znum != (size_t) -1); 1167 1168 size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base); 921 1169 922 1170 irq_spinlock_unlock(&zones.lock, true); … … 924 1172 /* 925 1173 * Signal that some memory has been freed. 926 * Since the mem_avail_mtx is an active mutex,927 * we need to disable interruptsto prevent deadlock928 * with TLB shootdown.929 1174 */ 930 1175 1176 1177 /* 1178 * Since the mem_avail_mtx is an active mutex, we need to disable interrupts 1179 * to prevent deadlock with TLB shootdown. 1180 */ 931 1181 ipl_t ipl = interrupts_disable(); 932 1182 mutex_lock(&mem_avail_mtx); 933 934 1183 if (mem_avail_req > 0) 935 mem_avail_req -= min(mem_avail_req, freed);1184 mem_avail_req -= min(mem_avail_req, size); 936 1185 937 1186 if (mem_avail_req == 0) { … … 939 1188 condvar_broadcast(&mem_avail_cv); 940 1189 } 941 942 1190 mutex_unlock(&mem_avail_mtx); 943 1191 interrupts_restore(ipl); 944 1192 945 1193 if (!(flags & FRAME_NO_RESERVE)) 946 reserve_free( freed);947 } 948 949 void frame_free(uintptr_t frame , size_t count)950 { 951 frame_free_generic(frame, count,0);952 } 953 954 void frame_free_noreserve(uintptr_t frame , size_t count)955 { 956 frame_free_generic(frame, count,FRAME_NO_RESERVE);1194 reserve_free(size); 1195 } 1196 1197 void frame_free(uintptr_t frame) 1198 { 1199 frame_free_generic(frame, 0); 1200 } 1201 1202 void frame_free_noreserve(uintptr_t frame) 1203 { 1204 frame_free_generic(frame, FRAME_NO_RESERVE); 957 1205 } 958 1206 … … 988 1236 irq_spinlock_lock(&zones.lock, true); 989 1237 990 for (size_t i = 0; i < count; i++) { 1238 size_t i; 1239 for (i = 0; i < count; i++) { 991 1240 size_t znum = find_zone(start + i, 1, 0); 992 993 1241 if (znum == (size_t) -1) /* PFN not found */ 994 1242 continue; … … 1015 1263 /* Tell the architecture to create some memory */ 1016 1264 frame_low_arch_init(); 1017 1018 1265 if (config.cpu_active == 1) { 1019 1266 frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), … … 1022 1269 SIZE2FRAMES(config.stack_size)); 1023 1270 1024 for (size_t i = 0; i < init.cnt; i++) 1025 frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr), 1271 size_t i; 1272 for (i = 0; i < init.cnt; i++) { 1273 pfn_t pfn = ADDR2PFN(init.tasks[i].paddr); 1274 frame_mark_unavailable(pfn, 1026 1275 SIZE2FRAMES(init.tasks[i].size)); 1276 } 1027 1277 1028 1278 if (ballocs.size) … … 1030 1280 SIZE2FRAMES(ballocs.size)); 1031 1281 1032 /* 1033 * Blacklist first frame, as allocating NULL would 1282 /* Black list first frame, as allocating NULL would 1034 1283 * fail in some places 1035 1284 */ 1036 1285 frame_mark_unavailable(0, 1); 1037 1286 } 1038 1039 1287 frame_high_arch_init(); 1040 1288 } … … 1042 1290 /** Adjust bounds of physical memory region according to low/high memory split. 1043 1291 * 1044 * @param low[in] If true, the adjustment is performed to make the region 1045 * fit in the low memory. Otherwise the adjustment is 1046 * performed to make the region fit in the high memory. 1047 * @param basep[inout] Pointer to a variable which contains the region's base 1048 * address and which may receive the adjusted base address. 1049 * @param sizep[inout] Pointer to a variable which contains the region's size 1050 * and which may receive the adjusted size. 1051 * 1052 * @return True if the region still exists even after the adjustment. 1053 * @return False otherwise. 1054 * 1292 * @param low[in] If true, the adjustment is performed to make the region 1293 * fit in the low memory. Otherwise the adjustment is 1294 * performed to make the region fit in the high memory. 1295 * @param basep[inout] Pointer to a variable which contains the region's base 1296 * address and which may receive the adjusted base address. 1297 * @param sizep[inout] Pointer to a variable which contains the region's size 1298 * and which may receive the adjusted size. 1299 * @retun True if the region still exists even after the 1300 * adjustment, false otherwise. 1055 1301 */ 1056 1302 bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep) 1057 1303 { 1058 1304 uintptr_t limit = KA2PA(config.identity_base) + config.identity_size; 1059 1305 1060 1306 if (low) { 1061 1307 if (*basep > limit) 1062 1308 return false; 1063 1064 1309 if (*basep + *sizep > limit) 1065 1310 *sizep = limit - *basep; … … 1067 1312 if (*basep + *sizep <= limit) 1068 1313 return false; 1069 1070 1314 if (*basep <= limit) { 1071 1315 *sizep -= limit - *basep; … … 1073 1317 } 1074 1318 } 1075 1076 1319 return true; 1077 1320 } … … 1085 1328 1086 1329 uint64_t total = 0; 1087 1088 for ( size_ti = 0; i < zones.count; i++)1330 size_t i; 1331 for (i = 0; i < zones.count; i++) 1089 1332 total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1090 1333 … … 1109 1352 *free = 0; 1110 1353 1111 for (size_t i = 0; i < zones.count; i++) { 1354 size_t i; 1355 for (i = 0; i < zones.count; i++) { 1112 1356 *total += (uint64_t) FRAMES2SIZE(zones.info[i].count); 1113 1357 … … 1146 1390 */ 1147 1391 1148 for (size_t i = 0;; i++) { 1392 size_t i; 1393 for (i = 0;; i++) { 1149 1394 irq_spinlock_lock(&zones.lock, true); 1150 1395 … … 1199 1444 size_t znum = (size_t) -1; 1200 1445 1201 for (size_t i = 0; i < zones.count; i++) { 1446 size_t i; 1447 for (i = 0; i < zones.count; i++) { 1202 1448 if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) { 1203 1449 znum = i; … … 1212 1458 } 1213 1459 1214 uintptr_t base = PFN2ADDR(zones.info[ znum].base);1215 zone_flags_t flags = zones.info[ znum].flags;1216 size_t count = zones.info[ znum].count;1217 size_t free_count = zones.info[ znum].free_count;1218 size_t busy_count = zones.info[ znum].busy_count;1460 uintptr_t base = PFN2ADDR(zones.info[i].base); 1461 zone_flags_t flags = zones.info[i].flags; 1462 size_t count = zones.info[i].count; 1463 size_t free_count = zones.info[i].free_count; 1464 size_t busy_count = zones.info[i].busy_count; 1219 1465 1220 1466 irq_spinlock_unlock(&zones.lock, true);
Note:
See TracChangeset
for help on using the changeset viewer.