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++) { |