Rev 2121 | Rev 2123 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2121 | Rev 2122 | ||
|---|---|---|---|
| Line 91... | Line 91... | ||
| 91 | * Some of the attributes in zone_t structures are 'read-only' |
91 | * Some of the attributes in zone_t structures are 'read-only' |
| 92 | */ |
92 | */ |
| 93 | 93 | ||
| 94 | typedef struct { |
94 | typedef struct { |
| 95 | SPINLOCK_DECLARE(lock); |
95 | SPINLOCK_DECLARE(lock); |
| 96 | int count; |
96 | unsigned int count; |
| 97 | zone_t *info[ZONES_MAX]; |
97 | zone_t *info[ZONES_MAX]; |
| 98 | } zones_t; |
98 | } zones_t; |
| 99 | 99 | ||
| 100 | static zones_t zones; |
100 | static zones_t zones; |
| 101 | 101 | ||
| Line 142... | Line 142... | ||
| 142 | * @param newzone New zone to be inserted into zone list |
142 | * @param newzone New zone to be inserted into zone list |
| 143 | * @return zone number on success, -1 on error |
143 | * @return zone number on success, -1 on error |
| 144 | */ |
144 | */ |
| 145 | static int zones_add_zone(zone_t *newzone) |
145 | static int zones_add_zone(zone_t *newzone) |
| 146 | { |
146 | { |
| 147 | int i,j; |
147 | unsigned int i, j; |
| 148 | ipl_t ipl; |
148 | ipl_t ipl; |
| 149 | zone_t *z; |
149 | zone_t *z; |
| 150 | 150 | ||
| 151 | ipl = interrupts_disable(); |
151 | ipl = interrupts_disable(); |
| 152 | spinlock_lock(&zones.lock); |
152 | spinlock_lock(&zones.lock); |
| Line 183... | Line 183... | ||
| 183 | * @param frame Frame number contained in zone |
183 | * @param frame Frame number contained in zone |
| 184 | * @param pzone If not null, it is used as zone hint. Zone index |
184 | * @param pzone If not null, it is used as zone hint. Zone index |
| 185 | * is filled into the variable on success. |
185 | * is filled into the variable on success. |
| 186 | * @return Pointer to locked zone containing frame |
186 | * @return Pointer to locked zone containing frame |
| 187 | */ |
187 | */ |
| 188 | static zone_t * find_zone_and_lock(pfn_t frame, int *pzone) |
188 | static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone) |
| 189 | { |
189 | { |
| 190 | int i; |
190 | unsigned int i; |
| 191 | int hint = pzone ? *pzone : 0; |
191 | unsigned int hint = pzone ? *pzone : 0; |
| 192 | zone_t *z; |
192 | zone_t *z; |
| 193 | 193 | ||
| 194 | spinlock_lock(&zones.lock); |
194 | spinlock_lock(&zones.lock); |
| 195 | 195 | ||
| 196 | if (hint >= zones.count || hint < 0) |
196 | if (hint >= zones.count || hint < 0) |
| Line 230... | Line 230... | ||
| 230 | * @param order Size (2^order) of free space we are trying to find |
230 | * @param order Size (2^order) of free space we are trying to find |
| 231 | * @param pzone Pointer to preferred zone or NULL, on return contains zone number |
231 | * @param pzone Pointer to preferred zone or NULL, on return contains zone number |
| 232 | */ |
232 | */ |
| 233 | static zone_t * find_free_zone_and_lock(uint8_t order, int *pzone) |
233 | static zone_t * find_free_zone_and_lock(uint8_t order, int *pzone) |
| 234 | { |
234 | { |
| 235 | int i; |
235 | unsigned int i; |
| 236 | zone_t *z; |
236 | zone_t *z; |
| 237 | int hint = pzone ? *pzone : 0; |
237 | unsigned int hint = pzone ? *pzone : 0; |
| 238 | 238 | ||
| 239 | spinlock_lock(&zones.lock); |
239 | spinlock_lock(&zones.lock); |
| 240 | if (hint >= zones.count) |
240 | if (hint >= zones.count) |
| 241 | hint = 0; |
241 | hint = 0; |
| 242 | i = hint; |
242 | i = hint; |
| Line 537... | Line 537... | ||
| 537 | * @param z2 Zone to merge |
537 | * @param z2 Zone to merge |
| 538 | */ |
538 | */ |
| 539 | static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
539 | static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
| 540 | { |
540 | { |
| 541 | uint8_t max_order; |
541 | uint8_t max_order; |
| - | 542 | unsigned int i; |
|
| 542 | int i, z2idx; |
543 | int z2idx; |
| 543 | pfn_t frame_idx; |
544 | pfn_t frame_idx; |
| 544 | frame_t *frame; |
545 | frame_t *frame; |
| 545 | 546 | ||
| 546 | ASSERT(!overlaps(z1->base,z1->count,z2->base,z2->count)); |
547 | ASSERT(!overlaps(z1->base,z1->count,z2->base,z2->count)); |
| 547 | ASSERT(z1->base < z2->base); |
548 | ASSERT(z1->base < z2->base); |
| Line 559... | Line 560... | ||
| 559 | z->buddy_system = (buddy_system_t *)&z[1]; |
560 | z->buddy_system = (buddy_system_t *)&z[1]; |
| 560 | buddy_system_create(z->buddy_system, max_order, |
561 | buddy_system_create(z->buddy_system, max_order, |
| 561 | &zone_buddy_system_operations, |
562 | &zone_buddy_system_operations, |
| 562 | (void *) z); |
563 | (void *) z); |
| 563 | 564 | ||
| 564 | z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); |
565 | z->frames = (frame_t *)((uint8_t *) z->buddy_system + buddy_conf_size(max_order)); |
| 565 | for (i = 0; i < z->count; i++) { |
566 | for (i = 0; i < z->count; i++) { |
| 566 | /* This marks all frames busy */ |
567 | /* This marks all frames busy */ |
| 567 | frame_initialize(&z->frames[i]); |
568 | frame_initialize(&z->frames[i]); |
| 568 | } |
569 | } |
| 569 | /* Copy frames from both zones to preserve full frame orders, |
570 | /* Copy frames from both zones to preserve full frame orders, |
| Line 571... | Line 572... | ||
| 571 | * we add all free frames to buddy allocator later again, clear |
572 | * we add all free frames to buddy allocator later again, clear |
| 572 | * order to 0. Don't set busy frames with refcount=0, as they |
573 | * order to 0. Don't set busy frames with refcount=0, as they |
| 573 | * will not be reallocated during merge and it would make later |
574 | * will not be reallocated during merge and it would make later |
| 574 | * problems with allocation/free. |
575 | * problems with allocation/free. |
| 575 | */ |
576 | */ |
| 576 | for (i=0; i<z1->count; i++) |
577 | for (i = 0; i < z1->count; i++) |
| 577 | z->frames[i] = z1->frames[i]; |
578 | z->frames[i] = z1->frames[i]; |
| 578 | for (i=0; i < z2->count; i++) { |
579 | for (i = 0; i < z2->count; i++) { |
| 579 | z2idx = i + (z2->base - z1->base); |
580 | z2idx = i + (z2->base - z1->base); |
| 580 | z->frames[z2idx] = z2->frames[i]; |
581 | z->frames[z2idx] = z2->frames[i]; |
| 581 | } |
582 | } |
| 582 | i = 0; |
583 | i = 0; |
| 583 | while (i < z->count) { |
584 | while (i < z->count) { |
| Line 621... | Line 622... | ||
| 621 | static void return_config_frames(zone_t *newzone, zone_t *oldzone) |
622 | static void return_config_frames(zone_t *newzone, zone_t *oldzone) |
| 622 | { |
623 | { |
| 623 | pfn_t pfn; |
624 | pfn_t pfn; |
| 624 | frame_t *frame; |
625 | frame_t *frame; |
| 625 | count_t cframes; |
626 | count_t cframes; |
| 626 | int i; |
627 | unsigned int i; |
| 627 | 628 | ||
| 628 | pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone)); |
629 | pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone)); |
| 629 | cframes = SIZE2FRAMES(zone_conf_size(oldzone->count)); |
630 | cframes = SIZE2FRAMES(zone_conf_size(oldzone->count)); |
| 630 | 631 | ||
| 631 | if (pfn < newzone->base || pfn >= newzone->base + newzone->count) |
632 | if (pfn < newzone->base || pfn >= newzone->base + newzone->count) |
| 632 | return; |
633 | return; |
| 633 | 634 | ||
| 634 | frame = &newzone->frames[pfn - newzone->base]; |
635 | frame = &newzone->frames[pfn - newzone->base]; |
| 635 | ASSERT(!frame->buddy_order); |
636 | ASSERT(!frame->buddy_order); |
| 636 | 637 | ||
| 637 | for (i=0; i < cframes; i++) { |
638 | for (i = 0; i < cframes; i++) { |
| 638 | newzone->busy_count++; |
639 | newzone->busy_count++; |
| 639 | zone_frame_free(newzone, pfn+i-newzone->base); |
640 | zone_frame_free(newzone, pfn+i-newzone->base); |
| 640 | } |
641 | } |
| 641 | } |
642 | } |
| 642 | 643 | ||
| Line 655... | Line 656... | ||
| 655 | { |
656 | { |
| 656 | count_t i; |
657 | count_t i; |
| 657 | uint8_t order; |
658 | uint8_t order; |
| 658 | frame_t *frame; |
659 | frame_t *frame; |
| 659 | 660 | ||
| 660 | ASSERT(frame_idx+count < zone->count); |
661 | ASSERT(frame_idx + count < zone->count); |
| 661 | 662 | ||
| 662 | order = zone->frames[frame_idx].buddy_order; |
663 | order = zone->frames[frame_idx].buddy_order; |
| 663 | ASSERT((1 << order) >= count); |
664 | ASSERT((count_t) (1 << order) >= count); |
| 664 | 665 | ||
| 665 | /* Reduce all blocks to order 0 */ |
666 | /* Reduce all blocks to order 0 */ |
| 666 | for (i=0; i < (1 << order); i++) { |
667 | for (i = 0; i < (count_t) (1 << order); i++) { |
| 667 | frame = &zone->frames[i + frame_idx]; |
668 | frame = &zone->frames[i + frame_idx]; |
| 668 | frame->buddy_order = 0; |
669 | frame->buddy_order = 0; |
| 669 | if (! frame->refcount) |
670 | if (! frame->refcount) |
| 670 | frame->refcount = 1; |
671 | frame->refcount = 1; |
| 671 | ASSERT(frame->refcount == 1); |
672 | ASSERT(frame->refcount == 1); |
| 672 | } |
673 | } |
| 673 | /* Free unneeded frames */ |
674 | /* Free unneeded frames */ |
| 674 | for (i=count; i < (1 << order); i++) { |
675 | for (i = count; i < (count_t) (1 << order); i++) { |
| 675 | zone_frame_free(zone, i + frame_idx); |
676 | zone_frame_free(zone, i + frame_idx); |
| 676 | } |
677 | } |
| 677 | } |
678 | } |
| 678 | 679 | ||
| 679 | /** Merge zones z1 and z2 |
680 | /** Merge zones z1 and z2 |
| Line 683... | Line 684... | ||
| 683 | * |
684 | * |
| 684 | * - When you create a new zone, the frame allocator configuration does |
685 | * - When you create a new zone, the frame allocator configuration does |
| 685 | * not to be 2^order size. Once the allocator is running it is no longer |
686 | * not to be 2^order size. Once the allocator is running it is no longer |
| 686 | * possible, merged configuration data occupies more space :-/ |
687 | * possible, merged configuration data occupies more space :-/ |
| 687 | */ |
688 | */ |
| 688 | void zone_merge(int z1, int z2) |
689 | void zone_merge(unsigned int z1, unsigned int z2) |
| 689 | { |
690 | { |
| 690 | ipl_t ipl; |
691 | ipl_t ipl; |
| 691 | zone_t *zone1, *zone2, *newzone; |
692 | zone_t *zone1, *zone2, *newzone; |
| 692 | int cframes; |
693 | unsigned int cframes; |
| 693 | uint8_t order; |
694 | uint8_t order; |
| 694 | int i; |
695 | unsigned int i; |
| 695 | pfn_t pfn; |
696 | pfn_t pfn; |
| 696 | 697 | ||
| 697 | ipl = interrupts_disable(); |
698 | ipl = interrupts_disable(); |
| 698 | spinlock_lock(&zones.lock); |
699 | spinlock_lock(&zones.lock); |
| 699 | 700 | ||
| Line 720... | Line 721... | ||
| 720 | else if (zone_can_alloc(zone2, order)) |
721 | else if (zone_can_alloc(zone2, order)) |
| 721 | pfn = zone2->base + zone_frame_alloc(zone2, order); |
722 | pfn = zone2->base + zone_frame_alloc(zone2, order); |
| 722 | else |
723 | else |
| 723 | goto errout2; |
724 | goto errout2; |
| 724 | 725 | ||
| 725 | newzone = (zone_t *)PA2KA(PFN2ADDR(pfn)); |
726 | newzone = (zone_t *) PA2KA(PFN2ADDR(pfn)); |
| 726 | 727 | ||
| 727 | _zone_merge(newzone, zone1, zone2); |
728 | _zone_merge(newzone, zone1, zone2); |
| 728 | 729 | ||
| 729 | /* Free unneeded config frames */ |
730 | /* Free unneeded config frames */ |
| 730 | zone_reduce_region(newzone, pfn - newzone->base, cframes); |
731 | zone_reduce_region(newzone, pfn - newzone->base, cframes); |
| Line 777... | Line 778... | ||
| 777 | * |
778 | * |
| 778 | * @return Initialized zone. |
779 | * @return Initialized zone. |
| 779 | */ |
780 | */ |
| 780 | static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) |
781 | static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags) |
| 781 | { |
782 | { |
| 782 | int i; |
783 | unsigned int i; |
| 783 | uint8_t max_order; |
784 | uint8_t max_order; |
| 784 | 785 | ||
| 785 | spinlock_initialize(&z->lock, "zone_lock"); |
786 | spinlock_initialize(&z->lock, "zone_lock"); |
| 786 | z->base = start; |
787 | z->base = start; |
| 787 | z->count = count; |
788 | z->count = count; |
| Line 799... | Line 800... | ||
| 799 | &zone_buddy_system_operations, |
800 | &zone_buddy_system_operations, |
| 800 | (void *) z); |
801 | (void *) z); |
| 801 | 802 | ||
| 802 | /* Allocate frames _after_ the conframe */ |
803 | /* Allocate frames _after_ the conframe */ |
| 803 | /* Check sizes */ |
804 | /* Check sizes */ |
| 804 | z->frames = (frame_t *)((void *)z->buddy_system+buddy_conf_size(max_order)); |
805 | z->frames = (frame_t *)((uint8_t *) z->buddy_system + buddy_conf_size(max_order)); |
| 805 | for (i = 0; i<count; i++) { |
806 | for (i = 0; i < count; i++) { |
| 806 | frame_initialize(&z->frames[i]); |
807 | frame_initialize(&z->frames[i]); |
| 807 | } |
808 | } |
| 808 | 809 | ||
| 809 | /* Stuffing frames */ |
810 | /* Stuffing frames */ |
| 810 | for (i = 0; i < count; i++) { |
811 | for (i = 0; i < count; i++) { |
| Line 846... | Line 847... | ||
| 846 | int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
847 | int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags) |
| 847 | { |
848 | { |
| 848 | zone_t *z; |
849 | zone_t *z; |
| 849 | uintptr_t addr; |
850 | uintptr_t addr; |
| 850 | count_t confcount; |
851 | count_t confcount; |
| 851 | int i; |
852 | unsigned int i; |
| 852 | int znum; |
853 | int znum; |
| 853 | 854 | ||
| 854 | /* Theoretically we could have here 0, practically make sure |
855 | /* Theoretically we could have here 0, practically make sure |
| 855 | * nobody tries to do that. If some platform requires, remove |
856 | * nobody tries to do that. If some platform requires, remove |
| 856 | * the assert |
857 | * the assert |
| Line 890... | Line 891... | ||
| 890 | znum = zones_add_zone(z); |
891 | znum = zones_add_zone(z); |
| 891 | if (znum == -1) |
892 | if (znum == -1) |
| 892 | return -1; |
893 | return -1; |
| 893 | 894 | ||
| 894 | /* If confdata in zone, mark as unavailable */ |
895 | /* If confdata in zone, mark as unavailable */ |
| 895 | if (confframe >= start && confframe < start+count) |
896 | if (confframe >= start && confframe < start + count) |
| 896 | for (i=confframe; i<confframe+confcount; i++) { |
897 | for (i = confframe; i < confframe + confcount; i++) { |
| 897 | zone_mark_unavailable(z, i - z->base); |
898 | zone_mark_unavailable(z, i - z->base); |
| 898 | } |
899 | } |
| 899 | return znum; |
900 | return znum; |
| 900 | } |
901 | } |
| 901 | 902 | ||
| 902 | /***************************************/ |
903 | /***************************************/ |
| 903 | /* Frame functions */ |
904 | /* Frame functions */ |
| 904 | 905 | ||
| 905 | /** Set parent of frame */ |
906 | /** Set parent of frame */ |
| 906 | void frame_set_parent(pfn_t pfn, void *data, int hint) |
907 | void frame_set_parent(pfn_t pfn, void *data, unsigned int hint) |
| 907 | { |
908 | { |
| 908 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
909 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
| 909 | 910 | ||
| 910 | ASSERT(zone); |
911 | ASSERT(zone); |
| 911 | 912 | ||
| 912 | zone_get_frame(zone, pfn-zone->base)->parent = data; |
913 | zone_get_frame(zone, pfn-zone->base)->parent = data; |
| 913 | spinlock_unlock(&zone->lock); |
914 | spinlock_unlock(&zone->lock); |
| 914 | } |
915 | } |
| 915 | 916 | ||
| 916 | void * frame_get_parent(pfn_t pfn, int hint) |
917 | void * frame_get_parent(pfn_t pfn, unsigned int hint) |
| 917 | { |
918 | { |
| 918 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
919 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
| 919 | void *res; |
920 | void *res; |
| 920 | 921 | ||
| 921 | ASSERT(zone); |
922 | ASSERT(zone); |
| Line 1042... | Line 1043... | ||
| 1042 | } |
1043 | } |
| 1043 | 1044 | ||
| 1044 | /** Mark given range unavailable in frame zones */ |
1045 | /** Mark given range unavailable in frame zones */ |
| 1045 | void frame_mark_unavailable(pfn_t start, count_t count) |
1046 | void frame_mark_unavailable(pfn_t start, count_t count) |
| 1046 | { |
1047 | { |
| 1047 | int i; |
1048 | unsigned int i; |
| 1048 | zone_t *zone; |
1049 | zone_t *zone; |
| 1049 | int prefzone = 0; |
1050 | unsigned int prefzone = 0; |
| 1050 | 1051 | ||
| 1051 | for (i=0; i < count; i++) { |
1052 | for (i = 0; i < count; i++) { |
| 1052 | zone = find_zone_and_lock(start + i, &prefzone); |
1053 | zone = find_zone_and_lock(start + i, &prefzone); |
| 1053 | if (!zone) /* PFN not found */ |
1054 | if (!zone) /* PFN not found */ |
| 1054 | continue; |
1055 | continue; |
| 1055 | zone_mark_unavailable(zone, start + i - zone->base); |
1056 | zone_mark_unavailable(zone, start + i - zone->base); |
| 1056 | 1057 | ||
| Line 1092... | Line 1093... | ||
| 1092 | /** Prints list of zones |
1093 | /** Prints list of zones |
| 1093 | * |
1094 | * |
| 1094 | */ |
1095 | */ |
| 1095 | void zone_print_list(void) { |
1096 | void zone_print_list(void) { |
| 1096 | zone_t *zone = NULL; |
1097 | zone_t *zone = NULL; |
| 1097 | int i; |
1098 | unsigned int i; |
| 1098 | ipl_t ipl; |
1099 | ipl_t ipl; |
| 1099 | 1100 | ||
| 1100 | ipl = interrupts_disable(); |
1101 | ipl = interrupts_disable(); |
| 1101 | spinlock_lock(&zones.lock); |
1102 | spinlock_lock(&zones.lock); |
| 1102 | printf("# base address free frames busy frames\n"); |
1103 | printf("# base address free frames busy frames\n"); |
| Line 1113... | Line 1114... | ||
| 1113 | 1114 | ||
| 1114 | /** Prints zone details. |
1115 | /** Prints zone details. |
| 1115 | * |
1116 | * |
| 1116 | * @param num Zone base address or zone number. |
1117 | * @param num Zone base address or zone number. |
| 1117 | */ |
1118 | */ |
| 1118 | void zone_print_one(int num) { |
1119 | void zone_print_one(unsigned int num) { |
| 1119 | zone_t *zone = NULL; |
1120 | zone_t *zone = NULL; |
| 1120 | ipl_t ipl; |
1121 | ipl_t ipl; |
| 1121 | int i; |
1122 | unsigned int i; |
| 1122 | 1123 | ||
| 1123 | ipl = interrupts_disable(); |
1124 | ipl = interrupts_disable(); |
| 1124 | spinlock_lock(&zones.lock); |
1125 | spinlock_lock(&zones.lock); |
| 1125 | 1126 | ||
| 1126 | for (i = 0; i < zones.count; i++) { |
1127 | for (i = 0; i < zones.count; i++) { |