Changeset 0773396 in mainline for kernel/generic/src/mm/frame.c


Ignore:
Timestamp:
2013-12-25T13:05:25Z (10 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bc54126c
Parents:
f4a47e52 (diff), 6946f23 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge mainline changes

File:
1 edited

Legend:

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

    rf4a47e52 r0773396  
    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
     
    9291}
    9392
    94 NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
    95 {
    96         return (frame - zone->frames);
    97 }
    98 
    9993/** Initialize frame structure.
    10094 *
     
    10498NO_TRACE static void frame_initialize(frame_t *frame)
    10599{
    106         frame->refcount = 1;
    107         frame->buddy_order = 0;
     100        frame->refcount = 0;
     101        frame->parent = NULL;
    108102}
    109103
     
    161155       
    162156        /* Move other zones up */
    163         size_t j;
    164         for (j = zones.count; j > i; j--) {
     157        for (size_t j = zones.count; j > i; j--)
    165158                zones.info[j] = zones.info[j - 1];
    166                 if (zones.info[j].buddy_system != NULL)
    167                         zones.info[j].buddy_system->data =
    168                             (void *) &zones.info[j];
    169         }
    170159       
    171160        zones.count++;
     
    237226}
    238227
    239 /** @return True if zone can allocate specified order */
    240 NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
    241 {
     228/** @return True if zone can allocate specified number of frames */
     229NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count,
     230    pfn_t constraint)
     231{
     232        /*
     233         * The function bitmap_allocate_range() does not modify
     234         * the bitmap if the last argument is NULL.
     235         */
     236       
    242237        return ((zone->flags & ZONE_AVAILABLE) &&
    243             buddy_system_can_alloc(zone->buddy_system, order));
    244 }
    245 
    246 /** Find a zone that can allocate order frames.
     238            bitmap_allocate_range(&zone->bitmap, count, zone->base,
     239            FRAME_LOWPRIO, constraint, NULL));
     240}
     241
     242/** Find a zone that can allocate specified number of frames
     243 *
     244 * This function searches among all zones. Assume interrupts are
     245 * disabled and zones lock is locked.
     246 *
     247 * @param count      Number of free frames we are trying to find.
     248 * @param flags      Required flags of the zone.
     249 * @param constraint Indication of bits that cannot be set in the
     250 *                   physical frame number of the first allocated frame.
     251 * @param hint       Preferred zone.
     252 *
     253 * @return Zone that can allocate specified number of frames.
     254 * @return -1 if no zone can satisfy the request.
     255 *
     256 */
     257NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
     258    pfn_t constraint, size_t hint)
     259{
     260        for (size_t pos = 0; pos < zones.count; pos++) {
     261                size_t i = (pos + hint) % zones.count;
     262               
     263                /* Check whether the zone meets the search criteria. */
     264                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     265                        continue;
     266               
     267                /* Check if the zone can satisfy the allocation request. */
     268                if (zone_can_alloc(&zones.info[i], count, constraint))
     269                        return i;
     270        }
     271       
     272        return (size_t) -1;
     273}
     274
     275/** Check if frame range  priority memory
     276 *
     277 * @param pfn   Starting frame.
     278 * @param count Number of frames.
     279 *
     280 * @return True if the range contains only priority memory.
     281 *
     282 */
     283NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
     284{
     285        return (base + count <= FRAME_LOWPRIO);
     286}
     287
     288/** Find a zone that can allocate specified number of frames
     289 *
     290 * This function ignores zones that contain only high-priority
     291 * memory. Assume interrupts are disabled and zones lock is locked.
     292 *
     293 * @param count      Number of free frames we are trying to find.
     294 * @param flags      Required flags of the zone.
     295 * @param constraint Indication of bits that cannot be set in the
     296 *                   physical frame number of the first allocated frame.
     297 * @param hint       Preferred zone.
     298 *
     299 * @return Zone that can allocate specified number of frames.
     300 * @return -1 if no low-priority zone can satisfy the request.
     301 *
     302 */
     303NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
     304    pfn_t constraint, size_t hint)
     305{       
     306        for (size_t pos = 0; pos < zones.count; pos++) {
     307                size_t i = (pos + hint) % zones.count;
     308               
     309                /* Skip zones containing only high-priority memory. */
     310                if (is_high_priority(zones.info[i].base, zones.info[i].count))
     311                        continue;
     312               
     313                /* Check whether the zone meets the search criteria. */
     314                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     315                        continue;
     316               
     317                /* Check if the zone can satisfy the allocation request. */
     318                if (zone_can_alloc(&zones.info[i], count, constraint))
     319                        return i;
     320        }
     321       
     322        return (size_t) -1;
     323}
     324
     325/** Find a zone that can allocate specified number of frames
    247326 *
    248327 * Assume interrupts are disabled and zones lock is
    249328 * locked.
    250329 *
    251  * @param order Size (2^order) of free space we are trying to find.
    252  * @param flags Required flags of the target zone.
    253  * @param hind  Preferred zone.
    254  *
    255  */
    256 NO_TRACE static size_t find_free_zone(uint8_t order, zone_flags_t flags,
    257     size_t hint)
     330 * @param count      Number of free frames we are trying to find.
     331 * @param flags      Required flags of the target zone.
     332 * @param constraint Indication of bits that cannot be set in the
     333 *                   physical frame number of the first allocated frame.
     334 * @param hint       Preferred zone.
     335 *
     336 * @return Zone that can allocate specified number of frames.
     337 * @return -1 if no zone can satisfy the request.
     338 *
     339 */
     340NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
     341    pfn_t constraint, size_t hint)
    258342{
    259343        if (hint >= zones.count)
    260344                hint = 0;
    261345       
    262         size_t i = hint;
    263         do {
    264                 /*
    265                  * Check whether the zone meets the search criteria.
    266                  */
    267                 if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
    268                         /*
    269                          * Check if the zone has 2^order frames area available.
    270                          */
    271                         if (zone_can_alloc(&zones.info[i], order))
    272                                 return i;
    273                 }
    274                
    275                 i++;
    276                 if (i >= zones.count)
    277                         i = 0;
    278                
    279         } while (i != hint);
    280        
    281         return (size_t) -1;
    282 }
    283 
    284 /**************************/
    285 /* Buddy system functions */
    286 /**************************/
    287 
    288 /** Buddy system find_block implementation.
    289  *
    290  * Find block that is parent of current list.
    291  * That means go to lower addresses, until such block is found
    292  *
    293  * @param order Order of parent must be different then this
    294  *              parameter!!
    295  *
    296  */
    297 NO_TRACE static link_t *zone_buddy_find_block(buddy_system_t *buddy,
    298     link_t *child, uint8_t order)
    299 {
    300         frame_t *frame = list_get_instance(child, frame_t, buddy_link);
    301         zone_t *zone = (zone_t *) buddy->data;
    302        
    303         size_t index = frame_index(zone, frame);
    304         do {
    305                 if (zone->frames[index].buddy_order != order)
    306                         return &zone->frames[index].buddy_link;
    307         } while (index-- > 0);
    308        
    309         return NULL;
    310 }
    311 
    312 /** Buddy system find_buddy implementation.
    313  *
    314  * @param buddy Buddy system.
    315  * @param block Block for which buddy should be found.
    316  *
    317  * @return Buddy for given block if found.
    318  *
    319  */
    320 NO_TRACE static link_t *zone_buddy_find_buddy(buddy_system_t *buddy,
    321     link_t *block)
    322 {
    323         frame_t *frame = list_get_instance(block, frame_t, buddy_link);
    324         zone_t *zone = (zone_t *) buddy->data;
    325         ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
    326             frame->buddy_order));
    327        
    328         bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
    329        
    330         size_t index;
    331         if (is_left) {
    332                 index = (frame_index(zone, frame)) +
    333                     (1 << frame->buddy_order);
    334         } else {  /* is_right */
    335                 index = (frame_index(zone, frame)) -
    336                     (1 << frame->buddy_order);
    337         }
    338        
    339         if (frame_index_valid(zone, index)) {
    340                 if ((zone->frames[index].buddy_order == frame->buddy_order) &&
    341                     (zone->frames[index].refcount == 0)) {
    342                         return &zone->frames[index].buddy_link;
    343                 }
    344         }
    345        
    346         return NULL;
    347 }
    348 
    349 /** Buddy system bisect implementation.
    350  *
    351  * @param buddy Buddy system.
    352  * @param block Block to bisect.
    353  *
    354  * @return Right block.
    355  *
    356  */
    357 NO_TRACE static link_t *zone_buddy_bisect(buddy_system_t *buddy, link_t *block)
    358 {
    359         frame_t *frame_l = list_get_instance(block, frame_t, buddy_link);
    360         frame_t *frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
    361        
    362         return &frame_r->buddy_link;
    363 }
    364 
    365 /** Buddy system coalesce implementation.
    366  *
    367  * @param buddy   Buddy system.
    368  * @param block_1 First block.
    369  * @param block_2 First block's buddy.
    370  *
    371  * @return Coalesced block (actually block that represents lower
    372  *         address).
    373  *
    374  */
    375 NO_TRACE static link_t *zone_buddy_coalesce(buddy_system_t *buddy,
    376     link_t *block_1, link_t *block_2)
    377 {
    378         frame_t *frame1 = list_get_instance(block_1, frame_t, buddy_link);
    379         frame_t *frame2 = list_get_instance(block_2, frame_t, buddy_link);
    380        
    381         return ((frame1 < frame2) ? block_1 : block_2);
    382 }
    383 
    384 /** Buddy system set_order implementation.
    385  *
    386  * @param buddy Buddy system.
    387  * @param block Buddy system block.
    388  * @param order Order to set.
    389  *
    390  */
    391 NO_TRACE static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
    392     uint8_t order)
    393 {
    394         list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
    395 }
    396 
    397 /** Buddy system get_order implementation.
    398  *
    399  * @param buddy Buddy system.
    400  * @param block Buddy system block.
    401  *
    402  * @return Order of block.
    403  *
    404  */
    405 NO_TRACE static uint8_t zone_buddy_get_order(buddy_system_t *buddy,
    406     link_t *block)
    407 {
    408         return list_get_instance(block, frame_t, buddy_link)->buddy_order;
    409 }
    410 
    411 /** Buddy system mark_busy implementation.
    412  *
    413  * @param buddy Buddy system.
    414  * @param block Buddy system block.
    415  *
    416  */
    417 NO_TRACE static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t *block)
    418 {
    419         list_get_instance(block, frame_t, buddy_link)->refcount = 1;
    420 }
    421 
    422 /** Buddy system mark_available implementation.
    423  *
    424  * @param buddy Buddy system.
    425  * @param block Buddy system block.
    426  *
    427  */
    428 NO_TRACE static void zone_buddy_mark_available(buddy_system_t *buddy,
    429     link_t *block)
    430 {
    431         list_get_instance(block, frame_t, buddy_link)->refcount = 0;
    432 }
    433 
    434 static buddy_system_operations_t zone_buddy_system_operations = {
    435         .find_buddy = zone_buddy_find_buddy,
    436         .bisect = zone_buddy_bisect,
    437         .coalesce = zone_buddy_coalesce,
    438         .set_order = zone_buddy_set_order,
    439         .get_order = zone_buddy_get_order,
    440         .mark_busy = zone_buddy_mark_busy,
    441         .mark_available = zone_buddy_mark_available,
    442         .find_block = zone_buddy_find_block
    443 };
     346        /*
     347         * Prefer zones with low-priority memory over
     348         * zones with high-priority memory.
     349         */
     350       
     351        size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
     352        if (znum != (size_t) -1)
     353                return znum;
     354       
     355        /* Take all zones into account */
     356        return find_free_zone_all(count, flags, constraint, hint);
     357}
    444358
    445359/******************/
     
    447361/******************/
    448362
     363/** Return frame from zone. */
     364NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)
     365{
     366        ASSERT(index < zone->count);
     367       
     368        return &zone->frames[index];
     369}
     370
    449371/** Allocate frame in particular zone.
    450372 *
     
    452374 * Panics if allocation is impossible.
    453375 *
    454  * @param zone  Zone to allocate from.
    455  * @param order Allocate exactly 2^order frames.
     376 * @param zone       Zone to allocate from.
     377 * @param count      Number of frames to allocate
     378 * @param constraint Indication of bits that cannot be set in the
     379 *                   physical frame number of the first allocated frame.
    456380 *
    457381 * @return Frame index in zone.
    458382 *
    459383 */
    460 NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
     384NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
     385    pfn_t constraint)
    461386{
    462387        ASSERT(zone->flags & ZONE_AVAILABLE);
    463388       
    464         /* Allocate frames from zone buddy system */
    465         link_t *link = buddy_system_alloc(zone->buddy_system, order);
    466        
    467         ASSERT(link);
     389        /* Allocate frames from zone */
     390        size_t index;
     391        int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
     392            FRAME_LOWPRIO, constraint, &index);
     393       
     394        ASSERT(avail);
     395       
     396        /* Update frame reference count */
     397        for (size_t i = 0; i < count; i++) {
     398                frame_t *frame = zone_get_frame(zone, index + i);
     399               
     400                ASSERT(frame->refcount == 0);
     401                frame->refcount = 1;
     402        }
    468403       
    469404        /* Update zone information. */
    470         zone->free_count -= (1 << order);
    471         zone->busy_count += (1 << order);
    472        
    473         /* Frame will be actually a first frame of the block. */
    474         frame_t *frame = list_get_instance(link, frame_t, buddy_link);
    475        
    476         /* Get frame address */
    477         return make_frame_index(zone, frame);
     405        zone->free_count -= count;
     406        zone->busy_count += count;
     407       
     408        return index;
    478409}
    479410
     
    482413 * Assume zone is locked and is available for deallocation.
    483414 *
    484  * @param zone      Pointer to zone from which the frame is to be freed.
    485  * @param frame_idx Frame index relative to zone.
    486  *
    487  * @return          Number of freed frames.
    488  *
    489  */
    490 NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
     415 * @param zone  Pointer to zone from which the frame is to be freed.
     416 * @param index Frame index relative to zone.
     417 *
     418 * @return Number of freed frames.
     419 *
     420 */
     421NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
    491422{
    492423        ASSERT(zone->flags & ZONE_AVAILABLE);
    493424       
    494         frame_t *frame = &zone->frames[frame_idx];
    495         size_t size = 0;
    496        
    497         ASSERT(frame->refcount);
     425        frame_t *frame = zone_get_frame(zone, index);
     426       
     427        ASSERT(frame->refcount > 0);
    498428       
    499429        if (!--frame->refcount) {
    500                 size = 1 << frame->buddy_order;
    501                 buddy_system_free(zone->buddy_system, &frame->buddy_link);             
     430                bitmap_set(&zone->bitmap, index, 0);
     431               
    502432                /* Update zone information. */
    503                 zone->free_count += size;
    504                 zone->busy_count -= size;
    505         }
    506        
    507         return size;
    508 }
    509 
    510 /** Return frame from zone. */
    511 NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t frame_idx)
    512 {
    513         ASSERT(frame_idx < zone->count);
    514         return &zone->frames[frame_idx];
     433                zone->free_count++;
     434                zone->busy_count--;
     435               
     436                return 1;
     437        }
     438       
     439        return 0;
    515440}
    516441
    517442/** Mark frame in zone unavailable to allocation. */
    518 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
    519 {
    520         if (!(zone->flags & ZONE_AVAILABLE))
     443NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
     444{
     445        ASSERT(zone->flags & ZONE_AVAILABLE);
     446       
     447        frame_t *frame = zone_get_frame(zone, index);
     448        if (frame->refcount > 0)
    521449                return;
    522 //      ASSERT(zone->flags & ZONE_AVAILABLE);
    523        
    524         frame_t *frame = zone_get_frame(zone, frame_idx);
    525         if (frame->refcount)
    526                 return;
    527        
    528         link_t *link __attribute__ ((unused));
    529        
    530         link = buddy_system_alloc_block(zone->buddy_system,
    531             &frame->buddy_link);
    532        
    533         ASSERT(link);
     450       
     451        frame->refcount = 1;
     452        bitmap_set_range(&zone->bitmap, index, 1);
     453       
    534454        zone->free_count--;
    535455        reserve_force_alloc(1);
     
    538458/** Merge two zones.
    539459 *
    540  * Expect buddy to point to space at least zone_conf_size large.
    541460 * Assume z1 & z2 are locked and compatible and zones lock is
    542461 * locked.
    543462 *
    544  * @param z1     First zone to merge.
    545  * @param z2     Second zone to merge.
    546  * @param old_z1 Original date of the first zone.
    547  * @param buddy  Merged zone buddy.
     463 * @param z1       First zone to merge.
     464 * @param z2       Second zone to merge.
     465 * @param old_z1   Original data of the first zone.
     466 * @param confdata Merged zone configuration data.
    548467 *
    549468 */
    550469NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
    551     buddy_system_t *buddy)
     470    void *confdata)
    552471{
    553472        ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
     
    564483        zones.info[z1].free_count += zones.info[z2].free_count;
    565484        zones.info[z1].busy_count += zones.info[z2].busy_count;
    566         zones.info[z1].buddy_system = buddy;
    567        
    568         uint8_t order = fnzb(zones.info[z1].count);
    569         buddy_system_create(zones.info[z1].buddy_system, order,
    570             &zone_buddy_system_operations, (void *) &zones.info[z1]);
    571        
    572         zones.info[z1].frames =
    573             (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
    574             + buddy_conf_size(order));
    575        
    576         /* This marks all frames busy */
    577         size_t i;
    578         for (i = 0; i < zones.info[z1].count; i++)
    579                 frame_initialize(&zones.info[z1].frames[i]);
    580        
    581         /* Copy frames from both zones to preserve full frame orders,
    582          * parents etc. Set all free frames with refcount = 0 to 1, because
    583          * we add all free frames to buddy allocator later again, clearing
    584          * order to 0. Don't set busy frames with refcount = 0, as they
    585          * will not be reallocated during merge and it would make later
    586          * problems with allocation/free.
     485       
     486        bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
     487            confdata + (sizeof(frame_t) * zones.info[z1].count));
     488        bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count);
     489       
     490        zones.info[z1].frames = (frame_t *) confdata;
     491       
     492        /*
     493         * Copy frames and bits from both zones to preserve parents, etc.
    587494         */
    588         for (i = 0; i < old_z1->count; i++)
     495       
     496        for (size_t i = 0; i < old_z1->count; i++) {
     497                bitmap_set(&zones.info[z1].bitmap, i,
     498                    bitmap_get(&old_z1->bitmap, i));
    589499                zones.info[z1].frames[i] = old_z1->frames[i];
    590        
    591         for (i = 0; i < zones.info[z2].count; i++)
    592                 zones.info[z1].frames[base_diff + i]
    593                     = zones.info[z2].frames[i];
    594        
    595         i = 0;
    596         while (i < zones.info[z1].count) {
    597                 if (zones.info[z1].frames[i].refcount) {
    598                         /* Skip busy frames */
    599                         i += 1 << zones.info[z1].frames[i].buddy_order;
    600                 } else {
    601                         /* Free frames, set refcount = 1
    602                          * (all free frames have refcount == 0, we need not
    603                          * to check the order)
    604                          */
    605                         zones.info[z1].frames[i].refcount = 1;
    606                         zones.info[z1].frames[i].buddy_order = 0;
    607                         i++;
    608                 }
    609         }
    610        
    611         /* Add free blocks from the original zone z1 */
    612         while (zone_can_alloc(old_z1, 0)) {
    613                 /* Allocate from the original zone */
    614                 pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
    615                
    616                 /* Free the frame from the merged zone */
    617                 frame_t *frame = &zones.info[z1].frames[frame_idx];
    618                 frame->refcount = 0;
    619                 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
    620         }
    621        
    622         /* Add free blocks from the original zone z2 */
    623         while (zone_can_alloc(&zones.info[z2], 0)) {
    624                 /* Allocate from the original zone */
    625                 pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
    626                
    627                 /* Free the frame from the merged zone */
    628                 frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
    629                 frame->refcount = 0;
    630                 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
     500        }
     501       
     502        for (size_t i = 0; i < zones.info[z2].count; i++) {
     503                bitmap_set(&zones.info[z1].bitmap, base_diff + i,
     504                    bitmap_get(&zones.info[z2].bitmap, i));
     505                zones.info[z1].frames[base_diff + i] =
     506                    zones.info[z2].frames[i];
    631507        }
    632508}
     
    651527        size_t cframes = SIZE2FRAMES(zone_conf_size(count));
    652528       
    653         if ((pfn < zones.info[znum].base)
    654             || (pfn >= zones.info[znum].base + zones.info[znum].count))
     529        if ((pfn < zones.info[znum].base) ||
     530            (pfn >= zones.info[znum].base + zones.info[znum].count))
    655531                return;
    656532       
    657         frame_t *frame __attribute__ ((unused));
    658 
    659         frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
    660         ASSERT(!frame->buddy_order);
    661        
    662         size_t i;
    663         for (i = 0; i < cframes; i++) {
    664                 zones.info[znum].busy_count++;
     533        for (size_t i = 0; i < cframes; i++)
    665534                (void) zone_frame_free(&zones.info[znum],
    666535                    pfn - zones.info[znum].base + i);
    667         }
    668 }
    669 
    670 /** Reduce allocated block to count of order 0 frames.
    671  *
    672  * The allocated block needs 2^order frames. Reduce all frames
    673  * in the block to order 0 and free the unneeded frames. This means that
    674  * when freeing the previously allocated block starting with frame_idx,
    675  * you have to free every frame.
    676  *
    677  * @param znum      Zone.
    678  * @param frame_idx Index the first frame of the block.
    679  * @param count     Allocated frames in block.
    680  *
    681  */
    682 NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,
    683     size_t count)
    684 {
    685         ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
    686         ASSERT(frame_idx + count < zones.info[znum].count);
    687        
    688         uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
    689         ASSERT((size_t) (1 << order) >= count);
    690        
    691         /* Reduce all blocks to order 0 */
    692         size_t i;
    693         for (i = 0; i < (size_t) (1 << order); i++) {
    694                 frame_t *frame = &zones.info[znum].frames[i + frame_idx];
    695                 frame->buddy_order = 0;
    696                 if (!frame->refcount)
    697                         frame->refcount = 1;
    698                 ASSERT(frame->refcount == 1);
    699         }
    700        
    701         /* Free unneeded frames */
    702         for (i = count; i < (size_t) (1 << order); i++)
    703                 (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    704536}
    705537
     
    721553        bool ret = true;
    722554       
    723         /* We can join only 2 zones with none existing inbetween,
     555        /*
     556         * We can join only 2 zones with none existing inbetween,
    724557         * the zones have to be available and with the same
    725558         * set of flags
     
    735568            + zones.info[z2].count));
    736569       
    737         uint8_t order;
    738         if (cframes == 1)
    739                 order = 0;
    740         else
    741                 order = fnzb(cframes - 1) + 1;
    742        
    743570        /* Allocate merged zone data inside one of the zones */
    744571        pfn_t pfn;
    745         if (zone_can_alloc(&zones.info[z1], order)) {
    746                 pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
    747         } else if (zone_can_alloc(&zones.info[z2], order)) {
    748                 pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
     572        if (zone_can_alloc(&zones.info[z1], cframes, 0)) {
     573                pfn = zones.info[z1].base +
     574                    zone_frame_alloc(&zones.info[z1], cframes, 0);
     575        } else if (zone_can_alloc(&zones.info[z2], cframes, 0)) {
     576                pfn = zones.info[z2].base +
     577                    zone_frame_alloc(&zones.info[z2], cframes, 0);
    749578        } else {
    750579                ret = false;
     
    754583        /* Preserve original data from z1 */
    755584        zone_t old_z1 = zones.info[z1];
    756         old_z1.buddy_system->data = (void *) &old_z1;
    757585       
    758586        /* Do zone merging */
    759         buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
    760         zone_merge_internal(z1, z2, &old_z1, buddy);
    761        
    762         /* Free unneeded config frames */
    763         zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
     587        zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn)));
    764588       
    765589        /* Subtract zone information from busy frames */
     
    774598       
    775599        /* Move zones down */
    776         size_t i;
    777         for (i = z2 + 1; i < zones.count; i++) {
     600        for (size_t i = z2 + 1; i < zones.count; i++)
    778601                zones.info[i - 1] = zones.info[i];
    779                 if (zones.info[i - 1].buddy_system != NULL)
    780                         zones.info[i - 1].buddy_system->data =
    781                             (void *) &zones.info[i - 1];
    782         }
    783602       
    784603        zones.count--;
     
    799618void zone_merge_all(void)
    800619{
    801         size_t i = 0;
     620        size_t i = 1;
     621       
    802622        while (i < zones.count) {
    803                 if (!zone_merge(i, i + 1))
     623                if (!zone_merge(i - 1, i))
    804624                        i++;
    805625        }
     
    808628/** Create new frame zone.
    809629 *
    810  * @param zone  Zone to construct.
    811  * @param buddy Address of buddy system configuration information.
    812  * @param start Physical address of the first frame within the zone.
    813  * @param count Count of frames in zone.
    814  * @param flags Zone flags.
     630 * @param zone     Zone to construct.
     631 * @param start    Physical address of the first frame within the zone.
     632 * @param count    Count of frames in zone.
     633 * @param flags    Zone flags.
     634 * @param confdata Configuration data of the zone.
    815635 *
    816636 * @return Initialized zone.
    817637 *
    818638 */
    819 NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,
    820     pfn_t start, size_t count, zone_flags_t flags)
     639NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
     640    zone_flags_t flags, void *confdata)
    821641{
    822642        zone->base = start;
     
    825645        zone->free_count = count;
    826646        zone->busy_count = 0;
    827         zone->buddy_system = buddy;
    828647       
    829648        if (flags & ZONE_AVAILABLE) {
    830649                /*
    831                  * Compute order for buddy system and initialize
     650                 * Initialize frame bitmap (located after the array of
     651                 * frame_t structures in the configuration space).
    832652                 */
    833                 uint8_t order = fnzb(count);
    834                 buddy_system_create(zone->buddy_system, order,
    835                     &zone_buddy_system_operations, (void *) zone);
    836                
    837                 /* Allocate frames _after_ the confframe */
    838                
    839                 /* Check sizes */
    840                 zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
    841                     buddy_conf_size(order));
    842                
    843                 size_t i;
    844                 for (i = 0; i < count; i++)
     653               
     654                bitmap_initialize(&zone->bitmap, count, confdata +
     655                    (sizeof(frame_t) * count));
     656                bitmap_clear_range(&zone->bitmap, 0, count);
     657               
     658                /*
     659                 * Initialize the array of frame_t structures.
     660                 */
     661               
     662                zone->frames = (frame_t *) confdata;
     663               
     664                for (size_t i = 0; i < count; i++)
    845665                        frame_initialize(&zone->frames[i]);
    846                
    847                 /* Stuffing frames */
    848                 for (i = 0; i < count; i++) {
    849                         zone->frames[i].refcount = 0;
    850                         buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
    851                 }
    852         } else
     666        } else {
     667                bitmap_initialize(&zone->bitmap, 0, NULL);
    853668                zone->frames = NULL;
     669        }
    854670}
    855671
     
    863679size_t zone_conf_size(size_t count)
    864680{
    865         return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
     681        return (count * sizeof(frame_t) + bitmap_size(count));
    866682}
    867683
     
    869685pfn_t zone_external_conf_alloc(size_t count)
    870686{
    871         size_t size = zone_conf_size(count);
    872         size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
    873 
    874         return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH,
    875             FRAME_LOWMEM | FRAME_ATOMIC));
     687        size_t frames = SIZE2FRAMES(zone_conf_size(count));
     688       
     689        return ADDR2PFN((uintptr_t)
     690            frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0));
    876691}
    877692
     
    881696 * @param count     Size of zone in frames.
    882697 * @param confframe Where configuration frames are supposed to be.
    883  *                  Automatically checks, that we will not disturb the
     698 *                  Automatically checks that we will not disturb the
    884699 *                  kernel and possibly init. If confframe is given
    885700 *                  _outside_ this zone, it is expected, that the area is
     
    898713       
    899714        if (flags & ZONE_AVAILABLE) {  /* Create available zone */
    900                 /* Theoretically we could have NULL here, practically make sure
     715                /*
     716                 * Theoretically we could have NULL here, practically make sure
    901717                 * nobody tries to do that. If some platform requires, remove
    902718                 * the assert
    903719                 */
    904720                ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
    905 
     721               
    906722                /* Update the known end of physical memory. */
    907723                config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
    908724               
    909                 /* If confframe is supposed to be inside our zone, then make sure
     725                /*
     726                 * If confframe is supposed to be inside our zone, then make sure
    910727                 * it does not span kernel & init
    911728                 */
    912729                size_t confcount = SIZE2FRAMES(zone_conf_size(count));
     730               
    913731                if ((confframe >= start) && (confframe < start + count)) {
    914732                        for (; confframe < start + count; confframe++) {
     
    923741                               
    924742                                bool overlap = false;
    925                                 size_t i;
    926                                 for (i = 0; i < init.cnt; i++)
     743                                for (size_t i = 0; i < init.cnt; i++) {
    927744                                        if (overlaps(addr, PFN2ADDR(confcount),
    928745                                            init.tasks[i].paddr,
     
    931748                                                break;
    932749                                        }
     750                                }
     751                               
    933752                                if (overlap)
    934753                                        continue;
     
    937756                        }
    938757                       
    939                         if (confframe >= start + count) {
    940                                 flags &= ~ZONE_AVAILABLE;
    941                                 goto nonavail;
    942 //                              panic("Cannot find configuration data for zone.");
    943                         }
     758                        if (confframe >= start + count)
     759                                panic("Cannot find configuration data for zone.");
    944760                }
    945761               
     
    950766                }
    951767               
    952                 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
    953                 zone_construct(&zones.info[znum], buddy, start, count, flags);
     768                void *confdata = (void *) PA2KA(PFN2ADDR(confframe));
     769                zone_construct(&zones.info[znum], start, count, flags, confdata);
    954770               
    955771                /* If confdata in zone, mark as unavailable */
    956772                if ((confframe >= start) && (confframe < start + count)) {
    957                         size_t i;
    958                         for (i = confframe; i < confframe + confcount; i++)
     773                        for (size_t i = confframe; i < confframe + confcount; i++)
    959774                                zone_mark_unavailable(&zones.info[znum],
    960775                                    i - zones.info[znum].base);
     
    965780                return znum;
    966781        }
    967 nonavail:
    968         (void)0; // label trick
     782       
    969783        /* Non-available zone */
    970784        size_t znum = zones_insert_zone(start, count, flags);
     
    973787                return (size_t) -1;
    974788        }
    975         zone_construct(&zones.info[znum], NULL, start, count, flags);
     789       
     790        zone_construct(&zones.info[znum], start, count, flags, NULL);
    976791       
    977792        irq_spinlock_unlock(&zones.lock, true);
     
    1015830}
    1016831
    1017 /** Allocate power-of-two frames of physical memory.
    1018  *
    1019  * @param order Allocate exactly 2^order frames.
    1020  * @param flags Flags for host zone selection and address processing.
    1021  * @param pzone Preferred zone.
     832/** Allocate frames of physical memory.
     833 *
     834 * @param count      Number of continuous frames to allocate.
     835 * @param flags      Flags for host zone selection and address processing.
     836 * @param constraint Indication of physical address bits that cannot be
     837 *                   set in the address of the first allocated frame.
     838 * @param pzone      Preferred zone.
    1022839 *
    1023840 * @return Physical address of the allocated frame.
    1024841 *
    1025842 */
    1026 void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
    1027 {
    1028         size_t size = ((size_t) 1) << order;
     843uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
     844    uintptr_t constraint, size_t *pzone)
     845{
     846        ASSERT(count > 0);
     847       
    1029848        size_t hint = pzone ? (*pzone) : 0;
     849        pfn_t frame_constraint = ADDR2PFN(constraint);
    1030850       
    1031851        /*
    1032852         * If not told otherwise, we must first reserve the memory.
    1033853         */
    1034         if (!(flags & FRAME_NO_RESERVE)) 
    1035                 reserve_force_alloc(size);
    1036 
     854        if (!(flags & FRAME_NO_RESERVE))
     855                reserve_force_alloc(count);
     856       
    1037857loop:
    1038858        irq_spinlock_lock(&zones.lock, true);
     
    1041861         * First, find suitable frame zone.
    1042862         */
    1043         size_t znum = find_free_zone(order,
    1044             FRAME_TO_ZONE_FLAGS(flags), hint);
    1045        
    1046         /* If no memory, reclaim some slab memory,
    1047            if it does not help, reclaim all */
     863        size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     864            frame_constraint, hint);
     865       
     866        /*
     867         * If no memory, reclaim some slab memory,
     868         * if it does not help, reclaim all.
     869         */
    1048870        if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
    1049871                irq_spinlock_unlock(&zones.lock, true);
     
    1052874               
    1053875                if (freed > 0)
    1054                         znum = find_free_zone(order,
    1055                             FRAME_TO_ZONE_FLAGS(flags), hint);
     876                        znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     877                            frame_constraint, hint);
    1056878               
    1057879                if (znum == (size_t) -1) {
     
    1061883                       
    1062884                        if (freed > 0)
    1063                                 znum = find_free_zone(order,
    1064                                     FRAME_TO_ZONE_FLAGS(flags), hint);
     885                                znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     886                                    frame_constraint, hint);
    1065887                }
    1066888        }
     
    1069891                if (flags & FRAME_ATOMIC) {
    1070892                        irq_spinlock_unlock(&zones.lock, true);
     893                       
    1071894                        if (!(flags & FRAME_NO_RESERVE))
    1072                                 reserve_free(size);
    1073                         return NULL;
     895                                reserve_free(count);
     896                       
     897                        return 0;
    1074898                }
    1075899               
     
    1081905               
    1082906                if (!THREAD)
    1083                         panic("Cannot wait for memory to become available.");
     907                        panic("Cannot wait for %zu frames to become available "
     908                            "(%zu available).", count, avail);
    1084909               
    1085910                /*
     
    1088913               
    1089914#ifdef CONFIG_DEBUG
    1090                 printf("Thread %" PRIu64 " waiting for %zu frames, "
    1091                     "%zu available.\n", THREAD->tid, size, avail);
     915                printf("Thread %" PRIu64 " waiting for %zu frames "
     916                    "(%zu available).\n", THREAD->tid, count, avail);
    1092917#endif
    1093918               
    1094919                /*
    1095                  * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
    1096                  * to prevent deadlock with TLB shootdown.
     920                 * Since the mem_avail_mtx is an active mutex, we need to
     921                 * disable interrupts to prevent deadlock with TLB shootdown.
    1097922                 */
    1098923                ipl_t ipl = interrupts_disable();
     
    1100925               
    1101926                if (mem_avail_req > 0)
    1102                         mem_avail_req = min(mem_avail_req, size);
     927                        mem_avail_req = min(mem_avail_req, count);
    1103928                else
    1104                         mem_avail_req = size;
     929                        mem_avail_req = count;
     930               
    1105931                size_t gen = mem_avail_gen;
    1106932               
     
    1118944        }
    1119945       
    1120         pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
    1121             + zones.info[znum].base;
     946        pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,
     947            frame_constraint) + zones.info[znum].base;
    1122948       
    1123949        irq_spinlock_unlock(&zones.lock, true);
     
    1126952                *pzone = znum;
    1127953       
    1128         if (flags & FRAME_KA)
    1129                 return (void *) PA2KA(PFN2ADDR(pfn));
    1130        
    1131         return (void *) PFN2ADDR(pfn);
    1132 }
    1133 
    1134 void *frame_alloc(uint8_t order, frame_flags_t flags)
    1135 {
    1136         return frame_alloc_generic(order, flags, NULL);
    1137 }
    1138 
    1139 void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
    1140 {
    1141         return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
    1142 }
    1143 
    1144 /** Free a frame.
    1145  *
    1146  * Find respective frame structure for supplied physical frame address.
    1147  * Decrement frame reference count. If it drops to zero, move the frame
    1148  * structure to free list.
    1149  *
    1150  * @param frame Physical Address of of the frame to be freed.
     954        return PFN2ADDR(pfn);
     955}
     956
     957uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint)
     958{
     959        return frame_alloc_generic(count, flags, constraint, NULL);
     960}
     961
     962/** Free frames of physical memory.
     963 *
     964 * Find respective frame structures for supplied physical frames.
     965 * Decrement each frame reference count. If it drops to zero, mark
     966 * the frames as available.
     967 *
     968 * @param start Physical Address of the first frame to be freed.
     969 * @param count Number of frames to free.
    1151970 * @param flags Flags to control memory reservation.
    1152971 *
    1153972 */
    1154 void frame_free_generic(uintptr_t frame, frame_flags_t flags)
    1155 {
    1156         size_t size;
     973void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
     974{
     975        size_t freed = 0;
    1157976       
    1158977        irq_spinlock_lock(&zones.lock, true);
    1159978       
    1160         /*
    1161          * First, find host frame zone for addr.
    1162          */
    1163         pfn_t pfn = ADDR2PFN(frame);
    1164         size_t znum = find_zone(pfn, 1, 0);
    1165 
    1166         ASSERT(znum != (size_t) -1);
    1167        
    1168         size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     979        for (size_t i = 0; i < count; i++) {
     980                /*
     981                 * First, find host frame zone for addr.
     982                 */
     983                pfn_t pfn = ADDR2PFN(start) + i;
     984                size_t znum = find_zone(pfn, 1, 0);
     985               
     986                ASSERT(znum != (size_t) -1);
     987               
     988                freed += zone_frame_free(&zones.info[znum],
     989                    pfn - zones.info[znum].base);
     990        }
    1169991       
    1170992        irq_spinlock_unlock(&zones.lock, true);
     
    1172994        /*
    1173995         * Signal that some memory has been freed.
     996         * Since the mem_avail_mtx is an active mutex,
     997         * we need to disable interruptsto prevent deadlock
     998         * with TLB shootdown.
    1174999         */
    1175 
    1176        
    1177         /*
    1178          * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
    1179          * to prevent deadlock with TLB shootdown.
    1180          */
     1000       
    11811001        ipl_t ipl = interrupts_disable();
    11821002        mutex_lock(&mem_avail_mtx);
     1003       
    11831004        if (mem_avail_req > 0)
    1184                 mem_avail_req -= min(mem_avail_req, size);
     1005                mem_avail_req -= min(mem_avail_req, freed);
    11851006       
    11861007        if (mem_avail_req == 0) {
     
    11881009                condvar_broadcast(&mem_avail_cv);
    11891010        }
     1011       
    11901012        mutex_unlock(&mem_avail_mtx);
    11911013        interrupts_restore(ipl);
    11921014       
    11931015        if (!(flags & FRAME_NO_RESERVE))
    1194                 reserve_free(size);
    1195 }
    1196 
    1197 void frame_free(uintptr_t frame)
    1198 {
    1199         frame_free_generic(frame, 0);
    1200 }
    1201 
    1202 void frame_free_noreserve(uintptr_t frame)
    1203 {
    1204         frame_free_generic(frame, FRAME_NO_RESERVE);
     1016                reserve_free(freed);
     1017}
     1018
     1019void frame_free(uintptr_t frame, size_t count)
     1020{
     1021        frame_free_generic(frame, count, 0);
     1022}
     1023
     1024void frame_free_noreserve(uintptr_t frame, size_t count)
     1025{
     1026        frame_free_generic(frame, count, FRAME_NO_RESERVE);
    12051027}
    12061028
     
    12361058        irq_spinlock_lock(&zones.lock, true);
    12371059       
    1238         size_t i;
    1239         for (i = 0; i < count; i++) {
     1060        for (size_t i = 0; i < count; i++) {
    12401061                size_t znum = find_zone(start + i, 1, 0);
     1062               
    12411063                if (znum == (size_t) -1)  /* PFN not found */
    12421064                        continue;
     
    12631085        /* Tell the architecture to create some memory */
    12641086        frame_low_arch_init();
     1087       
    12651088        if (config.cpu_active == 1) {
    12661089                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
     
    12691092                    SIZE2FRAMES(config.stack_size));
    12701093               
    1271                 size_t i;
    1272                 for (i = 0; i < init.cnt; i++) {
    1273                         pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
    1274                         frame_mark_unavailable(pfn,
     1094                for (size_t i = 0; i < init.cnt; i++)
     1095                        frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr),
    12751096                            SIZE2FRAMES(init.tasks[i].size));
    1276                 }
    12771097               
    12781098                if (ballocs.size)
     
    12801100                            SIZE2FRAMES(ballocs.size));
    12811101               
    1282                 /* Black list first frame, as allocating NULL would
     1102                /*
     1103                 * Blacklist first frame, as allocating NULL would
    12831104                 * fail in some places
    12841105                 */
    12851106                frame_mark_unavailable(0, 1);
    12861107        }
     1108       
    12871109        frame_high_arch_init();
    12881110}
     
    12901112/** Adjust bounds of physical memory region according to low/high memory split.
    12911113 *
    1292  * @param low[in]       If true, the adjustment is performed to make the region
    1293  *                      fit in the low memory. Otherwise the adjustment is
    1294  *                      performed to make the region fit in the high memory.
    1295  * @param basep[inout]  Pointer to a variable which contains the region's base
    1296  *                      address and which may receive the adjusted base address.
    1297  * @param sizep[inout]  Pointer to a variable which contains the region's size
    1298  *                      and which may receive the adjusted size.
    1299  * @retun               True if the region still exists even after the
    1300  *                      adjustment, false otherwise.
     1114 * @param low[in]      If true, the adjustment is performed to make the region
     1115 *                     fit in the low memory. Otherwise the adjustment is
     1116 *                     performed to make the region fit in the high memory.
     1117 * @param basep[inout] Pointer to a variable which contains the region's base
     1118 *                     address and which may receive the adjusted base address.
     1119 * @param sizep[inout] Pointer to a variable which contains the region's size
     1120 *                     and which may receive the adjusted size.
     1121 *
     1122 * @return True if the region still exists even after the adjustment.
     1123 * @return False otherwise.
     1124 *
    13011125 */
    13021126bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
    13031127{
    13041128        uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
    1305 
     1129       
    13061130        if (low) {
    13071131                if (*basep > limit)
    13081132                        return false;
     1133               
    13091134                if (*basep + *sizep > limit)
    13101135                        *sizep = limit - *basep;
     
    13121137                if (*basep + *sizep <= limit)
    13131138                        return false;
     1139               
    13141140                if (*basep <= limit) {
    13151141                        *sizep -= limit - *basep;
     
    13171143                }
    13181144        }
     1145       
    13191146        return true;
    13201147}
     
    13281155       
    13291156        uint64_t total = 0;
    1330         size_t i;
    1331         for (i = 0; i < zones.count; i++)
     1157       
     1158        for (size_t i = 0; i < zones.count; i++)
    13321159                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13331160       
     
    13521179        *free = 0;
    13531180       
    1354         size_t i;
    1355         for (i = 0; i < zones.count; i++) {
     1181        for (size_t i = 0; i < zones.count; i++) {
    13561182                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13571183               
     
    13811207        /*
    13821208         * Because printing may require allocation of memory, we may not hold
    1383          * the frame allocator locks when printing zone statistics.  Therefore,
     1209         * the frame allocator locks when printing zone statistics. Therefore,
    13841210         * we simply gather the statistics under the protection of the locks and
    13851211         * print the statistics when the locks have been released.
     
    13901216         */
    13911217       
    1392         size_t i;
    1393         for (i = 0;; i++) {
     1218        size_t free_lowmem = 0;
     1219        size_t free_highmem = 0;
     1220        size_t free_highprio = 0;
     1221       
     1222        for (size_t i = 0;; i++) {
    13941223                irq_spinlock_lock(&zones.lock, true);
    13951224               
     
    13991228                }
    14001229               
    1401                 uintptr_t base = PFN2ADDR(zones.info[i].base);
     1230                pfn_t fbase = zones.info[i].base;
     1231                uintptr_t base = PFN2ADDR(fbase);
    14021232                size_t count = zones.info[i].count;
    14031233                zone_flags_t flags = zones.info[i].flags;
     
    14051235                size_t busy_count = zones.info[i].busy_count;
    14061236               
     1237                bool available = ((flags & ZONE_AVAILABLE) != 0);
     1238                bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1239                bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1240                bool highprio = is_high_priority(fbase, count);
     1241               
     1242                if (available) {
     1243                        if (lowmem)
     1244                                free_lowmem += free_count;
     1245                       
     1246                        if (highmem)
     1247                                free_highmem += free_count;
     1248                       
     1249                        if (highprio) {
     1250                                free_highprio += free_count;
     1251                        } else {
     1252                                /*
     1253                                 * Walk all frames of the zone and examine
     1254                                 * all high priority memory to get accurate
     1255                                 * statistics.
     1256                                 */
     1257                               
     1258                                for (size_t index = 0; index < count; index++) {
     1259                                        if (is_high_priority(fbase + index, 0)) {
     1260                                                if (!bitmap_get(&zones.info[i].bitmap, index))
     1261                                                        free_highprio++;
     1262                                        } else
     1263                                                break;
     1264                                }
     1265                        }
     1266                }
     1267               
    14071268                irq_spinlock_unlock(&zones.lock, true);
    1408                
    1409                 bool available = ((flags & ZONE_AVAILABLE) != 0);
    14101269               
    14111270                printf("%-4zu", i);
     
    14321291                printf("\n");
    14331292        }
     1293       
     1294        printf("\n");
     1295       
     1296        uint64_t size;
     1297        const char *size_suffix;
     1298       
     1299        bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1300            false);
     1301        printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1302            free_lowmem, size, size_suffix);
     1303       
     1304        bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1305            false);
     1306        printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1307            free_highmem, size, size_suffix);
     1308       
     1309        bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1310            false);
     1311        printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1312            free_highprio, size, size_suffix);
    14341313}
    14351314
     
    14441323        size_t znum = (size_t) -1;
    14451324       
    1446         size_t i;
    1447         for (i = 0; i < zones.count; i++) {
     1325        for (size_t i = 0; i < zones.count; i++) {
    14481326                if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
    14491327                        znum = i;
     
    14581336        }
    14591337       
    1460         uintptr_t base = PFN2ADDR(zones.info[i].base);
    1461         zone_flags_t flags = zones.info[i].flags;
    1462         size_t count = zones.info[i].count;
    1463         size_t free_count = zones.info[i].free_count;
    1464         size_t busy_count = zones.info[i].busy_count;
     1338        size_t free_lowmem = 0;
     1339        size_t free_highmem = 0;
     1340        size_t free_highprio = 0;
     1341       
     1342        pfn_t fbase = zones.info[znum].base;
     1343        uintptr_t base = PFN2ADDR(fbase);
     1344        zone_flags_t flags = zones.info[znum].flags;
     1345        size_t count = zones.info[znum].count;
     1346        size_t free_count = zones.info[znum].free_count;
     1347        size_t busy_count = zones.info[znum].busy_count;
     1348       
     1349        bool available = ((flags & ZONE_AVAILABLE) != 0);
     1350        bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1351        bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1352        bool highprio = is_high_priority(fbase, count);
     1353       
     1354        if (available) {
     1355                if (lowmem)
     1356                        free_lowmem = free_count;
     1357               
     1358                if (highmem)
     1359                        free_highmem = free_count;
     1360               
     1361                if (highprio) {
     1362                        free_highprio = free_count;
     1363                } else {
     1364                        /*
     1365                         * Walk all frames of the zone and examine
     1366                         * all high priority memory to get accurate
     1367                         * statistics.
     1368                         */
     1369                       
     1370                        for (size_t index = 0; index < count; index++) {
     1371                                if (is_high_priority(fbase + index, 0)) {
     1372                                        if (!bitmap_get(&zones.info[znum].bitmap, index))
     1373                                                free_highprio++;
     1374                                } else
     1375                                        break;
     1376                        }
     1377                }
     1378        }
    14651379       
    14661380        irq_spinlock_unlock(&zones.lock, true);
    1467        
    1468         bool available = ((flags & ZONE_AVAILABLE) != 0);
    14691381       
    14701382        uint64_t size;
    14711383        const char *size_suffix;
     1384       
    14721385        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    14731386       
    1474         printf("Zone number:       %zu\n", znum);
    1475         printf("Zone base address: %p\n", (void *) base);
    1476         printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
     1387        printf("Zone number:             %zu\n", znum);
     1388        printf("Zone base address:       %p\n", (void *) base);
     1389        printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
    14771390            size, size_suffix);
    1478         printf("Zone flags:        %c%c%c%c%c\n",
     1391        printf("Zone flags:              %c%c%c%c%c\n",
    14791392            available ? 'A' : '-',
    14801393            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    14861399                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    14871400                    false);
    1488                 printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1401                printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
    14891402                    busy_count, size, size_suffix);
     1403               
    14901404                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    14911405                    false);
    1492                 printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1406                printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
    14931407                    free_count, size, size_suffix);
     1408               
     1409                bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1410                    false);
     1411                printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1412                    free_lowmem, size, size_suffix);
     1413               
     1414                bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1415                    false);
     1416                printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1417                    free_highmem, size, size_suffix);
     1418               
     1419                bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1420                    false);
     1421                printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1422                    free_highprio, size, size_suffix);
    14941423        }
    14951424}
Note: See TracChangeset for help on using the changeset viewer.