Ignore:
File:
1 edited

Legend:

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

    r905721b rc12f891  
    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 */
    6364
    6465zones_t zones;
     
    7374static size_t mem_avail_gen = 0;  /**< Generation counter. */
    7475
    75 /********************/
    76 /* Helper functions */
    77 /********************/
    78 
    79 NO_TRACE static inline size_t frame_index(zone_t *zone, frame_t *frame)
    80 {
    81         return (size_t) (frame - zone->frames);
    82 }
    83 
    84 NO_TRACE static inline size_t frame_index_abs(zone_t *zone, frame_t *frame)
    85 {
    86         return (size_t) (frame - zone->frames) + zone->base;
    87 }
    88 
    89 NO_TRACE static inline bool frame_index_valid(zone_t *zone, size_t index)
    90 {
    91         return (index < zone->count);
    92 }
    93 
    94 NO_TRACE static inline size_t make_frame_index(zone_t *zone, frame_t *frame)
    95 {
    96         return (frame - zone->frames);
    97 }
    98 
    9976/** Initialize frame structure.
    10077 *
     
    10481NO_TRACE static void frame_initialize(frame_t *frame)
    10582{
    106         frame->refcount = 1;
    107         frame->buddy_order = 0;
     83        frame->refcount = 0;
     84        frame->parent = NULL;
    10885}
    10986
     
    127104{
    128105        if (zones.count + 1 == ZONES_MAX) {
    129                 printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
     106                log(LF_OTHER, LVL_ERROR, "Maximum zone count %u exceeded!",
     107                    ZONES_MAX);
    130108                return (size_t) -1;
    131109        }
     
    147125                            (!iswithin(zones.info[i].base, zones.info[i].count,
    148126                            base, count))) {
    149                                 printf("Zone (%p, %p) overlaps "
    150                                     "with previous zone (%p %p)!\n",
     127                                log(LF_OTHER, LVL_WARN,
     128                                    "Zone (%p, %p) overlaps "
     129                                    "with previous zone (%p %p)!",
    151130                                    (void *) PFN2ADDR(base), (void *) PFN2ADDR(count),
    152131                                    (void *) PFN2ADDR(zones.info[i].base),
     
    161140       
    162141        /* Move other zones up */
    163         size_t j;
    164         for (j = zones.count; j > i; j--) {
     142        for (size_t j = zones.count; j > i; j--)
    165143                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         }
    170144       
    171145        zones.count++;
     
    237211}
    238212
    239 /** @return True if zone can allocate specified order */
    240 NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
    241 {
     213/** @return True if zone can allocate specified number of frames */
     214NO_TRACE static bool zone_can_alloc(zone_t *zone, size_t count,
     215    pfn_t constraint)
     216{
     217        /*
     218         * The function bitmap_allocate_range() does not modify
     219         * the bitmap if the last argument is NULL.
     220         */
     221       
    242222        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.
     223            bitmap_allocate_range(&zone->bitmap, count, zone->base,
     224            FRAME_LOWPRIO, constraint, NULL));
     225}
     226
     227/** Find a zone that can allocate specified number of frames
     228 *
     229 * This function searches among all zones. Assume interrupts are
     230 * disabled and zones lock is locked.
     231 *
     232 * @param count      Number of free frames we are trying to find.
     233 * @param flags      Required flags of the zone.
     234 * @param constraint Indication of bits that cannot be set in the
     235 *                   physical frame number of the first allocated frame.
     236 * @param hint       Preferred zone.
     237 *
     238 * @return Zone that can allocate specified number of frames.
     239 * @return -1 if no zone can satisfy the request.
     240 *
     241 */
     242NO_TRACE static size_t find_free_zone_all(size_t count, zone_flags_t flags,
     243    pfn_t constraint, size_t hint)
     244{
     245        for (size_t pos = 0; pos < zones.count; pos++) {
     246                size_t i = (pos + hint) % zones.count;
     247               
     248                /* Check whether the zone meets the search criteria. */
     249                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     250                        continue;
     251               
     252                /* Check if the zone can satisfy the allocation request. */
     253                if (zone_can_alloc(&zones.info[i], count, constraint))
     254                        return i;
     255        }
     256       
     257        return (size_t) -1;
     258}
     259
     260/** Check if frame range  priority memory
     261 *
     262 * @param pfn   Starting frame.
     263 * @param count Number of frames.
     264 *
     265 * @return True if the range contains only priority memory.
     266 *
     267 */
     268NO_TRACE static bool is_high_priority(pfn_t base, size_t count)
     269{
     270        return (base + count <= FRAME_LOWPRIO);
     271}
     272
     273/** Find a zone that can allocate specified number of frames
     274 *
     275 * This function ignores zones that contain only high-priority
     276 * memory. Assume interrupts are disabled and zones lock is locked.
     277 *
     278 * @param count      Number of free frames we are trying to find.
     279 * @param flags      Required flags of the zone.
     280 * @param constraint Indication of bits that cannot be set in the
     281 *                   physical frame number of the first allocated frame.
     282 * @param hint       Preferred zone.
     283 *
     284 * @return Zone that can allocate specified number of frames.
     285 * @return -1 if no low-priority zone can satisfy the request.
     286 *
     287 */
     288NO_TRACE static size_t find_free_zone_lowprio(size_t count, zone_flags_t flags,
     289    pfn_t constraint, size_t hint)
     290{       
     291        for (size_t pos = 0; pos < zones.count; pos++) {
     292                size_t i = (pos + hint) % zones.count;
     293               
     294                /* Skip zones containing only high-priority memory. */
     295                if (is_high_priority(zones.info[i].base, zones.info[i].count))
     296                        continue;
     297               
     298                /* Check whether the zone meets the search criteria. */
     299                if (!ZONE_FLAGS_MATCH(zones.info[i].flags, flags))
     300                        continue;
     301               
     302                /* Check if the zone can satisfy the allocation request. */
     303                if (zone_can_alloc(&zones.info[i], count, constraint))
     304                        return i;
     305        }
     306       
     307        return (size_t) -1;
     308}
     309
     310/** Find a zone that can allocate specified number of frames
    247311 *
    248312 * Assume interrupts are disabled and zones lock is
    249313 * locked.
    250314 *
    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)
     315 * @param count      Number of free frames we are trying to find.
     316 * @param flags      Required flags of the target zone.
     317 * @param constraint Indication of bits that cannot be set in the
     318 *                   physical frame number of the first allocated frame.
     319 * @param hint       Preferred zone.
     320 *
     321 * @return Zone that can allocate specified number of frames.
     322 * @return -1 if no zone can satisfy the request.
     323 *
     324 */
     325NO_TRACE static size_t find_free_zone(size_t count, zone_flags_t flags,
     326    pfn_t constraint, size_t hint)
    258327{
    259328        if (hint >= zones.count)
    260329                hint = 0;
    261330       
    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 };
     331        /*
     332         * Prefer zones with low-priority memory over
     333         * zones with high-priority memory.
     334         */
     335       
     336        size_t znum = find_free_zone_lowprio(count, flags, constraint, hint);
     337        if (znum != (size_t) -1)
     338                return znum;
     339       
     340        /* Take all zones into account */
     341        return find_free_zone_all(count, flags, constraint, hint);
     342}
    444343
    445344/******************/
     
    447346/******************/
    448347
     348/** Return frame from zone. */
     349NO_TRACE static frame_t *zone_get_frame(zone_t *zone, size_t index)
     350{
     351        ASSERT(index < zone->count);
     352       
     353        return &zone->frames[index];
     354}
     355
    449356/** Allocate frame in particular zone.
    450357 *
     
    452359 * Panics if allocation is impossible.
    453360 *
    454  * @param zone  Zone to allocate from.
    455  * @param order Allocate exactly 2^order frames.
     361 * @param zone       Zone to allocate from.
     362 * @param count      Number of frames to allocate
     363 * @param constraint Indication of bits that cannot be set in the
     364 *                   physical frame number of the first allocated frame.
    456365 *
    457366 * @return Frame index in zone.
    458367 *
    459368 */
    460 NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
     369NO_TRACE static size_t zone_frame_alloc(zone_t *zone, size_t count,
     370    pfn_t constraint)
    461371{
    462372        ASSERT(zone->flags & ZONE_AVAILABLE);
    463373       
    464         /* Allocate frames from zone buddy system */
    465         link_t *link = buddy_system_alloc(zone->buddy_system, order);
    466        
    467         ASSERT(link);
     374        /* Allocate frames from zone */
     375        size_t index = (size_t) -1;
     376        int avail = bitmap_allocate_range(&zone->bitmap, count, zone->base,
     377            FRAME_LOWPRIO, constraint, &index);
     378       
     379        ASSERT(avail);
     380        ASSERT(index != (size_t) -1);
     381       
     382        /* Update frame reference count */
     383        for (size_t i = 0; i < count; i++) {
     384                frame_t *frame = zone_get_frame(zone, index + i);
     385               
     386                ASSERT(frame->refcount == 0);
     387                frame->refcount = 1;
     388        }
    468389       
    469390        /* 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);
     391        zone->free_count -= count;
     392        zone->busy_count += count;
     393       
     394        return index;
    478395}
    479396
     
    482399 * Assume zone is locked and is available for deallocation.
    483400 *
    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)
     401 * @param zone  Pointer to zone from which the frame is to be freed.
     402 * @param index Frame index relative to zone.
     403 *
     404 * @return Number of freed frames.
     405 *
     406 */
     407NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t index)
    491408{
    492409        ASSERT(zone->flags & ZONE_AVAILABLE);
    493410       
    494         frame_t *frame = &zone->frames[frame_idx];
    495         size_t size = 0;
    496        
    497         ASSERT(frame->refcount);
     411        frame_t *frame = zone_get_frame(zone, index);
     412       
     413        ASSERT(frame->refcount > 0);
    498414       
    499415        if (!--frame->refcount) {
    500                 size = 1 << frame->buddy_order;
    501                 buddy_system_free(zone->buddy_system, &frame->buddy_link);             
     416                bitmap_set(&zone->bitmap, index, 0);
     417               
    502418                /* 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];
     419                zone->free_count++;
     420                zone->busy_count--;
     421               
     422                return 1;
     423        }
     424       
     425        return 0;
    515426}
    516427
    517428/** Mark frame in zone unavailable to allocation. */
    518 NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
     429NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
    519430{
    520431        ASSERT(zone->flags & ZONE_AVAILABLE);
    521432       
    522         frame_t *frame = zone_get_frame(zone, frame_idx);
    523         if (frame->refcount)
     433        frame_t *frame = zone_get_frame(zone, index);
     434        if (frame->refcount > 0)
    524435                return;
    525436       
    526         link_t *link __attribute__ ((unused));
    527        
    528         link = buddy_system_alloc_block(zone->buddy_system,
    529             &frame->buddy_link);
    530        
    531         ASSERT(link);
     437        frame->refcount = 1;
     438        bitmap_set_range(&zone->bitmap, index, 1);
     439       
    532440        zone->free_count--;
    533441        reserve_force_alloc(1);
     
    536444/** Merge two zones.
    537445 *
    538  * Expect buddy to point to space at least zone_conf_size large.
    539446 * Assume z1 & z2 are locked and compatible and zones lock is
    540447 * locked.
    541448 *
    542  * @param z1     First zone to merge.
    543  * @param z2     Second zone to merge.
    544  * @param old_z1 Original date of the first zone.
    545  * @param buddy  Merged zone buddy.
     449 * @param z1       First zone to merge.
     450 * @param z2       Second zone to merge.
     451 * @param old_z1   Original data of the first zone.
     452 * @param confdata Merged zone configuration data.
    546453 *
    547454 */
    548455NO_TRACE static void zone_merge_internal(size_t z1, size_t z2, zone_t *old_z1,
    549     buddy_system_t *buddy)
     456    void *confdata)
    550457{
    551458        ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
     
    562469        zones.info[z1].free_count += zones.info[z2].free_count;
    563470        zones.info[z1].busy_count += zones.info[z2].busy_count;
    564         zones.info[z1].buddy_system = buddy;
    565        
    566         uint8_t order = fnzb(zones.info[z1].count);
    567         buddy_system_create(zones.info[z1].buddy_system, order,
    568             &zone_buddy_system_operations, (void *) &zones.info[z1]);
    569        
    570         zones.info[z1].frames =
    571             (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
    572             + buddy_conf_size(order));
    573        
    574         /* This marks all frames busy */
    575         size_t i;
    576         for (i = 0; i < zones.info[z1].count; i++)
    577                 frame_initialize(&zones.info[z1].frames[i]);
    578        
    579         /* Copy frames from both zones to preserve full frame orders,
    580          * parents etc. Set all free frames with refcount = 0 to 1, because
    581          * we add all free frames to buddy allocator later again, clearing
    582          * order to 0. Don't set busy frames with refcount = 0, as they
    583          * will not be reallocated during merge and it would make later
    584          * problems with allocation/free.
     471       
     472        bitmap_initialize(&zones.info[z1].bitmap, zones.info[z1].count,
     473            confdata + (sizeof(frame_t) * zones.info[z1].count));
     474        bitmap_clear_range(&zones.info[z1].bitmap, 0, zones.info[z1].count);
     475       
     476        zones.info[z1].frames = (frame_t *) confdata;
     477       
     478        /*
     479         * Copy frames and bits from both zones to preserve parents, etc.
    585480         */
    586         for (i = 0; i < old_z1->count; i++)
     481       
     482        for (size_t i = 0; i < old_z1->count; i++) {
     483                bitmap_set(&zones.info[z1].bitmap, i,
     484                    bitmap_get(&old_z1->bitmap, i));
    587485                zones.info[z1].frames[i] = old_z1->frames[i];
    588        
    589         for (i = 0; i < zones.info[z2].count; i++)
    590                 zones.info[z1].frames[base_diff + i]
    591                     = zones.info[z2].frames[i];
    592        
    593         i = 0;
    594         while (i < zones.info[z1].count) {
    595                 if (zones.info[z1].frames[i].refcount) {
    596                         /* Skip busy frames */
    597                         i += 1 << zones.info[z1].frames[i].buddy_order;
    598                 } else {
    599                         /* Free frames, set refcount = 1
    600                          * (all free frames have refcount == 0, we need not
    601                          * to check the order)
    602                          */
    603                         zones.info[z1].frames[i].refcount = 1;
    604                         zones.info[z1].frames[i].buddy_order = 0;
    605                         i++;
    606                 }
    607         }
    608        
    609         /* Add free blocks from the original zone z1 */
    610         while (zone_can_alloc(old_z1, 0)) {
    611                 /* Allocate from the original zone */
    612                 pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
    613                
    614                 /* Free the frame from the merged zone */
    615                 frame_t *frame = &zones.info[z1].frames[frame_idx];
    616                 frame->refcount = 0;
    617                 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
    618         }
    619        
    620         /* Add free blocks from the original zone z2 */
    621         while (zone_can_alloc(&zones.info[z2], 0)) {
    622                 /* Allocate from the original zone */
    623                 pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
    624                
    625                 /* Free the frame from the merged zone */
    626                 frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
    627                 frame->refcount = 0;
    628                 buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
     486        }
     487       
     488        for (size_t i = 0; i < zones.info[z2].count; i++) {
     489                bitmap_set(&zones.info[z1].bitmap, base_diff + i,
     490                    bitmap_get(&zones.info[z2].bitmap, i));
     491                zones.info[z1].frames[base_diff + i] =
     492                    zones.info[z2].frames[i];
    629493        }
    630494}
     
    649513        size_t cframes = SIZE2FRAMES(zone_conf_size(count));
    650514       
    651         if ((pfn < zones.info[znum].base)
    652             || (pfn >= zones.info[znum].base + zones.info[znum].count))
     515        if ((pfn < zones.info[znum].base) ||
     516            (pfn >= zones.info[znum].base + zones.info[znum].count))
    653517                return;
    654518       
    655         frame_t *frame __attribute__ ((unused));
    656 
    657         frame = &zones.info[znum].frames[pfn - zones.info[znum].base];
    658         ASSERT(!frame->buddy_order);
    659        
    660         size_t i;
    661         for (i = 0; i < cframes; i++) {
    662                 zones.info[znum].busy_count++;
     519        for (size_t i = 0; i < cframes; i++)
    663520                (void) zone_frame_free(&zones.info[znum],
    664521                    pfn - zones.info[znum].base + i);
    665         }
    666 }
    667 
    668 /** Reduce allocated block to count of order 0 frames.
    669  *
    670  * The allocated block needs 2^order frames. Reduce all frames
    671  * in the block to order 0 and free the unneeded frames. This means that
    672  * when freeing the previously allocated block starting with frame_idx,
    673  * you have to free every frame.
    674  *
    675  * @param znum      Zone.
    676  * @param frame_idx Index the first frame of the block.
    677  * @param count     Allocated frames in block.
    678  *
    679  */
    680 NO_TRACE static void zone_reduce_region(size_t znum, pfn_t frame_idx,
    681     size_t count)
    682 {
    683         ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
    684         ASSERT(frame_idx + count < zones.info[znum].count);
    685        
    686         uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
    687         ASSERT((size_t) (1 << order) >= count);
    688        
    689         /* Reduce all blocks to order 0 */
    690         size_t i;
    691         for (i = 0; i < (size_t) (1 << order); i++) {
    692                 frame_t *frame = &zones.info[znum].frames[i + frame_idx];
    693                 frame->buddy_order = 0;
    694                 if (!frame->refcount)
    695                         frame->refcount = 1;
    696                 ASSERT(frame->refcount == 1);
    697         }
    698        
    699         /* Free unneeded frames */
    700         for (i = count; i < (size_t) (1 << order); i++)
    701                 (void) zone_frame_free(&zones.info[znum], i + frame_idx);
    702522}
    703523
     
    719539        bool ret = true;
    720540       
    721         /* We can join only 2 zones with none existing inbetween,
     541        /*
     542         * We can join only 2 zones with none existing inbetween,
    722543         * the zones have to be available and with the same
    723544         * set of flags
     
    733554            + zones.info[z2].count));
    734555       
    735         uint8_t order;
    736         if (cframes == 1)
    737                 order = 0;
    738         else
    739                 order = fnzb(cframes - 1) + 1;
    740        
    741556        /* Allocate merged zone data inside one of the zones */
    742557        pfn_t pfn;
    743         if (zone_can_alloc(&zones.info[z1], order)) {
    744                 pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
    745         } else if (zone_can_alloc(&zones.info[z2], order)) {
    746                 pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
     558        if (zone_can_alloc(&zones.info[z1], cframes, 0)) {
     559                pfn = zones.info[z1].base +
     560                    zone_frame_alloc(&zones.info[z1], cframes, 0);
     561        } else if (zone_can_alloc(&zones.info[z2], cframes, 0)) {
     562                pfn = zones.info[z2].base +
     563                    zone_frame_alloc(&zones.info[z2], cframes, 0);
    747564        } else {
    748565                ret = false;
     
    752569        /* Preserve original data from z1 */
    753570        zone_t old_z1 = zones.info[z1];
    754         old_z1.buddy_system->data = (void *) &old_z1;
    755571       
    756572        /* Do zone merging */
    757         buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
    758         zone_merge_internal(z1, z2, &old_z1, buddy);
    759        
    760         /* Free unneeded config frames */
    761         zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
     573        zone_merge_internal(z1, z2, &old_z1, (void *) PA2KA(PFN2ADDR(pfn)));
    762574       
    763575        /* Subtract zone information from busy frames */
     
    772584       
    773585        /* Move zones down */
    774         size_t i;
    775         for (i = z2 + 1; i < zones.count; i++) {
     586        for (size_t i = z2 + 1; i < zones.count; i++)
    776587                zones.info[i - 1] = zones.info[i];
    777                 if (zones.info[i - 1].buddy_system != NULL)
    778                         zones.info[i - 1].buddy_system->data =
    779                             (void *) &zones.info[i - 1];
    780         }
    781588       
    782589        zones.count--;
     
    797604void zone_merge_all(void)
    798605{
    799         size_t i = 0;
     606        size_t i = 1;
     607       
    800608        while (i < zones.count) {
    801                 if (!zone_merge(i, i + 1))
     609                if (!zone_merge(i - 1, i))
    802610                        i++;
    803611        }
     
    806614/** Create new frame zone.
    807615 *
    808  * @param zone  Zone to construct.
    809  * @param buddy Address of buddy system configuration information.
    810  * @param start Physical address of the first frame within the zone.
    811  * @param count Count of frames in zone.
    812  * @param flags Zone flags.
     616 * @param zone     Zone to construct.
     617 * @param start    Physical address of the first frame within the zone.
     618 * @param count    Count of frames in zone.
     619 * @param flags    Zone flags.
     620 * @param confdata Configuration data of the zone.
    813621 *
    814622 * @return Initialized zone.
    815623 *
    816624 */
    817 NO_TRACE static void zone_construct(zone_t *zone, buddy_system_t *buddy,
    818     pfn_t start, size_t count, zone_flags_t flags)
     625NO_TRACE static void zone_construct(zone_t *zone, pfn_t start, size_t count,
     626    zone_flags_t flags, void *confdata)
    819627{
    820628        zone->base = start;
     
    823631        zone->free_count = count;
    824632        zone->busy_count = 0;
    825         zone->buddy_system = buddy;
    826633       
    827634        if (flags & ZONE_AVAILABLE) {
    828635                /*
    829                  * Compute order for buddy system and initialize
     636                 * Initialize frame bitmap (located after the array of
     637                 * frame_t structures in the configuration space).
    830638                 */
    831                 uint8_t order = fnzb(count);
    832                 buddy_system_create(zone->buddy_system, order,
    833                     &zone_buddy_system_operations, (void *) zone);
    834                
    835                 /* Allocate frames _after_ the confframe */
    836                
    837                 /* Check sizes */
    838                 zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
    839                     buddy_conf_size(order));
    840                
    841                 size_t i;
    842                 for (i = 0; i < count; i++)
     639               
     640                bitmap_initialize(&zone->bitmap, count, confdata +
     641                    (sizeof(frame_t) * count));
     642                bitmap_clear_range(&zone->bitmap, 0, count);
     643               
     644                /*
     645                 * Initialize the array of frame_t structures.
     646                 */
     647               
     648                zone->frames = (frame_t *) confdata;
     649               
     650                for (size_t i = 0; i < count; i++)
    843651                        frame_initialize(&zone->frames[i]);
    844                
    845                 /* Stuffing frames */
    846                 for (i = 0; i < count; i++) {
    847                         zone->frames[i].refcount = 0;
    848                         buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
    849                 }
    850         } else
     652        } else {
     653                bitmap_initialize(&zone->bitmap, 0, NULL);
    851654                zone->frames = NULL;
     655        }
    852656}
    853657
     
    861665size_t zone_conf_size(size_t count)
    862666{
    863         return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
     667        return (count * sizeof(frame_t) + bitmap_size(count));
    864668}
    865669
     
    867671pfn_t zone_external_conf_alloc(size_t count)
    868672{
    869         size_t size = zone_conf_size(count);
    870         size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
    871 
    872         return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH,
    873             FRAME_LOWMEM | FRAME_ATOMIC));
     673        size_t frames = SIZE2FRAMES(zone_conf_size(count));
     674       
     675        return ADDR2PFN((uintptr_t)
     676            frame_alloc(frames, FRAME_LOWMEM | FRAME_ATOMIC, 0));
    874677}
    875678
     
    879682 * @param count     Size of zone in frames.
    880683 * @param confframe Where configuration frames are supposed to be.
    881  *                  Automatically checks, that we will not disturb the
     684 *                  Automatically checks that we will not disturb the
    882685 *                  kernel and possibly init. If confframe is given
    883686 *                  _outside_ this zone, it is expected, that the area is
     
    896699       
    897700        if (flags & ZONE_AVAILABLE) {  /* Create available zone */
    898                 /* Theoretically we could have NULL here, practically make sure
     701                /*
     702                 * Theoretically we could have NULL here, practically make sure
    899703                 * nobody tries to do that. If some platform requires, remove
    900704                 * the assert
    901705                 */
    902706                ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
    903 
     707               
    904708                /* Update the known end of physical memory. */
    905709                config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
    906710               
    907                 /* If confframe is supposed to be inside our zone, then make sure
     711                /*
     712                 * If confframe is supposed to be inside our zone, then make sure
    908713                 * it does not span kernel & init
    909714                 */
    910715                size_t confcount = SIZE2FRAMES(zone_conf_size(count));
     716               
    911717                if ((confframe >= start) && (confframe < start + count)) {
    912718                        for (; confframe < start + count; confframe++) {
     
    921727                               
    922728                                bool overlap = false;
    923                                 size_t i;
    924                                 for (i = 0; i < init.cnt; i++)
     729                                for (size_t i = 0; i < init.cnt; i++) {
    925730                                        if (overlaps(addr, PFN2ADDR(confcount),
    926731                                            init.tasks[i].paddr,
     
    929734                                                break;
    930735                                        }
     736                                }
     737                               
    931738                                if (overlap)
    932739                                        continue;
     
    945752                }
    946753               
    947                 buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
    948                 zone_construct(&zones.info[znum], buddy, start, count, flags);
     754                void *confdata = (void *) PA2KA(PFN2ADDR(confframe));
     755                zone_construct(&zones.info[znum], start, count, flags, confdata);
    949756               
    950757                /* If confdata in zone, mark as unavailable */
    951758                if ((confframe >= start) && (confframe < start + count)) {
    952                         size_t i;
    953                         for (i = confframe; i < confframe + confcount; i++)
     759                        for (size_t i = confframe; i < confframe + confcount; i++)
    954760                                zone_mark_unavailable(&zones.info[znum],
    955761                                    i - zones.info[znum].base);
     
    967773                return (size_t) -1;
    968774        }
    969         zone_construct(&zones.info[znum], NULL, start, count, flags);
     775       
     776        zone_construct(&zones.info[znum], start, count, flags, NULL);
    970777       
    971778        irq_spinlock_unlock(&zones.lock, true);
     
    1009816}
    1010817
    1011 /** Allocate power-of-two frames of physical memory.
    1012  *
    1013  * @param order Allocate exactly 2^order frames.
    1014  * @param flags Flags for host zone selection and address processing.
    1015  * @param pzone Preferred zone.
     818/** Allocate frames of physical memory.
     819 *
     820 * @param count      Number of continuous frames to allocate.
     821 * @param flags      Flags for host zone selection and address processing.
     822 * @param constraint Indication of physical address bits that cannot be
     823 *                   set in the address of the first allocated frame.
     824 * @param pzone      Preferred zone.
    1016825 *
    1017826 * @return Physical address of the allocated frame.
    1018827 *
    1019828 */
    1020 void *frame_alloc_generic(uint8_t order, frame_flags_t flags, size_t *pzone)
    1021 {
    1022         size_t size = ((size_t) 1) << order;
     829uintptr_t frame_alloc_generic(size_t count, frame_flags_t flags,
     830    uintptr_t constraint, size_t *pzone)
     831{
     832        ASSERT(count > 0);
     833       
    1023834        size_t hint = pzone ? (*pzone) : 0;
     835        pfn_t frame_constraint = ADDR2PFN(constraint);
    1024836       
    1025837        /*
    1026838         * If not told otherwise, we must first reserve the memory.
    1027839         */
    1028         if (!(flags & FRAME_NO_RESERVE)) 
    1029                 reserve_force_alloc(size);
    1030 
     840        if (!(flags & FRAME_NO_RESERVE))
     841                reserve_force_alloc(count);
     842       
    1031843loop:
    1032844        irq_spinlock_lock(&zones.lock, true);
     
    1035847         * First, find suitable frame zone.
    1036848         */
    1037         size_t znum = find_free_zone(order,
    1038             FRAME_TO_ZONE_FLAGS(flags), hint);
    1039        
    1040         /* If no memory, reclaim some slab memory,
    1041            if it does not help, reclaim all */
     849        size_t znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     850            frame_constraint, hint);
     851       
     852        /*
     853         * If no memory, reclaim some slab memory,
     854         * if it does not help, reclaim all.
     855         */
    1042856        if ((znum == (size_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
    1043857                irq_spinlock_unlock(&zones.lock, true);
     
    1046860               
    1047861                if (freed > 0)
    1048                         znum = find_free_zone(order,
    1049                             FRAME_TO_ZONE_FLAGS(flags), hint);
     862                        znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     863                            frame_constraint, hint);
    1050864               
    1051865                if (znum == (size_t) -1) {
     
    1055869                       
    1056870                        if (freed > 0)
    1057                                 znum = find_free_zone(order,
    1058                                     FRAME_TO_ZONE_FLAGS(flags), hint);
     871                                znum = find_free_zone(count, FRAME_TO_ZONE_FLAGS(flags),
     872                                    frame_constraint, hint);
    1059873                }
    1060874        }
     
    1063877                if (flags & FRAME_ATOMIC) {
    1064878                        irq_spinlock_unlock(&zones.lock, true);
     879                       
    1065880                        if (!(flags & FRAME_NO_RESERVE))
    1066                                 reserve_free(size);
    1067                         return NULL;
     881                                reserve_free(count);
     882                       
     883                        return 0;
    1068884                }
    1069885               
    1070 #ifdef CONFIG_DEBUG
    1071886                size_t avail = frame_total_free_get_internal();
    1072 #endif
    1073887               
    1074888                irq_spinlock_unlock(&zones.lock, true);
    1075889               
    1076890                if (!THREAD)
    1077                         panic("Cannot wait for memory to become available.");
     891                        panic("Cannot wait for %zu frames to become available "
     892                            "(%zu available).", count, avail);
    1078893               
    1079894                /*
     
    1082897               
    1083898#ifdef CONFIG_DEBUG
    1084                 printf("Thread %" PRIu64 " waiting for %zu frames, "
    1085                     "%zu available.\n", THREAD->tid, size, avail);
     899                log(LF_OTHER, LVL_DEBUG,
     900                    "Thread %" PRIu64 " waiting for %zu frames "
     901                    "%zu available.", THREAD->tid, count, avail);
    1086902#endif
    1087903               
    1088904                /*
    1089                  * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
    1090                  * to prevent deadlock with TLB shootdown.
     905                 * Since the mem_avail_mtx is an active mutex, we need to
     906                 * disable interrupts to prevent deadlock with TLB shootdown.
    1091907                 */
    1092908                ipl_t ipl = interrupts_disable();
     
    1094910               
    1095911                if (mem_avail_req > 0)
    1096                         mem_avail_req = min(mem_avail_req, size);
     912                        mem_avail_req = min(mem_avail_req, count);
    1097913                else
    1098                         mem_avail_req = size;
     914                        mem_avail_req = count;
     915               
    1099916                size_t gen = mem_avail_gen;
    1100917               
     
    1106923               
    1107924#ifdef CONFIG_DEBUG
    1108                 printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
     925                log(LF_OTHER, LVL_DEBUG, "Thread %" PRIu64 " woken up.",
     926                    THREAD->tid);
    1109927#endif
    1110928               
     
    1112930        }
    1113931       
    1114         pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
    1115             + zones.info[znum].base;
     932        pfn_t pfn = zone_frame_alloc(&zones.info[znum], count,
     933            frame_constraint) + zones.info[znum].base;
    1116934       
    1117935        irq_spinlock_unlock(&zones.lock, true);
     
    1120938                *pzone = znum;
    1121939       
    1122         if (flags & FRAME_KA)
    1123                 return (void *) PA2KA(PFN2ADDR(pfn));
    1124        
    1125         return (void *) PFN2ADDR(pfn);
    1126 }
    1127 
    1128 void *frame_alloc(uint8_t order, frame_flags_t flags)
    1129 {
    1130         return frame_alloc_generic(order, flags, NULL);
    1131 }
    1132 
    1133 void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
    1134 {
    1135         return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
    1136 }
    1137 
    1138 /** Free a frame.
    1139  *
    1140  * Find respective frame structure for supplied physical frame address.
    1141  * Decrement frame reference count. If it drops to zero, move the frame
    1142  * structure to free list.
    1143  *
    1144  * @param frame Physical Address of of the frame to be freed.
     940        return PFN2ADDR(pfn);
     941}
     942
     943uintptr_t frame_alloc(size_t count, frame_flags_t flags, uintptr_t constraint)
     944{
     945        return frame_alloc_generic(count, flags, constraint, NULL);
     946}
     947
     948/** Free frames of physical memory.
     949 *
     950 * Find respective frame structures for supplied physical frames.
     951 * Decrement each frame reference count. If it drops to zero, mark
     952 * the frames as available.
     953 *
     954 * @param start Physical Address of the first frame to be freed.
     955 * @param count Number of frames to free.
    1145956 * @param flags Flags to control memory reservation.
    1146957 *
    1147958 */
    1148 void frame_free_generic(uintptr_t frame, frame_flags_t flags)
    1149 {
    1150         size_t size;
     959void frame_free_generic(uintptr_t start, size_t count, frame_flags_t flags)
     960{
     961        size_t freed = 0;
    1151962       
    1152963        irq_spinlock_lock(&zones.lock, true);
    1153964       
    1154         /*
    1155          * First, find host frame zone for addr.
    1156          */
    1157         pfn_t pfn = ADDR2PFN(frame);
    1158         size_t znum = find_zone(pfn, 1, 0);
    1159 
    1160         ASSERT(znum != (size_t) -1);
    1161        
    1162         size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     965        for (size_t i = 0; i < count; i++) {
     966                /*
     967                 * First, find host frame zone for addr.
     968                 */
     969                pfn_t pfn = ADDR2PFN(start) + i;
     970                size_t znum = find_zone(pfn, 1, 0);
     971               
     972                ASSERT(znum != (size_t) -1);
     973               
     974                freed += zone_frame_free(&zones.info[znum],
     975                    pfn - zones.info[znum].base);
     976        }
    1163977       
    1164978        irq_spinlock_unlock(&zones.lock, true);
     
    1166980        /*
    1167981         * Signal that some memory has been freed.
     982         * Since the mem_avail_mtx is an active mutex,
     983         * we need to disable interruptsto prevent deadlock
     984         * with TLB shootdown.
    1168985         */
    1169 
    1170        
    1171         /*
    1172          * Since the mem_avail_mtx is an active mutex, we need to disable interrupts
    1173          * to prevent deadlock with TLB shootdown.
    1174          */
     986       
    1175987        ipl_t ipl = interrupts_disable();
    1176988        mutex_lock(&mem_avail_mtx);
     989       
    1177990        if (mem_avail_req > 0)
    1178                 mem_avail_req -= min(mem_avail_req, size);
     991                mem_avail_req -= min(mem_avail_req, freed);
    1179992       
    1180993        if (mem_avail_req == 0) {
     
    1182995                condvar_broadcast(&mem_avail_cv);
    1183996        }
     997       
    1184998        mutex_unlock(&mem_avail_mtx);
    1185999        interrupts_restore(ipl);
    11861000       
    11871001        if (!(flags & FRAME_NO_RESERVE))
    1188                 reserve_free(size);
    1189 }
    1190 
    1191 void frame_free(uintptr_t frame)
    1192 {
    1193         frame_free_generic(frame, 0);
    1194 }
    1195 
    1196 void frame_free_noreserve(uintptr_t frame)
    1197 {
    1198         frame_free_generic(frame, FRAME_NO_RESERVE);
     1002                reserve_free(freed);
     1003}
     1004
     1005void frame_free(uintptr_t frame, size_t count)
     1006{
     1007        frame_free_generic(frame, count, 0);
     1008}
     1009
     1010void frame_free_noreserve(uintptr_t frame, size_t count)
     1011{
     1012        frame_free_generic(frame, count, FRAME_NO_RESERVE);
    11991013}
    12001014
     
    12301044        irq_spinlock_lock(&zones.lock, true);
    12311045       
    1232         size_t i;
    1233         for (i = 0; i < count; i++) {
     1046        for (size_t i = 0; i < count; i++) {
    12341047                size_t znum = find_zone(start + i, 1, 0);
     1048               
    12351049                if (znum == (size_t) -1)  /* PFN not found */
    12361050                        continue;
     
    12571071        /* Tell the architecture to create some memory */
    12581072        frame_low_arch_init();
     1073       
    12591074        if (config.cpu_active == 1) {
    12601075                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
     
    12631078                    SIZE2FRAMES(config.stack_size));
    12641079               
    1265                 size_t i;
    1266                 for (i = 0; i < init.cnt; i++) {
    1267                         pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
    1268                         frame_mark_unavailable(pfn,
     1080                for (size_t i = 0; i < init.cnt; i++)
     1081                        frame_mark_unavailable(ADDR2PFN(init.tasks[i].paddr),
    12691082                            SIZE2FRAMES(init.tasks[i].size));
    1270                 }
    12711083               
    12721084                if (ballocs.size)
     
    12741086                            SIZE2FRAMES(ballocs.size));
    12751087               
    1276                 /* Black list first frame, as allocating NULL would
     1088                /*
     1089                 * Blacklist first frame, as allocating NULL would
    12771090                 * fail in some places
    12781091                 */
    12791092                frame_mark_unavailable(0, 1);
    12801093        }
     1094       
    12811095        frame_high_arch_init();
    12821096}
     
    12841098/** Adjust bounds of physical memory region according to low/high memory split.
    12851099 *
    1286  * @param low[in]       If true, the adjustment is performed to make the region
    1287  *                      fit in the low memory. Otherwise the adjustment is
    1288  *                      performed to make the region fit in the high memory.
    1289  * @param basep[inout]  Pointer to a variable which contains the region's base
    1290  *                      address and which may receive the adjusted base address.
    1291  * @param sizep[inout]  Pointer to a variable which contains the region's size
    1292  *                      and which may receive the adjusted size.
    1293  * @retun               True if the region still exists even after the
    1294  *                      adjustment, false otherwise.
     1100 * @param low[in]      If true, the adjustment is performed to make the region
     1101 *                     fit in the low memory. Otherwise the adjustment is
     1102 *                     performed to make the region fit in the high memory.
     1103 * @param basep[inout] Pointer to a variable which contains the region's base
     1104 *                     address and which may receive the adjusted base address.
     1105 * @param sizep[inout] Pointer to a variable which contains the region's size
     1106 *                     and which may receive the adjusted size.
     1107 *
     1108 * @return True if the region still exists even after the adjustment.
     1109 * @return False otherwise.
     1110 *
    12951111 */
    12961112bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
    12971113{
    12981114        uintptr_t limit = KA2PA(config.identity_base) + config.identity_size;
    1299 
     1115       
    13001116        if (low) {
    13011117                if (*basep > limit)
    13021118                        return false;
     1119               
    13031120                if (*basep + *sizep > limit)
    13041121                        *sizep = limit - *basep;
     
    13061123                if (*basep + *sizep <= limit)
    13071124                        return false;
     1125               
    13081126                if (*basep <= limit) {
    13091127                        *sizep -= limit - *basep;
     
    13111129                }
    13121130        }
     1131       
    13131132        return true;
    13141133}
     
    13221141       
    13231142        uint64_t total = 0;
    1324         size_t i;
    1325         for (i = 0; i < zones.count; i++)
     1143       
     1144        for (size_t i = 0; i < zones.count; i++)
    13261145                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13271146       
     
    13461165        *free = 0;
    13471166       
    1348         size_t i;
    1349         for (i = 0; i < zones.count; i++) {
     1167        for (size_t i = 0; i < zones.count; i++) {
    13501168                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    13511169               
     
    13751193        /*
    13761194         * Because printing may require allocation of memory, we may not hold
    1377          * the frame allocator locks when printing zone statistics.  Therefore,
     1195         * the frame allocator locks when printing zone statistics. Therefore,
    13781196         * we simply gather the statistics under the protection of the locks and
    13791197         * print the statistics when the locks have been released.
     
    13841202         */
    13851203       
    1386         size_t i;
    1387         for (i = 0;; i++) {
     1204        size_t free_lowmem = 0;
     1205        size_t free_highmem = 0;
     1206        size_t free_highprio = 0;
     1207       
     1208        for (size_t i = 0;; i++) {
    13881209                irq_spinlock_lock(&zones.lock, true);
    13891210               
     
    13931214                }
    13941215               
    1395                 uintptr_t base = PFN2ADDR(zones.info[i].base);
     1216                pfn_t fbase = zones.info[i].base;
     1217                uintptr_t base = PFN2ADDR(fbase);
    13961218                size_t count = zones.info[i].count;
    13971219                zone_flags_t flags = zones.info[i].flags;
     
    13991221                size_t busy_count = zones.info[i].busy_count;
    14001222               
     1223                bool available = ((flags & ZONE_AVAILABLE) != 0);
     1224                bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1225                bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1226                bool highprio = is_high_priority(fbase, count);
     1227               
     1228                if (available) {
     1229                        if (lowmem)
     1230                                free_lowmem += free_count;
     1231                       
     1232                        if (highmem)
     1233                                free_highmem += free_count;
     1234                       
     1235                        if (highprio) {
     1236                                free_highprio += free_count;
     1237                        } else {
     1238                                /*
     1239                                 * Walk all frames of the zone and examine
     1240                                 * all high priority memory to get accurate
     1241                                 * statistics.
     1242                                 */
     1243                               
     1244                                for (size_t index = 0; index < count; index++) {
     1245                                        if (is_high_priority(fbase + index, 0)) {
     1246                                                if (!bitmap_get(&zones.info[i].bitmap, index))
     1247                                                        free_highprio++;
     1248                                        } else
     1249                                                break;
     1250                                }
     1251                        }
     1252                }
     1253               
    14011254                irq_spinlock_unlock(&zones.lock, true);
    1402                
    1403                 bool available = ((flags & ZONE_AVAILABLE) != 0);
    14041255               
    14051256                printf("%-4zu", i);
     
    14261277                printf("\n");
    14271278        }
     1279       
     1280        printf("\n");
     1281       
     1282        uint64_t size;
     1283        const char *size_suffix;
     1284       
     1285        bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1286            false);
     1287        printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1288            free_lowmem, size, size_suffix);
     1289       
     1290        bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1291            false);
     1292        printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1293            free_highmem, size, size_suffix);
     1294       
     1295        bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1296            false);
     1297        printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1298            free_highprio, size, size_suffix);
    14281299}
    14291300
     
    14381309        size_t znum = (size_t) -1;
    14391310       
    1440         size_t i;
    1441         for (i = 0; i < zones.count; i++) {
     1311        for (size_t i = 0; i < zones.count; i++) {
    14421312                if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
    14431313                        znum = i;
     
    14521322        }
    14531323       
    1454         uintptr_t base = PFN2ADDR(zones.info[i].base);
    1455         zone_flags_t flags = zones.info[i].flags;
    1456         size_t count = zones.info[i].count;
    1457         size_t free_count = zones.info[i].free_count;
    1458         size_t busy_count = zones.info[i].busy_count;
     1324        size_t free_lowmem = 0;
     1325        size_t free_highmem = 0;
     1326        size_t free_highprio = 0;
     1327       
     1328        pfn_t fbase = zones.info[znum].base;
     1329        uintptr_t base = PFN2ADDR(fbase);
     1330        zone_flags_t flags = zones.info[znum].flags;
     1331        size_t count = zones.info[znum].count;
     1332        size_t free_count = zones.info[znum].free_count;
     1333        size_t busy_count = zones.info[znum].busy_count;
     1334       
     1335        bool available = ((flags & ZONE_AVAILABLE) != 0);
     1336        bool lowmem = ((flags & ZONE_LOWMEM) != 0);
     1337        bool highmem = ((flags & ZONE_HIGHMEM) != 0);
     1338        bool highprio = is_high_priority(fbase, count);
     1339       
     1340        if (available) {
     1341                if (lowmem)
     1342                        free_lowmem = free_count;
     1343               
     1344                if (highmem)
     1345                        free_highmem = free_count;
     1346               
     1347                if (highprio) {
     1348                        free_highprio = free_count;
     1349                } else {
     1350                        /*
     1351                         * Walk all frames of the zone and examine
     1352                         * all high priority memory to get accurate
     1353                         * statistics.
     1354                         */
     1355                       
     1356                        for (size_t index = 0; index < count; index++) {
     1357                                if (is_high_priority(fbase + index, 0)) {
     1358                                        if (!bitmap_get(&zones.info[znum].bitmap, index))
     1359                                                free_highprio++;
     1360                                } else
     1361                                        break;
     1362                        }
     1363                }
     1364        }
    14591365       
    14601366        irq_spinlock_unlock(&zones.lock, true);
    1461        
    1462         bool available = ((flags & ZONE_AVAILABLE) != 0);
    14631367       
    14641368        uint64_t size;
    14651369        const char *size_suffix;
     1370       
    14661371        bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
    14671372       
    1468         printf("Zone number:       %zu\n", znum);
    1469         printf("Zone base address: %p\n", (void *) base);
    1470         printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
     1373        printf("Zone number:             %zu\n", znum);
     1374        printf("Zone base address:       %p\n", (void *) base);
     1375        printf("Zone size:               %zu frames (%" PRIu64 " %s)\n", count,
    14711376            size, size_suffix);
    1472         printf("Zone flags:        %c%c%c%c%c\n",
     1377        printf("Zone flags:              %c%c%c%c%c\n",
    14731378            available ? 'A' : '-',
    14741379            (flags & ZONE_RESERVED) ? 'R' : '-',
     
    14801385                bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
    14811386                    false);
    1482                 printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
     1387                printf("Allocated space:         %zu frames (%" PRIu64 " %s)\n",
    14831388                    busy_count, size, size_suffix);
     1389               
    14841390                bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
    14851391                    false);
    1486                 printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
     1392                printf("Available space:         %zu frames (%" PRIu64 " %s)\n",
    14871393                    free_count, size, size_suffix);
     1394               
     1395                bin_order_suffix(FRAMES2SIZE(free_lowmem), &size, &size_suffix,
     1396                    false);
     1397                printf("Available low memory:    %zu frames (%" PRIu64 " %s)\n",
     1398                    free_lowmem, size, size_suffix);
     1399               
     1400                bin_order_suffix(FRAMES2SIZE(free_highmem), &size, &size_suffix,
     1401                    false);
     1402                printf("Available high memory:   %zu frames (%" PRIu64 " %s)\n",
     1403                    free_highmem, size, size_suffix);
     1404               
     1405                bin_order_suffix(FRAMES2SIZE(free_highprio), &size, &size_suffix,
     1406                    false);
     1407                printf("Available high priority: %zu frames (%" PRIu64 " %s)\n",
     1408                    free_highprio, size, size_suffix);
    14881409        }
    14891410}
Note: See TracChangeset for help on using the changeset viewer.