Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/frame.c

    r1066041 r566da7f8  
    3838 *
    3939 * 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 *
    4342 */
    4443
     
    5554#include <arch.h>
    5655#include <print.h>
     56#include <log.h>
    5757#include <align.h>
    5858#include <mm/slab.h>
     
    6161#include <config.h>
    6262#include <str.h>
    63 #include <proc/thread.h> /* THREAD */
    6463
    6564zones_t zones;
     
    9392}
    9493
    95 NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
    96 {
    97         return (frame - zone->frames);
    98 }
    99 
    10094/** Initialize frame structure.
    10195 *
     
    10599NO_TRACE static void frame_initialize(frame_t *frame)
    106100{
    107         frame->refcount = 1;
    108         frame->buddy_order = 0;
     101        frame->refcount = 0;
     102        frame->parent = NULL;
    109103}
    110104
     
    128122{
    129123        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);
    131126                return (size_t) -1;
    132127        }
     
    148143                            (!iswithin(zones.info[i].base, zones.info[i].count,
    149144                            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)!",
    152148                                    (void *) PFN2ADDR(base), (void *) PFN2ADDR(count),
    153149                                    (void *) PFN2ADDR(zones.info[i].base),
     
    162158       
    163159        /* 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--)
    166161                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         }
    171162       
    172163        zones.count++;
     
    238229}
    239230
    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 */
     232NO_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       
    243240        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 */
     260NO_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 */
     286NO_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 */
     306NO_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
    248329 *
    249330 * Assume interrupts are disabled and zones lock is
    250331 * locked.
    251332 *
    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 */
     343NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
     344    pfn_t constraint, size_t hint)
    259345{
    260346        if (hint >= zones.count)
    261347                hint = 0;
    262348       
    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}
    445361
    446362/******************/
     
    448364/******************/
    449365
     366/** Return frame from zone. */
     367NO_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
    450374/** Allocate frame in particular zone.
    451375 *
     
    453377 * Panics if allocation is impossible.
    454378 *
    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.
    457383 *
    458384 * @return Frame index in zone.
    459385 *
    460386 */
    461 NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
     387NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
     388    pfn_t constraint)
    462389{
    463390        ASSERT(zone->flags & ZONE_AVAILABLE);
    464391       
    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        }
    469407       
    470408        /* 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;
    479413}
    480414
     
    483417 * Assume zone is locked and is available for deallocation.
    484418 *
    485  * @param zone      Pointer to zone from which the frame is to be freed.
    486  * @param frame_idx Frame index relative to zone.
    487  *
    488  * @return          Number of freed frames.
    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 */
     425NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
    492426{
    493427        ASSERT(zone->flags & ZONE_AVAILABLE);
    494428       
    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);
    499432       
    500433        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               
    503436                /* 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;
    516444}
    517445
    518446/** Mark frame in zone unavailable to allocation. */
    519 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
     447NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
    520448{
    521449        ASSERT(zone->flags & ZONE_AVAILABLE);
    522450       
    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)
    525453                return;
    526454       
    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       
    533458        zone->free_count--;
    534459        reserve_force_alloc(1);
     
    537462/** Merge two zones.
    538463 *
    539  * Expect buddy to point to space at least zone_conf_size large.
    540464 * Assume z1 & z2 are locked and compatible and zones lock is
    541465 * locked.
    542466 *
    543  * @param z1     First zone to merge.
    544  * @param z2     Second zone to merge.
    545  * @param old_z1 Original date of 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.
    547471 *
    548472 */
    549473NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
    550     buddy_system_t *buddy)
     474    void *confdata)
    551475{
    552476        ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
     
    563487        zones.info[z1].free_count += zones.info[z2].free_count;
    564488        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.
    586498         */
    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));
    588503                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];
    630511        }
    631512}
     
    650531        size_t cframes = SIZE2FRAMES(zone_conf_size(count));
    651532       
    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))
    654535                return;
    655536       
    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++)
    664538                (void) zone_frame_free(&zones.info[znum],
    665539                    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 frames
    672  * in the block to order 0 and free the unneeded frames. This means that
    673  * 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);
    703540}
    704541
     
    720557        bool ret = true;
    721558       
    722         /* We can join only 2 zones with none existing inbetween,
     559        /*
     560         * We can join only 2 zones with none existing inbetween,
    723561         * the zones have to be available and with the same
    724562         * set of flags
     
    734572            + zones.info[z2].count));
    735573       
    736         uint8_t order;
    737         if (cframes == 1)
    738                 order = 0;
    739         else
    740                 order = fnzb(cframes - 1) + 1;
    741        
    742574        /* Allocate merged zone data inside one of the zones */
    743575        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);
    748582        } else {
    749583                ret = false;
     
    753587        /* Preserve original data from z1 */
    754588        zone_t old_z1 = zones.info[z1];
    755         old_z1.buddy_system->data = (void *) &old_z1;
    756589       
    757590        /* 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)));
    763592       
    764593        /* Subtract zone information from busy frames */
     
    773602       
    774603        /* 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++)
    777605                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         }
    782606       
    783607        zones.count--;
     
    798622void zone_merge_all(void)
    799623{
    800         size_t i = 0;
     624        size_t i = 1;
     625       
    801626        while (i < zones.count) {
    802                 if (!zone_merge(i, i + 1))
     627                if (!zone_merge(i - 1, i))
    803628                        i++;
    804629        }
     
    807632/** Create new frame zone.
    808633 *
    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 the zone.
    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.
    814639 *
    815640 * @return Initialized zone.
    816641 *
    817642 */
    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)
     643NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
     644    zone_flags_t flags, void *confdata)
    820645{
    821646        zone->base = start;
     
    824649        zone->free_count = count;
    825650        zone->busy_count = 0;
    826         zone->buddy_system = buddy;
    827651       
    828652        if (flags & ZONE_AVAILABLE) {
    829653                /*
    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).
    831656                 */
    832                 uint8_t order = fnzb(count);
    833                 buddy_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++)
    844669                        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);
    852672                zone->frames = NULL;
     673        }
    853674}
    854675
     
    862683size_t zone_conf_size(size_t count)
    863684{
    864         return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
     685        return (count * sizeof(frame_t) + bitmap_size(count));
    865686}
    866687
     
    868689pfn_t zone_external_conf_alloc(size_t count)
    869690{
    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));
    875695}
    876696
     
    880700 * @param count     Size of zone in frames.
    881701 * @param confframe Where configuration frames are supposed to be.
    882  *                  Automatically checks, that we will not disturb the
     702 *                  Automatically checks that we will not disturb the
    883703 *                  kernel and possibly init. If confframe is given
    884704 *                  _outside_ this zone, it is expected, that the area is
     
    897717       
    898718        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
    900721                 * nobody tries to do that. If some platform requires, remove
    901722                 * the assert
    902723                 */
    903724                ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
    904 
     725               
    905726                /* Update the known end of physical memory. */
    906727                config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
    907728               
    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
    909731                 * it does not span kernel & init
    910732                 */
    911733                size_t confcount = SIZE2FRAMES(zone_conf_size(count));
     734               
    912735                if ((confframe >= start) && (confframe < start + count)) {
    913736                        for (; confframe < start + count; confframe++) {
     
    922745                               
    923746                                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++) {
    926748                                        if (overlaps(addr, PFN2ADDR(confcount),
    927749                                            init.tasks[i].paddr,
     
    930752                                                break;
    931753                                        }
     754                                }
     755                               
    932756                                if (overlap)
    933757                                        continue;
     
    946770                }
    947771               
    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);
    950774               
    951775                /* If confdata in zone, mark as unavailable */
    952776                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++)
    955778                                zone_mark_unavailable(&zones.info[znum],
    956779                                    i - zones.info[znum].base);
     
    968791                return (size_t) -1;
    969792        }
    970         zone_construct(&zones.info[znum], NULL, start, count, flags);
     793       
     794        zone_construct(&zones.info[znum], start, count, flags, NULL);
    971795       
    972796        irq_spinlock_unlock(&zones.lock, true);
     
    1010834}
    1011835
    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.
    1017843 *
    1018844 * @return Physical address of the allocated frame.
    1019845 *
    1020846 */
    1021 void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
    1022 {
    1023         size_t size = ((size_t) 1) << order;
     847uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
     848    uintptr_t constraint, size_t *pzone)
     849{
     850        ASSERT(count > 0);
     851       
    1024852        size_t hint = pzone ? (*pzone) : 0;
     853        pfn_t frame_constraint = ADDR2PFN(constraint);
    1025854       
    1026855        /*
    1027856         * If not told otherwise, we must first reserve the memory.
    1028857         */
    1029         if (!(flags & FRAME_NO_RESERVE)) 
    1030                 reserve_force_alloc(size);
    1031 
     858        if (!(flags & FRAME_NO_RESERVE))
     859                reserve_force_alloc(count);
     860       
    1032861loop:
    1033862        irq_spinlock_lock(&zones.lock, true);
     
    1036865         * First, find suitable frame zone.
    1037866         */
    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         */
    1043874        if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
    1044875                irq_spinlock_unlock(&zones.lock, true);
     
    1047878               
    1048879                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);
    1051882               
    1052883                if (znum == (size_t) -1) {
     
    1056887                       
    1057888                        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);
    1060891                }
    1061892        }
     
    1064895                if (flags & FRAME_ATOMIC) {
    1065896                        irq_spinlock_unlock(&zones.lock, true);
     897                       
    1066898                        if (!(flags & FRAME_NO_RESERVE))
    1067                                 reserve_free(size);
    1068                         return NULL;
     899                                reserve_free(count);
     900                       
     901                        return 0;
    1069902                }
    1070903               
    1071 #ifdef CONFIG_DEBUG
    1072904                size_t avail = frame_total_free_get_internal();
    1073 #endif
    1074905               
    1075906                irq_spinlock_unlock(&zones.lock, true);
    1076907               
    1077908                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);
    1079911               
    1080912                /*
     
    1083915               
    1084916#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);
    1087920#endif
    1088921               
    1089922                /*
    1090                  * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
    1091                  * 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.
    1092925                 */
    1093926                ipl_t ipl = interrupts_disable();
     
    1095928               
    1096929                if (mem_avail_req > 0)
    1097                         mem_avail_req = min(mem_avail_req, size);
     930                        mem_avail_req = min(mem_avail_req, count);
    1098931                else
    1099                         mem_avail_req = size;
     932                        mem_avail_req = count;
     933               
    1100934                size_t gen = mem_avail_gen;
    1101935               
     
    1107941               
    1108942#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);
    1110945#endif
    1111946               
     
    1113948        }
    1114949       
    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;
    1117952       
    1118953        irq_spinlock_unlock(&zones.lock, true);
     
    1121956                *pzone = znum;
    1122957       
    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
     961uintptr_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.
    1146974 * @param flags Flags to control memory reservation.
    1147975 *
    1148976 */
    1149 void frame_free_generic(uintptr_t frame, frame_flags_t flags)
    1150 {
    1151         size_t size;
     977void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
     978{
     979        size_t freed = 0;
    1152980       
    1153981        irq_spinlock_lock(&zones.lock, true);
    1154982       
    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        }
    1164995       
    1165996        irq_spinlock_unlock(&zones.lock, true);
     
    1167998        /*
    1168999         * 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.
    11691003         */
    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       
    11761005        ipl_t ipl = interrupts_disable();
    11771006        mutex_lock(&mem_avail_mtx);
     1007       
    11781008        if (mem_avail_req > 0)
    1179                 mem_avail_req -= min(mem_avail_req, size);
     1009                mem_avail_req -= min(mem_avail_req, freed);
    11801010       
    11811011        if (mem_avail_req == 0) {
     
    11831013                condvar_broadcast(&mem_avail_cv);
    11841014        }
     1015       
    11851016        mutex_unlock(&mem_avail_mtx);
    11861017        interrupts_restore(ipl);
    11871018       
    11881019        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
     1023void frame_free(uintptr_t frame, size_t count)
     1024{
     1025        frame_free_generic(frame, count, 0);
     1026}
     1027
     1028void frame_free_noreserve(uintptr_t frame, size_t count)
     1029{
     1030        frame_free_generic(frame, count, FRAME_NO_RESERVE);
    12001031}
    12011032
     
    12311062        irq_spinlock_lock(&zones.lock, true);
    12321063       
    1233         size_t i;
    1234         for (i = 0; i < count; i++) {
     1064        for (size_t i = 0; i < count; i++) {
    12351065                size_t znum = find_zone(start + i, 1, 0);
     1066               
    12361067                if (znum == (size_t) -1)  /* PFN not found */
    12371068                        continue;
     
    12581089        /* Tell the architecture to create some memory */
    12591090        frame_low_arch_init();
     1091       
    12601092        if (config.cpu_active == 1) {
    12611093                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
     
    12641096                    SIZE2FRAMES(config.stack_size));
    12651097               
    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),
    12701100                            SIZE2FRAMES(init.tasks[i].size));
    1271                 }
    12721101               
    12731102                if (ballocs.size)
     
    12751104                            SIZE2FRAMES(ballocs.size));
    12761105               
    1277                 /* Black list first frame, as allocating NULL would
     1106                /*
     1107                 * Blacklist first frame, as allocating NULL would
    12781108                 * fail in some places
    12791109                 */
    12801110                frame_mark_unavailable(0, 1);
    12811111        }
     1112       
    12821113        frame_high_arch_init();
    12831114}
     
    12851116/** Adjust bounds of physical memory region according to low/high memory split.
    12861117 *
    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 *
    12961129 */
    12971130bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
    12981131{
    12991132        uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
    1300 
     1133       
    13011134        if (low) {
    13021135                if (*basep > limit)
    13031136                        return false;
     1137               
    13041138                if (*basep + *sizep > limit)
    13051139                        *sizep = limit - *basep;
     
    13071141                if (*basep + *sizep <= limit)
    13081142                        return false;
     1143               
    13091144                if (*basep <= limit) {
    13101145                        *sizep -= limit - *basep;
     
    13121147                }
    13131148        }
     1149       
    13141150        return true;
    13151151}
     
    13231159       
    13241160        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++)
    13271163                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13281164       
     
    13471183        *free = 0;
    13481184       
    1349         size_t i;
    1350         for (i = 0; i < zones.count; i++) {
     1185        for (size_t i = 0; i < zones.count; i++) {
    13511186                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13521187               
     
    13761211        /*
    13771212         * Because printing may require allocation of memory, we may not hold
    1378          * the frame allocator locks when printing zone statistics.  Therefore,
     1213         * the frame allocator locks when printing zone statistics. Therefore,
    13791214         * we simply gather the statistics under the protection of the locks and
    13801215         * print the statistics when the locks have been released.
     
    13851220         */
    13861221       
    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++) {
    13891227                irq_spinlock_lock(&zones.lock, true);
    13901228               
     
    13941232                }
    13951233               
    1396                 uintptr_t base = PFN2ADDR(zones.info[i].base);
     1234                pfn_t fbase = zones.info[i].base;
     1235                uintptr_t base = PFN2ADDR(fbase);
    13971236                size_t count = zones.info[i].count;
    13981237                zone_flags_t flags = zones.info[i].flags;
     
    14001239                size_t busy_count = zones.info[i].busy_count;
    14011240               
     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               
    14021272                irq_spinlock_unlock(&zones.lock, true);
    1403                
    1404                 bool available = ((flags & ZONE_AVAILABLE) != 0);
    14051273               
    14061274                printf("%-4zu", i);
     
    14271295                printf("\n");
    14281296        }
     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);
    14291317}
    14301318
     
    14391327        size_t znum = (size_t) -1;
    14401328       
    1441         size_t i;
    1442         for (i = 0; i < zones.count; i++) {
     1329        for (size_t i = 0; i < zones.count; i++) {
    14431330                if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
    14441331                        znum = i;
     
    14531340        }
    14541341       
    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        }
    14601383       
    14611384        irq_spinlock_unlock(&zones.lock, true);
    1462        
    1463         bool available = ((flags & ZONE_AVAILABLE) != 0);
    14641385       
    14651386        uint64_t size;
    14661387        const char *size_suffix;
     1388       
    14671389        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    14681390       
    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,
    14721394            size, size_suffix);
    1473         printf("Zone flags:        %c%c%c%c%c\n",
     1395        printf("Zone flags:              %c%c%c%c%c\n",
    14741396            available ? 'A' : '-',
    14751397            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    14811403                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    14821404                    false);
    1483                 printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1405                printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
    14841406                    busy_count, size, size_suffix);
     1407               
    14851408                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    14861409                    false);
    1487                 printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1410                printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
    14881411                    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);
    14891427        }
    14901428}
Note: See TracChangeset for help on using the changeset viewer.