Changeset bb68433 in mainline for generic/src/mm/frame.c
- Timestamp:
- 2006-02-08T22:58:06Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7e4e532
- Parents:
- 85dc2e7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/src/mm/frame.c
r85dc2e7 rbb68433 51 51 #include <align.h> 52 52 #include <mm/slab.h> 53 #include <bitops.h> 53 54 54 55 typedef struct { … … 122 123 /** 123 124 * Insert-sort zone into zones list 124 */ 125 static void zones_add_zone(zone_t *zone) 126 { 127 int i; 128 125 * 126 * @return zone number on success, -1 on error 127 */ 128 static int zones_add_zone(zone_t *newzone) 129 { 130 int i,j; 131 ipl_t ipl; 132 zone_t *z; 133 134 ipl = interrupts_disable(); 129 135 spinlock_lock(&zones.lock); 130 136 /* Try to merge */ 131 if (zone->flags & ZONE_JOIN) { 132 for (i=0; i < zones.count; i++) { 133 spinlock_lock(&zones.info[i]->lock); 134 135 /* Join forward, join backward */ 136 panic("Not implemented"); 137 138 spinlock_unlock(&zones.info[i]->lock); 137 if (zones.count+1 == ZONES_MAX) 138 panic("Maximum zone(%d) count exceeded.", ZONES_MAX); 139 140 for (i=0; i < zones.count; i++) { 141 /* Check for overflow */ 142 z = zones.info[zones.count]; 143 if (overlaps(newzone->base,newzone->count, 144 z->base, z->count)) { 145 printf("Zones overlap!\n"); 146 return -1; 139 147 } 140 spinlock_unlock(&zones.lock); 141 } else { 142 if (zones.count+1 == ZONES_MAX) 143 panic("Maximum zone(%d) count exceeded.", ZONES_MAX); 144 zones.info[zones.count++] = zone; 145 } 148 if (z->base < newzone->base) 149 break; 150 } 151 /* Move other zones up */ 152 for (j=i;j < zones.count;j++) 153 zones.info[j+1] = zones.info[j]; 154 155 zones.info[i] = newzone; 156 zones.count++; 157 146 158 spinlock_unlock(&zones.lock); 159 interrupts_restore(ipl); 160 161 return i; 147 162 } 148 163 … … 187 202 } 188 203 204 /** @return True if zone can allocate specified order */ 205 static int zone_can_alloc(zone_t *z, __u8 order) 206 { 207 return buddy_system_can_alloc(z->buddy_system, order); 208 } 209 189 210 /** 190 211 * Find AND LOCK zone that can allocate order frames … … 210 231 211 232 /* Check if the zone has 2^order frames area available */ 212 if ( buddy_system_can_alloc(z->buddy_system, order)) {233 if (zone_can_alloc(z, order)) { 213 234 spinlock_unlock(&zones.lock); 214 235 if (pzone) … … 253 274 } 254 275 255 276 static void zone_buddy_print_id(buddy_system_t *b, link_t *block) 277 { 278 frame_t * frame; 279 zone_t * zone; 280 index_t index; 281 282 frame = list_get_instance(block, frame_t, buddy_link); 283 zone = (zone_t *) b->data; 284 index = frame_index(zone, frame); 285 printf("%d", index); 286 } 256 287 257 288 /** Buddy system find_buddy implementation … … 319 350 */ 320 351 static link_t * zone_buddy_coalesce(buddy_system_t *b, link_t * block_1, 321 link_t * block_2) { 352 link_t * block_2) 353 { 322 354 frame_t *frame1, *frame2; 323 355 … … 361 393 static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) { 362 394 frame_t * frame; 395 363 396 frame = list_get_instance(block, frame_t, buddy_link); 364 397 frame->refcount = 1; … … 385 418 .mark_busy = zone_buddy_mark_busy, 386 419 .mark_available = zone_buddy_mark_available, 387 .find_block = zone_buddy_find_block 420 .find_block = zone_buddy_find_block, 421 .print_id = zone_buddy_print_id 388 422 }; 389 423 … … 394 428 * 395 429 * Assume zone is locked 430 * Panics, if allocation is impossible. 396 431 * 397 432 * @return Frame index in zone 398 433 */ 399 static pfn_t zone_frame_alloc(zone_t *zone,__u8 order , int flags, int *status)434 static pfn_t zone_frame_alloc(zone_t *zone,__u8 order) 400 435 { 401 436 pfn_t v; … … 459 494 460 495 frame = zone_get_frame(zone, frame_idx); 496 if (frame->refcount) 497 return; 461 498 link = buddy_system_alloc_block(zone->buddy_system, 462 499 &frame->buddy_link); … … 465 502 } 466 503 504 /** 505 * Join 2 zones 506 * 507 * Expect zone_t *z to point to space at least zone_conf_size large 508 * 509 * Assume z1 & z2 are locked 510 */ 511 512 static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) 513 { 514 __u8 max_order; 515 int i, z2idx; 516 pfn_t frame_idx; 517 frame_t *frame; 518 519 ASSERT(!overlaps(z1->base,z1->count,z2->base,z2->count)); 520 ASSERT(z1->base < z2->base); 521 522 spinlock_initialize(&z->lock, "zone_lock"); 523 z->base = z1->base; 524 z->count = z2->base+z2->count - z1->base; 525 z->flags = z1->flags & z2->flags; 526 527 z->free_count = z1->free_count + z2->free_count; 528 z->busy_count = z1->busy_count + z2->busy_count; 529 530 max_order = fnzb(z->count); 531 532 z->buddy_system = (buddy_system_t *)&z[1]; 533 buddy_system_create(z->buddy_system, max_order, 534 &zone_buddy_system_operations, 535 (void *) z); 536 537 z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); 538 for (i = 0; i < z->count; i++) { 539 /* This marks all frames busy */ 540 frame_initialize(&z->frames[i]); 541 } 542 /* Copy frames from both zones to preserve full frame orders, 543 * parents etc. Set all frames with refcount=0 to 1, because 544 * we add all free frames to buddy allocator later again, clear 545 * order to 0. 546 */ 547 for (i=0; i<z1->count; i++) 548 z->frames[i] = z1->frames[i]; 549 for (i=0; i < z2->count; i++) { 550 z2idx = i + (z2->base - z1->base); 551 z->frames[z2idx] = z2->frames[i]; 552 } 553 for (i=0; i < z->count; i++) { 554 if (!z->frames[i].refcount) { 555 z->frames[i].refcount = 1; 556 z->frames[i].buddy_order = 0; 557 } 558 } 559 /* Add free blocks from the 2 original zones */ 560 while (zone_can_alloc(z1, 0)) { 561 frame_idx = zone_frame_alloc(z1, 0); 562 frame = &z->frames[frame_idx]; 563 frame->refcount = 0; 564 buddy_system_free(z->buddy_system, &frame->buddy_link); 565 } 566 while (zone_can_alloc(z2, 0)) { 567 frame_idx = zone_frame_alloc(z2, 0); 568 frame = &z->frames[frame_idx + (z2->base-z1->base)]; 569 frame->refcount = 0; 570 buddy_system_free(z->buddy_system, &frame->buddy_link); 571 } 572 } 573 574 /** Return old configuration frames into the zone 575 * 576 * We have several cases 577 * - the conf. data is outside of zone -> exit, shall we call frame_free?? 578 * - the conf. data was created by zone_create -> free every frame 579 * - the conf. data was created by merge in frame_alloc -> free first frame 580 * (the difference is in order) 581 */ 582 static void return_config_frames(zone_t *newzone, zone_t *oldzone) 583 { 584 pfn_t pfn; 585 frame_t *frame; 586 count_t cframes; 587 int i; 588 589 pfn = ADDR2PFN((__address)KA2PA(oldzone)); 590 cframes = SIZE2FRAMES(zone_conf_size(oldzone->count)); 591 592 if (pfn < newzone->base || pfn >= newzone->base + newzone->count) 593 return; 594 595 frame = &newzone->frames[pfn - newzone->base]; 596 if (frame->buddy_order) { 597 /* Normally zone config data is hidden, show it again */ 598 newzone->busy_count += (1 << frame->buddy_order); 599 zone_frame_free(newzone, pfn - newzone->base); 600 return; 601 } 602 603 for (i=0; i < cframes; i++) { 604 newzone->busy_count++; 605 zone_frame_free(newzone, pfn+i-newzone->base); 606 } 607 } 608 609 /** Merge zones z1 and z2 610 * 611 * - the zones must be 2 zones with no zone existing in between, 612 * which means that z2 = z1+1 613 * 614 * - When you create a new zone, the frame allocator configuration does 615 * not to be 2^order size. Once the allocator is running it is no longer 616 * possible, merged configuration data occupies more space :-/ 617 */ 618 void zone_merge(int z1, int z2) 619 { 620 ipl_t ipl; 621 zone_t *zone1, *zone2, *newzone; 622 int cframes; 623 __u8 order; 624 int i; 625 pfn_t pfn; 626 627 ipl = interrupts_disable(); 628 spinlock_lock(&zones.lock); 629 630 if (z1 < 0 || z1 >= zones.count || z2 < 0 || z2 >= zones.count) 631 goto errout; 632 /* We can join only 2 zones with none existing inbetween */ 633 if (z2-z1 != 1) 634 goto errout; 635 636 zone1 = zones.info[z1]; 637 zone2 = zones.info[z2]; 638 spinlock_lock(&zone1->lock); 639 spinlock_lock(&zone2->lock); 640 641 cframes = SIZE2FRAMES(zone_conf_size(zone2->base+zone2->count-zone1->base)); 642 order = fnzb(cframes) + 1; 643 644 /* Allocate zonedata inside one of the zones */ 645 if (zone_can_alloc(zone1, order)) 646 pfn = zone1->base + zone_frame_alloc(zone1, order); 647 else if (zone_can_alloc(zone2, order)) 648 pfn = zone2->base + zone_frame_alloc(zone2, order); 649 else 650 goto errout2; 651 652 newzone = (zone_t *)PA2KA(PFN2ADDR(pfn)); 653 654 _zone_merge(newzone, zone1, zone2); 655 656 /* Subtract zone information from busy frames */ 657 newzone->busy_count -= (1 << order); 658 659 zones.info[z1] = newzone; 660 for (i=z2+1;i < zones.count;i++) 661 zones.info[i-1] = zones.info[i]; 662 zones.count--; 663 664 /* Free old zone information */ 665 return_config_frames(newzone, zone1); 666 return_config_frames(newzone, zone2); 667 errout2: 668 /* Nobody is allowed to enter to zone, so we are safe 669 * to touch the spinlocks last time */ 670 spinlock_unlock(&zone1->lock); 671 spinlock_unlock(&zone2->lock); 672 errout: 673 spinlock_unlock(&zones.lock); 674 interrupts_restore(ipl); 675 } 676 677 678 /** 679 * Merge all zones into one big zone 680 * 681 * It is reasonable to do this on systems whose bios reports parts in chunks, 682 * so that we could have 1 zone (it's faster). 683 */ 684 void zone_merge_all(void) 685 { 686 int count = zones.count; 687 688 while (zones.count > 1 && --count) { 689 zone_merge(0,1); 690 break; 691 } 692 } 693 467 694 /** Create frame zone 468 695 * … … 476 703 * @return Initialized zone. 477 704 */ 478 static zone_t * zone_construct(pfn_t start, count_t count, 479 zone_t *z, int flags) 705 static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) 480 706 { 481 707 int i; … … 492 718 * Compute order for buddy system, initialize 493 719 */ 494 for (max_order = 0; count >> max_order; max_order++) 495 ; 720 max_order = fnzb(count); 496 721 z->buddy_system = (buddy_system_t *)&z[1]; 497 722 … … 503 728 /* Check sizes */ 504 729 z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); 505 506 730 for (i = 0; i<count; i++) { 507 731 frame_initialize(&z->frames[i]); 508 732 } 733 509 734 /* Stuffing frames */ 510 735 for (i = 0; i < count; i++) { … … 512 737 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link); 513 738 } 514 return z;515 739 } 516 740 517 741 518 742 /** Compute configuration data size for zone */ 519 __address zone_conf_size( pfn_t start,count_t count)743 __address zone_conf_size(count_t count) 520 744 { 521 745 int size = sizeof(zone_t) + count*sizeof(frame_t); 522 746 int max_order; 523 747 524 for (max_order = 0; count >> max_order; max_order++) 525 ; 748 max_order = fnzb(count); 526 749 size += buddy_conf_size(max_order); 527 750 return size; 528 751 } 752 529 753 530 754 /** Create and add zone to system … … 535 759 * that the area is already marked BUSY and big enough 536 760 * to contain zone_conf_size() amount of data 537 */ 538 void zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) 761 * 762 * @return Zone number or -1 on error 763 */ 764 int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) 539 765 { 540 766 zone_t *z; 541 __address addr ,endaddr;767 __address addr; 542 768 count_t confcount; 543 769 int i; 770 int znum; 544 771 545 772 /* Theoretically we could have here 0, practically make sure … … 551 778 * it does not span kernel & init 552 779 */ 553 confcount = SIZE2FRAMES(zone_conf_size( start,count));780 confcount = SIZE2FRAMES(zone_conf_size(count)); 554 781 if (confframe >= start && confframe < start+count) { 555 782 for (;confframe < start+count;confframe++) { 556 783 addr = PFN2ADDR(confframe); 557 endaddr = PFN2ADDR (confframe + confcount); 558 if (overlaps(addr, endaddr, KA2PA(config.base), 559 KA2PA(config.base+config.kernel_size))) 784 if (overlaps(addr, PFN2ADDR(confcount), 785 KA2PA(config.base),config.kernel_size)) 560 786 continue; 561 787 if (config.init_addr) 562 if (overlaps(addr, endaddr,788 if (overlaps(addr,PFN2ADDR(confcount), 563 789 KA2PA(config.init_addr), 564 KA2PA(config.init_addr+config.init_size)))790 config.init_size)) 565 791 continue; 566 792 break; … … 570 796 } 571 797 572 z = zone_construct(start, count, (zone_t *)PA2KA(PFN2ADDR(confframe)), flags); 573 zones_add_zone(z); 574 798 z = (zone_t *)PA2KA(PFN2ADDR(confframe)); 799 zone_construct(start, count, z, flags); 800 znum = zones_add_zone(z); 801 if (znum == -1) 802 return -1; 803 575 804 /* If confdata in zone, mark as unavailable */ 576 805 if (confframe >= start && confframe < start+count) … … 578 807 zone_mark_unavailable(z, i - z->base); 579 808 } 809 810 return znum; 580 811 } 581 812 … … 658 889 goto loop; 659 890 } 660 v = zone_frame_alloc(zone,order ,flags,status);891 v = zone_frame_alloc(zone,order); 661 892 v += zone->base; 662 893 … … 671 902 /** Free a frame. 672 903 * 673 * Find respective frame struct rue for supplied addr.904 * Find respective frame structure for supplied addr. 674 905 * Decrement frame reference count. 675 906 * If it drops to zero, move the frame structure to free list. … … 705 936 int prefzone = 0; 706 937 707 for (i=0; i <count; i++) {938 for (i=0; i < count; i++) { 708 939 zone = find_zone_and_lock(start+i,&prefzone); 709 940 if (!zone) /* PFN not found */ … … 748 979 ipl = interrupts_disable(); 749 980 spinlock_lock(&zones.lock); 750 printf(" Base address\tFree Frames\tBusy Frames\n");751 printf(" ------------\t-----------\t-----------\n");981 printf("# Base address\tFree Frames\tBusy Frames\n"); 982 printf(" ------------\t-----------\t-----------\n"); 752 983 for (i=0;i<zones.count;i++) { 753 984 zone = zones.info[i]; 754 985 spinlock_lock(&zone->lock); 755 printf("% L\t%d\t\t%d\n",PFN2ADDR(zone->base),986 printf("%d %L\t%d\t\t%d\n",i,PFN2ADDR(zone->base), 756 987 zone->free_count, zone->busy_count); 757 988 spinlock_unlock(&zone->lock); … … 763 994 /** Prints zone details 764 995 * 765 * @param base Zone base address 766 */ 767 void zone_print_one(int znum) {996 * @param base Zone base address OR zone number 997 */ 998 void zone_print_one(int num) { 768 999 zone_t *zone = NULL; 769 1000 ipl_t ipl; 1001 int i; 770 1002 771 1003 ipl = interrupts_disable(); 772 1004 spinlock_lock(&zones.lock); 773 774 if (znum >= zones.count || znum < 0) { 775 printf("Zone number out of bounds.\n"); 776 spinlock_unlock(&zones.lock); 777 interrupts_restore(ipl); 778 return; 779 } 780 781 zone = zones.info[znum]; 1005 1006 for (i=0;i < zones.count; i++) { 1007 if (i == num || zones.info[i]->base == ADDR2PFN(num)) { 1008 zone = zones.info[i]; 1009 break; 1010 } 1011 } 1012 if (!zone) { 1013 printf("Zone not found.\n"); 1014 goto out; 1015 } 782 1016 783 1017 spinlock_lock(&zone->lock); 784 printf("Memory zone information\n \n");1018 printf("Memory zone information\n"); 785 1019 printf("Zone base address: %P\n", PFN2ADDR(zone->base)); 786 1020 printf("Zone size: %d frames (%dK)\n", zone->count, ((zone->count) * FRAME_SIZE) >> 10); 787 1021 printf("Allocated space: %d frames (%dK)\n", zone->busy_count, (zone->busy_count * FRAME_SIZE) >> 10); 788 1022 printf("Available space: %d (%dK)\n", zone->free_count, (zone->free_count * FRAME_SIZE) >> 10); 789 790 printf("\nBuddy allocator structures:\n\n");791 1023 buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); 792 1024 793 1025 spinlock_unlock(&zone->lock); 1026 out: 794 1027 spinlock_unlock(&zones.lock); 795 1028 interrupts_restore(ipl);
Note:
See TracChangeset
for help on using the changeset viewer.