Changeset 5f0f29ce in mainline


Ignore:
Timestamp:
2009-02-26T23:34:27Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e49e234
Parents:
6b1de7a
Message:

kernel memory management revisited (phase 1): proper support for zone flags

  • the zone_t structures are now statically allocated to be easily available
  • the locking scheme was simplified
  • new flags for non-available zones were introduced
  • FRAME_LOW_4_GiB flag is removed, the functionality will be eventually reimplemented using a generic mechanism
Location:
kernel
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/mm/frame.c

    r6b1de7a r5f0f29ce  
    5858        pfn_t start, conf;
    5959        size_t size;
    60 
     60       
    6161        for (i = 0; i < e820counter; i++) {
    6262                if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
  • kernel/arch/ia32/src/smp/smp.c

    r6b1de7a r5f0f29ce  
    155155                 * Prepare new GDT for CPU in question.
    156156                 */
     157               
     158                /* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
     159                 * it needs to be replaced by a generic fuctionality of
     160                 * the memory subsystem
     161                 */
    157162                gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
    158                     sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);
     163                    sizeof(struct descriptor), FRAME_ATOMIC);
    159164                if (!gdt_new)
    160165                        panic("Cannot allocate memory for GDT.");
  • kernel/generic/include/mm/buddy.h

    r6b1de7a r5f0f29ce  
    8383extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t);
    8484extern void buddy_system_free(buddy_system_t *, link_t *);
    85 extern size_t buddy_conf_size(int);
     85extern size_t buddy_conf_size(size_t);
    8686extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
    8787
  • kernel/generic/include/mm/frame.h

    r6b1de7a r5f0f29ce  
    3939#include <arch/types.h>
    4040#include <adt/list.h>
    41 #include <synch/spinlock.h>
    4241#include <mm/buddy.h>
    4342#include <arch/mm/page.h>
    4443#include <arch/mm/frame.h>
    4544
    46 #define ONE_FRAME       0
    47 #define TWO_FRAMES      1
    48 #define FOUR_FRAMES     2
     45#define ONE_FRAME    0
     46#define TWO_FRAMES   1
     47#define FOUR_FRAMES  2
    4948
    5049
    5150#ifdef ARCH_STACK_FRAMES
    52 #define STACK_FRAMES ARCH_STACK_FRAMES
     51        #define STACK_FRAMES ARCH_STACK_FRAMES
    5352#else
    54 #define STACK_FRAMES ONE_FRAME
     53        #define STACK_FRAMES ONE_FRAME
    5554#endif
    5655
    57 /** Maximum number of zones in system. */
    58 #define ZONES_MAX               16
     56/** Maximum number of zones in the system. */
     57#define ZONES_MAX  32
    5958
    60 /** Convert the frame address to kernel va. */
    61 #define FRAME_KA                0x1
     59typedef uint8_t frame_flags_t;
     60
     61/** Convert the frame address to kernel VA. */
     62#define FRAME_KA          0x01
    6263/** Do not panic and do not sleep on failure. */
    63 #define FRAME_ATOMIC            0x2
     64#define FRAME_ATOMIC      0x02
    6465/** Do not start reclaiming when no free memory. */
    65 #define FRAME_NO_RECLAIM        0x4
    66 /** Do not allocate above 4 GiB. */
    67 #define FRAME_LOW_4_GiB         0x8
     66#define FRAME_NO_RECLAIM  0x04
     67
     68typedef uint8_t zone_flags_t;
     69
     70/** Zone is reserved (not available for allocation) */
     71#define ZONE_RESERVED  0x08
     72/** Zone is used by firmware (not available for allocation) */
     73#define ZONE_FIRMWARE  0x10
     74
     75/** Currently there is no equivalent zone flags
     76    for frame flags */
     77#define FRAME_TO_ZONE_FLAGS(frame_flags)  0
    6878
    6979static inline uintptr_t PFN2ADDR(pfn_t frame)
     
    8999}
    90100
    91 #define IS_BUDDY_ORDER_OK(index, order)         \
     101#define IS_BUDDY_ORDER_OK(index, order) \
    92102    ((~(((unative_t) -1) << (order)) & (index)) == 0)
    93 #define IS_BUDDY_LEFT_BLOCK(zone, frame)        \
    94     (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
    95 #define IS_BUDDY_RIGHT_BLOCK(zone, frame)       \
    96     (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
    97 #define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame)    \
    98     (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
    99 #define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame)   \
    100     (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
     103#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
     104    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
     105#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
     106    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
     107#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
     108    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
     109#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
     110    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
    101111
    102 #define frame_alloc(order, flags)               \
     112#define frame_alloc(order, flags) \
    103113    frame_alloc_generic(order, flags, NULL)
    104114
    105115extern void frame_init(void);
    106 extern void *frame_alloc_generic(uint8_t, int, unsigned int *);
     116extern void *frame_alloc_generic(uint8_t, frame_flags_t, count_t *);
    107117extern void frame_free(uintptr_t);
    108118extern void frame_reference_add(pfn_t);
    109119
    110 extern int zone_create(pfn_t, count_t, pfn_t, int);
    111 extern void *frame_get_parent(pfn_t, unsigned int);
    112 extern void frame_set_parent(pfn_t, void *, unsigned int);
     120extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
     121extern void *frame_get_parent(pfn_t, count_t);
     122extern void frame_set_parent(pfn_t, void *, count_t);
    113123extern void frame_mark_unavailable(pfn_t, count_t);
    114124extern uintptr_t zone_conf_size(count_t);
    115 extern void zone_merge(unsigned int, unsigned int);
     125extern bool zone_merge(count_t, count_t);
    116126extern void zone_merge_all(void);
    117127extern uint64_t zone_total_size(void);
     
    121131 */
    122132extern void zone_print_list(void);
    123 extern void zone_print_one(unsigned int);
     133extern void zone_print_one(count_t);
    124134
    125135#endif
  • kernel/generic/include/mm/slab.h

    r6b1de7a r5f0f29ce  
    6060
    6161/** Reclaim all possible memory, because we are in memory stress */
    62 #define SLAB_RECLAIM_ALL  0x1
     62#define SLAB_RECLAIM_ALL  0x01
    6363
    6464/* cache_create flags */
  • kernel/generic/src/mm/buddy.c

    r6b1de7a r5f0f29ce  
    4747
    4848/** Return size needed for the buddy configuration data. */
    49 size_t buddy_conf_size(int max_order)
     49size_t buddy_conf_size(size_t max_order)
    5050{
    5151        return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
  • kernel/generic/src/mm/frame.c

    r6b1de7a r5f0f29ce  
    22 * Copyright (c) 2001-2005 Jakub Jermar
    33 * Copyright (c) 2005 Sergey Bondari
     4 * Copyright (c) 2009 Martin Decky
    45 * All rights reserved.
    56 *
     
    3435/**
    3536 * @file
    36  * @brief       Physical frame allocator.
     37 * @brief Physical frame allocator.
    3738 *
    3839 * This file contains the physical frame allocator and memory zone management.
     
    4041 *
    4142 * @see buddy.c
    42  */
    43 
    44 /*
    45  * Locking order
    46  *
    47  * In order to access particular zone, the process must first lock
    48  * the zones.lock, then lock the zone and then unlock the zones.lock.
    49  * This insures, that we can fiddle with the zones in runtime without
    50  * affecting the processes.
    51  *
    5243 */
    5344
     
    7162
    7263typedef struct {
    73         count_t refcount;       /**< tracking of shared frames */
    74         uint8_t buddy_order;    /**< buddy system block order */
    75         link_t buddy_link;      /**< link to the next free block inside one
    76                                     order */
    77         void *parent;           /**< If allocated by slab, this points there */
     64        count_t refcount;     /**< Tracking of shared frames */
     65        uint8_t buddy_order;  /**< Buddy system block order */
     66        link_t buddy_link;    /**< Link to the next free block inside
     67                               one order */
     68        void *parent;         /**< If allocated by slab, this points there */
    7869} frame_t;
    7970
    8071typedef struct {
    81         SPINLOCK_DECLARE(lock); /**< this lock protects everything below */
    82         pfn_t base;             /**< frame_no of the first frame in the frames
    83                                      array */
    84         count_t count;          /**< Size of zone */
    85 
    86         frame_t *frames;        /**< array of frame_t structures in this
    87                                      zone */
    88         count_t free_count;     /**< number of free frame_t structures */
    89         count_t busy_count;     /**< number of busy frame_t structures */
    90        
    91         buddy_system_t *buddy_system; /**< buddy system for the zone */
    92         int flags;
     72        pfn_t base;                    /**< Frame_no of the first frame
     73                                        in the frames array */
     74        count_t count;                 /**< Size of zone */
     75        count_t free_count;            /**< Number of free frame_t
     76                                        structures */
     77        count_t busy_count;            /**< Number of busy frame_t
     78                                        structures */
     79        zone_flags_t flags;            /**< Type of the zone */
     80       
     81        frame_t *frames;               /**< Array of frame_t structures
     82                                        in this zone */
     83        buddy_system_t *buddy_system;  /**< Buddy system for the zone */
    9384} zone_t;
    9485
     
    9788 * Some of the attributes in zone_t structures are 'read-only'
    9889 */
    99 
    10090typedef struct {
    10191        SPINLOCK_DECLARE(lock);
    102         unsigned int count;
    103         zone_t *info[ZONES_MAX];
     92        count_t count;
     93        zone_t info[ZONES_MAX];
    10494} zones_t;
    10595
     
    112102mutex_t mem_avail_mtx;
    113103condvar_t mem_avail_cv;
    114 unsigned long mem_avail_frames = 0;     /**< Number of available frames. */
    115 unsigned long mem_avail_gen = 0;        /**< Generation counter. */
     104count_t mem_avail_req = 0;  /**< Number of frames requested. */
     105count_t mem_avail_gen = 0;  /**< Generation counter. */
    116106
    117107/********************/
     
    129119}
    130120
    131 static inline int frame_index_valid(zone_t *zone, index_t index)
     121static inline bool frame_index_valid(zone_t *zone, index_t index)
    132122{
    133123        return (index < zone->count);
    134124}
    135125
    136 /** Compute pfn_t from frame_t pointer & zone pointer */
    137 static index_t make_frame_index(zone_t *zone, frame_t *frame)
     126static inline index_t make_frame_index(zone_t *zone, frame_t *frame)
    138127{
    139128        return (frame - zone->frames);
    140129}
    141130
     131static inline bool zone_flags_available(zone_flags_t flags)
     132{
     133        return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
     134}
     135
    142136/** Initialize frame structure.
    143137 *
    144  * @param frame         Frame structure to be initialized.
     138 * @param frame Frame structure to be initialized.
     139 *
    145140 */
    146141static void frame_initialize(frame_t *frame)
     
    150145}
    151146
    152 /**********************/
    153 /* Zoneinfo functions */
    154 /**********************/
     147/*******************/
     148/* Zones functions */
     149/*******************/
    155150
    156151/** Insert-sort zone into zones list.
    157152 *
    158  * @param newzone       New zone to be inserted into zone list.
    159  * @return              Zone number on success, -1 on error.
    160  */
    161 static int zones_add_zone(zone_t *newzone)
    162 {
    163         unsigned int i, j;
    164         ipl_t ipl;
    165         zone_t *z;
    166 
    167         ipl = interrupts_disable();
    168         spinlock_lock(&zones.lock);
    169        
    170         /* Try to merge */
     153 * Assume interrupts are disabled and zones lock is
     154 * locked.
     155 *
     156 * @param base  Base frame of the newly inserted zone.
     157 * @param count Number of frames of the newly inserted zone.
     158 *
     159 * @return Zone number on success, -1 on error.
     160 *
     161 */
     162static count_t zones_insert_zone(pfn_t base, count_t count)
     163{
    171164        if (zones.count + 1 == ZONES_MAX) {
    172165                printf("Maximum zone count %u exceeded!\n", ZONES_MAX);
    173                 spinlock_unlock(&zones.lock);
    174                 interrupts_restore(ipl);
    175                 return -1;
    176         }
    177        
     166                return (count_t) -1;
     167        }
     168       
     169        count_t i;
    178170        for (i = 0; i < zones.count; i++) {
    179                 /* Check for overflow */
    180                 z = zones.info[i];
    181                 if (overlaps(newzone->base, newzone->count, z->base,
    182                     z->count)) {
     171                /* Check for overlap */
     172                if (overlaps(base, count,
     173                    zones.info[i].base, zones.info[i].count)) {
    183174                        printf("Zones overlap!\n");
    184                         return -1;
     175                        return (count_t) -1;
    185176                }
    186                 if (newzone->base < z->base)
     177                if (base < zones.info[i].base)
    187178                        break;
    188179        }
    189180       
    190181        /* Move other zones up */
     182        count_t j;
    191183        for (j = i; j < zones.count; j++)
    192184                zones.info[j + 1] = zones.info[j];
    193185       
    194         zones.info[i] = newzone;
    195186        zones.count++;
    196187       
    197         spinlock_unlock(&zones.lock);
    198         interrupts_restore(ipl);
    199 
    200188        return i;
    201189}
    202190
    203 /** Try to find a zone where can we find the frame.
    204  *
    205  * Assume interrupts are disabled.
    206  *
    207  * @param frame         Frame number contained in zone.
    208  * @param pzone         If not null, it is used as zone hint. Zone index is
    209  *                      filled into the variable on success.
    210  * @return              Pointer to locked zone containing frame.
    211  */
    212 static zone_t *find_zone_and_lock(pfn_t frame, unsigned int *pzone)
    213 {
    214         unsigned int i;
    215         unsigned int hint = pzone ? *pzone : 0;
    216         zone_t *z;
    217        
    218         spinlock_lock(&zones.lock);
    219 
     191/** Get total available frames.
     192 *
     193 * Assume interrupts are disabled and zones lock is
     194 * locked.
     195 *
     196 * @return Total number of available frames.
     197 *
     198 */
     199static count_t total_frames_free(void)
     200{
     201        count_t total = 0;
     202        count_t i;
     203        for (i = 0; i < zones.count; i++)
     204                total += zones.info[i].free_count;
     205       
     206        return total;
     207}
     208
     209/** Find a zone with a given frame.
     210 *
     211 * Assume interrupts are disabled and zones lock is
     212 * locked.
     213 *
     214 * @param frame Frame number contained in zone.
     215 * @param hint  Used as zone hint.
     216 *
     217 * @return Zone index or -1 if not found.
     218 *
     219 */
     220static count_t find_zone(pfn_t frame, count_t hint)
     221{
    220222        if (hint >= zones.count)
    221223                hint = 0;
    222224       
    223         i = hint;
     225        count_t i = hint;
    224226        do {
    225                 z = zones.info[i];
    226                 spinlock_lock(&z->lock);
    227                 if (z->base <= frame && z->base + z->count > frame) {
    228                         /* Unlock the global lock */
    229                         spinlock_unlock(&zones.lock);
    230                         if (pzone)
    231                                 *pzone = i;
    232                         return z;
    233                 }
    234                 spinlock_unlock(&z->lock);
    235 
     227                if ((zones.info[i].base <= frame)
     228                    && (zones.info[i].base + zones.info[i].count > frame))
     229                        return i;
     230               
    236231                i++;
    237232                if (i >= zones.count)
    238233                        i = 0;
    239234        } while (i != hint);
    240 
    241         spinlock_unlock(&zones.lock);
    242         return NULL;
     235       
     236        return (count_t) -1;
    243237}
    244238
    245239/** @return True if zone can allocate specified order */
    246 static int zone_can_alloc(zone_t *z, uint8_t order)
    247 {
    248         return buddy_system_can_alloc(z->buddy_system, order);
    249 }
    250 
    251 /** Find and lock zone that can allocate order frames.
    252  *
    253  * Assume interrupts are disabled.
    254  *
    255  * @param order         Size (2^order) of free space we are trying to find.
    256  * @param flags         Required flags of the target zone.
    257  * @param pzone         Pointer to preferred zone or NULL, on return contains
    258  *                      zone number.
    259  */
    260 static zone_t *
    261 find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone)
    262 {
    263         unsigned int i;
    264         zone_t *z;
    265         unsigned int hint = pzone ? *pzone : 0;
    266        
    267         /* Mask off flags that are not applicable. */
    268         flags &= FRAME_LOW_4_GiB;
    269 
    270         spinlock_lock(&zones.lock);
     240static bool zone_can_alloc(zone_t *zone, uint8_t order)
     241{
     242        return (zone_flags_available(zone->flags)
     243            && buddy_system_can_alloc(zone->buddy_system, order));
     244}
     245
     246/** Find a zone that can allocate order frames.
     247 *
     248 * Assume interrupts are disabled and zones lock is
     249 * locked.
     250 *
     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 */
     256static count_t find_free_zone(uint8_t order, zone_flags_t flags, count_t hint)
     257{
    271258        if (hint >= zones.count)
    272259                hint = 0;
    273         i = hint;
     260       
     261        count_t i = hint;
    274262        do {
    275                 z = zones.info[i];
    276                
    277                 spinlock_lock(&z->lock);
    278 
    279263                /*
    280264                 * Check whether the zone meets the search criteria.
    281265                 */
    282                 if ((z->flags & flags) == flags) {
     266                if ((zones.info[i].flags & flags) == flags) {
    283267                        /*
    284268                         * Check if the zone has 2^order frames area available.
    285269                         */
    286                         if (zone_can_alloc(z, order)) {
    287                                 spinlock_unlock(&zones.lock);
    288                                 if (pzone)
    289                                         *pzone = i;
    290                                 return z;
    291                         }
     270                        if (zone_can_alloc(&zones.info[i], order))
     271                                return i;
    292272                }
    293                 spinlock_unlock(&z->lock);
    294                 if (++i >= zones.count)
     273               
     274                i++;
     275                if (i >= zones.count)
    295276                        i = 0;
    296277        } while (i != hint);
    297         spinlock_unlock(&zones.lock);
    298         return NULL;
     278       
     279        return (count_t) -1;
    299280}
    300281
     
    308289 * That means go to lower addresses, until such block is found
    309290 *
    310  * @param order         Order of parent must be different then this
    311  *                      parameter!!
    312  */
    313 static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
     291 * @param order Order of parent must be different then this
     292 *              parameter!!
     293 *
     294 */
     295static link_t *zone_buddy_find_block(buddy_system_t *buddy, link_t *child,
    314296    uint8_t order)
    315297{
    316         frame_t *frame;
    317         zone_t *zone;
    318         index_t index;
    319        
    320         frame = list_get_instance(child, frame_t, buddy_link);
    321         zone = (zone_t *) b->data;
    322 
    323         index = frame_index(zone, frame);
     298        frame_t *frame = list_get_instance(child, frame_t, buddy_link);
     299        zone_t *zone = (zone_t *) buddy->data;
     300       
     301        index_t index = frame_index(zone, frame);
    324302        do {
    325                 if (zone->frames[index].buddy_order != order) {
     303                if (zone->frames[index].buddy_order != order)
    326304                        return &zone->frames[index].buddy_link;
    327                 }
    328         } while(index-- > 0);
     305        } while (index-- > 0);
     306       
    329307        return NULL;
    330308}
     
    332310/** Buddy system find_buddy implementation.
    333311 *
    334  * @param b             Buddy system.
    335  * @param block         Block for which buddy should be found.
    336  *
    337  * @return              Buddy for given block if found.
    338  */
    339 static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block)
    340 {
    341         frame_t *frame;
    342         zone_t *zone;
    343         index_t index;
    344         bool is_left, is_right;
    345 
    346         frame = list_get_instance(block, frame_t, buddy_link);
    347         zone = (zone_t *) b->data;
     312 * @param buddy Buddy system.
     313 * @param block Block for which buddy should be found.
     314 *
     315 * @return Buddy for given block if found.
     316 *
     317 */
     318static link_t *zone_buddy_find_buddy(buddy_system_t *buddy, link_t *block)
     319{
     320        frame_t *frame = list_get_instance(block, frame_t, buddy_link);
     321        zone_t *zone = (zone_t *) buddy->data;
    348322        ASSERT(IS_BUDDY_ORDER_OK(frame_index_abs(zone, frame),
    349323            frame->buddy_order));
    350324       
    351         is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
    352         is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
    353 
     325        bool is_left = IS_BUDDY_LEFT_BLOCK_ABS(zone, frame);
     326        bool is_right = IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame);
     327       
    354328        ASSERT(is_left ^ is_right);
     329       
     330        index_t index;
    355331        if (is_left) {
    356332                index = (frame_index(zone, frame)) +
    357333                    (1 << frame->buddy_order);
    358         } else {        /* if (is_right) */
     334        } else {  /* if (is_right) */
    359335                index = (frame_index(zone, frame)) -
    360336                    (1 << frame->buddy_order);
     
    362338       
    363339        if (frame_index_valid(zone, index)) {
    364                 if (zone->frames[index].buddy_order == frame->buddy_order &&
    365                     zone->frames[index].refcount == 0) {
     340                if ((zone->frames[index].buddy_order == frame->buddy_order) &&
     341                    (zone->frames[index].refcount == 0)) {
    366342                        return &zone->frames[index].buddy_link;
    367343                }
    368344        }
    369 
    370         return NULL;   
     345       
     346        return NULL;
    371347}
    372348
    373349/** Buddy system bisect implementation.
    374350 *
    375  * @param b             Buddy system.
    376  * @param block         Block to bisect.
    377  *
    378  * @return              Right block.
    379  */
    380 static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block)
    381 {
    382         frame_t *frame_l, *frame_r;
    383 
    384         frame_l = list_get_instance(block, frame_t, buddy_link);
    385         frame_r = (frame_l + (1 << (frame_l->buddy_order - 1)));
     351 * @param buddy Buddy system.
     352 * @param block Block to bisect.
     353 *
     354 * @return Right block.
     355 *
     356 */
     357static 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)));
    386361       
    387362        return &frame_r->buddy_link;
     
    390365/** Buddy system coalesce implementation.
    391366 *
    392  * @param b             Buddy system.
    393  * @param block_1       First block.
    394  * @param block_2       First block's buddy.
    395  *
    396  * @return              Coalesced block (actually block that represents lower
    397  *                      address).
    398  */
    399 static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1,
    400     link_t *block_2)
    401 {
    402         frame_t *frame1, *frame2;
    403        
    404         frame1 = list_get_instance(block_1, frame_t, buddy_link);
    405         frame2 = list_get_instance(block_2, frame_t, buddy_link);
    406        
    407         return frame1 < frame2 ? block_1 : block_2;
     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 */
     375static link_t *zone_buddy_coalesce(buddy_system_t *buddy, link_t *block_1,
     376    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);
    408382}
    409383
    410384/** Buddy system set_order implementation.
    411385 *
    412  * @param b             Buddy system.
    413  * @param block         Buddy system block.
    414  * @param order         Order to set.
    415  */
    416 static void zone_buddy_set_order(buddy_system_t *b, link_t *block,
     386 * @param buddy Buddy system.
     387 * @param block Buddy system block.
     388 * @param order Order to set.
     389 *
     390 */
     391static void zone_buddy_set_order(buddy_system_t *buddy, link_t *block,
    417392    uint8_t order)
    418393{
    419         frame_t *frame;
    420         frame = list_get_instance(block, frame_t, buddy_link);
    421         frame->buddy_order = order;
     394        list_get_instance(block, frame_t, buddy_link)->buddy_order = order;
    422395}
    423396
    424397/** Buddy system get_order implementation.
    425398 *
    426  * @param b             Buddy system.
    427  * @param block         Buddy system block.
    428  *
    429  * @return              Order of block.
    430  */
    431 static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block)
    432 {
    433         frame_t *frame;
    434         frame = list_get_instance(block, frame_t, buddy_link);
    435         return frame->buddy_order;
     399 * @param buddy Buddy system.
     400 * @param block Buddy system block.
     401 *
     402 * @return Order of block.
     403 *
     404 */
     405static uint8_t zone_buddy_get_order(buddy_system_t *buddy, link_t *block)
     406{
     407        return list_get_instance(block, frame_t, buddy_link)->buddy_order;
    436408}
    437409
    438410/** Buddy system mark_busy implementation.
    439411 *
    440  * @param b             Buddy system.
    441  * @param block         Buddy system block.
    442  */
    443 static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block)
    444 {
    445         frame_t * frame;
    446 
    447         frame = list_get_instance(block, frame_t, buddy_link);
    448         frame->refcount = 1;
     412 * @param buddy Buddy system.
     413 * @param block Buddy system block.
     414 *
     415 */
     416static void zone_buddy_mark_busy(buddy_system_t *buddy, link_t * block)
     417{
     418        list_get_instance(block, frame_t, buddy_link)->refcount = 1;
    449419}
    450420
    451421/** Buddy system mark_available implementation.
    452422 *
    453  * @param b             Buddy system.
    454  * @param block         Buddy system block.
    455  */
    456 static void zone_buddy_mark_available(buddy_system_t *b, link_t *block)
    457 {
    458         frame_t *frame;
    459         frame = list_get_instance(block, frame_t, buddy_link);
    460         frame->refcount = 0;
     423 * @param buddy Buddy system.
     424 * @param block Buddy system block.
     425 */
     426static void zone_buddy_mark_available(buddy_system_t *buddy, link_t *block)
     427{
     428        list_get_instance(block, frame_t, buddy_link)->refcount = 0;
    461429}
    462430
     
    478446/** Allocate frame in particular zone.
    479447 *
    480  * Assume zone is locked.
     448 * Assume zone is locked and is available for allocation.
    481449 * Panics if allocation is impossible.
    482450 *
    483  * @param zone          Zone to allocate from.
    484  * @param order         Allocate exactly 2^order frames.
    485  *
    486  * @return              Frame index in zone.
     451 * @param zone  Zone to allocate from.
     452 * @param order Allocate exactly 2^order frames.
     453 *
     454 * @return Frame index in zone.
    487455 *
    488456 */
    489457static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
    490458{
    491         pfn_t v;
    492         link_t *tmp;
    493         frame_t *frame;
    494 
     459        ASSERT(zone_flags_available(zone->flags));
     460       
    495461        /* Allocate frames from zone buddy system */
    496         tmp = buddy_system_alloc(zone->buddy_system, order);
    497        
    498         ASSERT(tmp);
     462        link_t *link = buddy_system_alloc(zone->buddy_system, order);
     463       
     464        ASSERT(link);
    499465       
    500466        /* Update zone information. */
    501467        zone->free_count -= (1 << order);
    502468        zone->busy_count += (1 << order);
    503 
     469       
    504470        /* Frame will be actually a first frame of the block. */
    505         frame = list_get_instance(tmp, frame_t, buddy_link);
    506        
    507         /* get frame address */
    508         v = make_frame_index(zone, frame);
    509         return v;
     471        frame_t *frame = list_get_instance(link, frame_t, buddy_link);
     472       
     473        /* Get frame address */
     474        return make_frame_index(zone, frame);
    510475}
    511476
    512477/** Free frame from zone.
    513478 *
    514  * Assume zone is locked.
    515  *
    516  * @param zone          Pointer to zone from which the frame is to be freed.
    517  * @param frame_idx     Frame index relative to zone.
     479 * Assume zone is locked and is available for deallocation.
     480 *
     481 * @param zone      Pointer to zone from which the frame is to be freed.
     482 * @param frame_idx Frame index relative to zone.
     483 *
    518484 */
    519485static void zone_frame_free(zone_t *zone, index_t frame_idx)
    520486{
    521         frame_t *frame;
    522         uint8_t order;
    523 
    524         frame = &zone->frames[frame_idx];
    525        
    526         /* remember frame order */
    527         order = frame->buddy_order;
    528 
     487        ASSERT(zone_flags_available(zone->flags));
     488       
     489        frame_t *frame = &zone->frames[frame_idx];
     490       
     491        /* Remember frame order */
     492        uint8_t order = frame->buddy_order;
     493       
    529494        ASSERT(frame->refcount);
    530 
     495       
    531496        if (!--frame->refcount) {
    532497                buddy_system_free(zone->buddy_system, &frame->buddy_link);
    533        
     498               
    534499                /* Update zone information. */
    535500                zone->free_count += (1 << order);
     
    548513static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
    549514{
    550         frame_t *frame;
    551         link_t *link;
    552 
    553         frame = zone_get_frame(zone, frame_idx);
     515        ASSERT(zone_flags_available(zone->flags));
     516       
     517        frame_t *frame = zone_get_frame(zone, frame_idx);
    554518        if (frame->refcount)
    555519                return;
    556         link = buddy_system_alloc_block(zone->buddy_system,
     520       
     521        link_t *link = buddy_system_alloc_block(zone->buddy_system,
    557522            &frame->buddy_link);
     523       
    558524        ASSERT(link);
    559525        zone->free_count--;
    560 
    561         mutex_lock(&mem_avail_mtx);
    562         mem_avail_frames--;
    563         mutex_unlock(&mem_avail_mtx);
    564 }
    565 
    566 /** Join two zones.
    567  *
    568  * Expect zone_t *z to point to space at least zone_conf_size large.
    569  *
    570  * Assume z1 & z2 are locked.
    571  *
    572  * @param z             Target zone structure pointer.
    573  * @param z1            Zone to merge.
    574  * @param z2            Zone to merge.
    575  */
    576 static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
    577 {
    578         uint8_t max_order;
    579         unsigned int i;
    580         int z2idx;
    581         pfn_t frame_idx;
    582         frame_t *frame;
    583 
    584         ASSERT(!overlaps(z1->base, z1->count, z2->base, z2->count));
    585         ASSERT(z1->base < z2->base);
    586 
    587         spinlock_initialize(&z->lock, "zone_lock");
    588         z->base = z1->base;
    589         z->count = z2->base + z2->count - z1->base;
    590         z->flags = z1->flags & z2->flags;
    591 
    592         z->free_count = z1->free_count + z2->free_count;
    593         z->busy_count = z1->busy_count + z2->busy_count;
    594        
    595         max_order = fnzb(z->count);
    596 
    597         z->buddy_system = (buddy_system_t *) &z[1];
    598         buddy_system_create(z->buddy_system, max_order,
    599             &zone_buddy_system_operations, (void *) z);
    600 
    601         z->frames = (frame_t *)((uint8_t *) z->buddy_system +
    602             buddy_conf_size(max_order));
    603         for (i = 0; i < z->count; i++) {
    604                 /* This marks all frames busy */
    605                 frame_initialize(&z->frames[i]);
    606         }
     526}
     527
     528/** Merge two zones.
     529 *
     530 * Expect buddy to point to space at least zone_conf_size large.
     531 * Assume z1 & z2 are locked and compatible and zones lock is
     532 * locked.
     533 *
     534 * @param z1     First zone to merge.
     535 * @param z2     Second zone to merge.
     536 * @param old_z1 Original date of the first zone.
     537 * @param buddy  Merged zone buddy.
     538 *
     539 */
     540static void zone_merge_internal(count_t z1, count_t z2, zone_t *old_z1, buddy_system_t *buddy)
     541{
     542        ASSERT(zone_flags_available(zones.info[z1].flags));
     543        ASSERT(zone_flags_available(zones.info[z2].flags));
     544        ASSERT(zones.info[z1].flags == zones.info[z2].flags);
     545        ASSERT(zones.info[z1].base < zones.info[z2].base);
     546        ASSERT(!overlaps(zones.info[z1].base, zones.info[z1].count,
     547            zones.info[z2].base, zones.info[z2].count));
     548       
     549        /* Difference between zone bases */
     550        pfn_t base_diff = zones.info[z2].base - zones.info[z1].base;
     551       
     552        zones.info[z1].count = base_diff + zones.info[z2].count;
     553        zones.info[z1].free_count += zones.info[z2].free_count;
     554        zones.info[z1].busy_count += zones.info[z2].busy_count;
     555        zones.info[z1].buddy_system = buddy;
     556       
     557        uint8_t order = fnzb(zones.info[z1].count);
     558        buddy_system_create(zones.info[z1].buddy_system, order,
     559            &zone_buddy_system_operations, (void *) &zones.info[z1]);
     560       
     561        zones.info[z1].frames =
     562            (frame_t *) ((uint8_t *) zones.info[z1].buddy_system
     563            + buddy_conf_size(order));
     564       
     565        /* This marks all frames busy */
     566        count_t i;
     567        for (i = 0; i < zones.info[z1].count; i++)
     568                frame_initialize(&zones.info[z1].frames[i]);
     569       
    607570        /* Copy frames from both zones to preserve full frame orders,
    608          * parents etc. Set all free frames with refcount=0 to 1, because
    609          * we add all free frames to buddy allocator later again, clear
    610          * order to 0. Don't set busy frames with refcount=0, as they
     571         * parents etc. Set all free frames with refcount = 0 to 1, because
     572         * we add all free frames to buddy allocator later again, clearing
     573         * order to 0. Don't set busy frames with refcount = 0, as they
    611574         * will not be reallocated during merge and it would make later
    612575         * problems with allocation/free.
    613576         */
    614         for (i = 0; i < z1->count; i++)
    615                 z->frames[i] = z1->frames[i];
    616         for (i = 0; i < z2->count; i++) {
    617                 z2idx = i + (z2->base - z1->base);
    618                 z->frames[z2idx] = z2->frames[i];
    619         }
     577        for (i = 0; i < old_z1->count; i++)
     578                zones.info[z1].frames[i] = old_z1->frames[i];
     579       
     580        for (i = 0; i < zones.info[z2].count; i++)
     581                zones.info[z1].frames[base_diff + i]
     582                    = zones.info[z2].frames[i];
     583       
    620584        i = 0;
    621         while (i < z->count) {
    622                 if (z->frames[i].refcount) {
    623                         /* skip busy frames */
    624                         i += 1 << z->frames[i].buddy_order;
    625                 } else { /* Free frames, set refcount=1 */
    626                         /* All free frames have refcount=0, we need not
    627                          * to check the order */
    628                         z->frames[i].refcount = 1;
    629                         z->frames[i].buddy_order = 0;
     585        while (i < zones.info[z1].count) {
     586                if (zones.info[z1].frames[i].refcount) {
     587                        /* Skip busy frames */
     588                        i += 1 << zones.info[z1].frames[i].buddy_order;
     589                } else {
     590                        /* Free frames, set refcount = 1
     591                         * (all free frames have refcount == 0, we need not
     592                         * to check the order)
     593                         */
     594                        zones.info[z1].frames[i].refcount = 1;
     595                        zones.info[z1].frames[i].buddy_order = 0;
    630596                        i++;
    631597                }
    632598        }
    633         /* Add free blocks from the 2 original zones */
    634         while (zone_can_alloc(z1, 0)) {
    635                 frame_idx = zone_frame_alloc(z1, 0);
    636                 frame = &z->frames[frame_idx];
     599       
     600        /* Add free blocks from the original zone z1 */
     601        while (zone_can_alloc(old_z1, 0)) {
     602                /* Allocate from the original zone */
     603                pfn_t frame_idx = zone_frame_alloc(old_z1, 0);
     604               
     605                /* Free the frame from the merged zone */
     606                frame_t *frame = &zones.info[z1].frames[frame_idx];
    637607                frame->refcount = 0;
    638                 buddy_system_free(z->buddy_system, &frame->buddy_link);
    639         }
    640         while (zone_can_alloc(z2, 0)) {
    641                 frame_idx = zone_frame_alloc(z2, 0);
    642                 frame = &z->frames[frame_idx + (z2->base - z1->base)];
     608                buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
     609        }
     610       
     611        /* Add free blocks from the original zone z2 */
     612        while (zone_can_alloc(&zones.info[z2], 0)) {
     613                /* Allocate from the original zone */
     614                pfn_t frame_idx = zone_frame_alloc(&zones.info[z2], 0);
     615               
     616                /* Free the frame from the merged zone */
     617                frame_t *frame = &zones.info[z1].frames[base_diff + frame_idx];
    643618                frame->refcount = 0;
    644                 buddy_system_free(z->buddy_system, &frame->buddy_link);
     619                buddy_system_free(zones.info[z1].buddy_system, &frame->buddy_link);
    645620        }
    646621}
     
    648623/** Return old configuration frames into the zone.
    649624 *
    650  * We have several cases
    651  * - the conf. data is outside of zone -> exit, shall we call frame_free??
    652  * - the conf. data was created by zone_create or
    653  *   updated with reduce_region -> free every frame
    654  *
    655  * @param newzone       The actual zone where freeing should occur.
    656  * @param oldzone       Pointer to old zone configuration data that should
    657  *                      be freed from new zone.
    658  */
    659 static void return_config_frames(zone_t *newzone, zone_t *oldzone)
    660 {
    661         pfn_t pfn;
    662         frame_t *frame;
    663         count_t cframes;
    664         unsigned int i;
    665 
    666         pfn = ADDR2PFN((uintptr_t)KA2PA(oldzone));
    667         cframes = SIZE2FRAMES(zone_conf_size(oldzone->count));
    668        
    669         if (pfn < newzone->base || pfn >= newzone->base + newzone->count)
     625 * We have two cases:
     626 * - The configuration data is outside the zone
     627 *   -> do nothing (perhaps call frame_free?)
     628 * - The configuration data was created by zone_create
     629 *   or updated by reduce_region -> free every frame
     630 *
     631 * @param znum  The actual zone where freeing should occur.
     632 * @param pfn   Old zone configuration frame.
     633 * @param count Old zone frame count.
     634 *
     635 */
     636static void return_config_frames(count_t znum, pfn_t pfn, count_t count)
     637{
     638        ASSERT(zone_flags_available(zones.info[znum].flags));
     639       
     640        count_t cframes = SIZE2FRAMES(zone_conf_size(count));
     641       
     642        if ((pfn < zones.info[znum].base)
     643            || (pfn >= zones.info[znum].base + zones.info[znum].count))
    670644                return;
    671 
    672         frame = &newzone->frames[pfn - newzone->base];
     645       
     646        frame_t *frame
     647            = &zones.info[znum].frames[pfn - zones.info[znum].base];
    673648        ASSERT(!frame->buddy_order);
    674 
     649       
     650        count_t i;
    675651        for (i = 0; i < cframes; i++) {
    676                 newzone->busy_count++;
    677                 zone_frame_free(newzone, pfn+i-newzone->base);
     652                zones.info[znum].busy_count++;
     653                zone_frame_free(&zones.info[znum],
     654                    pfn - zones.info[znum].base + i);
    678655        }
    679656}
     
    681658/** Reduce allocated block to count of order 0 frames.
    682659 *
    683  * The allocated block need 2^order frames of space. Reduce all frames
    684  * in block to order 0 and free the unneeded frames. This means, that
    685  * when freeing the previously allocated block starting with frame_idx, 
     660 * The allocated block needs 2^order frames. Reduce all frames
     661 * in the block to order 0 and free the unneeded frames. This means that
     662 * when freeing the previously allocated block starting with frame_idx,
    686663 * you have to free every frame.
    687664 *
    688  * @param zone
    689  * @param frame_idx             Index to block.
    690  * @param count                 Allocated space in block.
    691  */
    692 static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count)
    693 {
     665 * @param znum      Zone.
     666 * @param frame_idx Index the first frame of the block.
     667 * @param count     Allocated frames in block.
     668 *
     669 */
     670static void zone_reduce_region(count_t znum, pfn_t frame_idx, count_t count)
     671{
     672        ASSERT(zone_flags_available(zones.info[znum].flags));
     673        ASSERT(frame_idx + count < zones.info[znum].count);
     674       
     675        uint8_t order = zones.info[znum].frames[frame_idx].buddy_order;
     676        ASSERT((count_t) (1 << order) >= count);
     677       
     678        /* Reduce all blocks to order 0 */
    694679        count_t i;
    695         uint8_t order;
    696         frame_t *frame;
    697        
    698         ASSERT(frame_idx + count < zone->count);
    699 
    700         order = zone->frames[frame_idx].buddy_order;
    701         ASSERT((count_t) (1 << order) >= count);
    702 
    703         /* Reduce all blocks to order 0 */
    704680        for (i = 0; i < (count_t) (1 << order); i++) {
    705                 frame = &zone->frames[i + frame_idx];
     681                frame_t *frame = &zones.info[znum].frames[i + frame_idx];
    706682                frame->buddy_order = 0;
    707683                if (!frame->refcount)
     
    709685                ASSERT(frame->refcount == 1);
    710686        }
     687       
    711688        /* Free unneeded frames */
    712         for (i = count; i < (count_t) (1 << order); i++) {
    713                 zone_frame_free(zone, i + frame_idx);
    714         }
     689        for (i = count; i < (count_t) (1 << order); i++)
     690                zone_frame_free(&zones.info[znum], i + frame_idx);
    715691}
    716692
    717693/** Merge zones z1 and z2.
    718694 *
    719  * - the zones must be 2 zones with no zone existing in between,
    720  *   which means that z2 = z1+1
    721  *
    722  * - When you create a new zone, the frame allocator configuration does
    723  *   not to be 2^order size. Once the allocator is running it is no longer
    724  *   possible, merged configuration data occupies more space :-/
    725  */
    726 void zone_merge(unsigned int z1, unsigned int z2)
    727 {
    728         ipl_t ipl;
    729         zone_t *zone1, *zone2, *newzone;
    730         unsigned int cframes;
     695 * The merged zones must be 2 zones with no zone existing in between
     696 * (which means that z2 = z1 + 1). Both zones must be available zones
     697 * with the same flags.
     698 *
     699 * When you create a new zone, the frame allocator configuration does
     700 * not to be 2^order size. Once the allocator is running it is no longer
     701 * possible, merged configuration data occupies more space :-/
     702 *
     703 * The function uses
     704 *
     705 */
     706bool zone_merge(count_t z1, count_t z2)
     707{
     708        ipl_t ipl = interrupts_disable();
     709        spinlock_lock(&zones.lock);
     710       
     711        bool ret = true;
     712       
     713        /* We can join only 2 zones with none existing inbetween,
     714         * the zones have to be available and with the same
     715         * set of flags
     716         */
     717        if ((z1 >= zones.count) || (z2 >= zones.count)
     718            || (z2 - z1 != 1)
     719            || (!zone_flags_available(zones.info[z1].flags))
     720            || (!zone_flags_available(zones.info[z2].flags))
     721            || (zones.info[z1].flags != zones.info[z2].flags)) {
     722                ret = false;
     723                goto errout;
     724        }
     725       
     726        pfn_t cframes = SIZE2FRAMES(zone_conf_size(
     727            zones.info[z2].base - zones.info[z1].base
     728            + zones.info[z2].count));
     729       
    731730        uint8_t order;
    732         unsigned int i;
    733         pfn_t pfn;
    734 
    735         ipl = interrupts_disable();
    736         spinlock_lock(&zones.lock);
    737 
    738         if ((z1 >= zones.count) || (z2 >= zones.count))
    739                 goto errout;
    740         /* We can join only 2 zones with none existing inbetween */
    741         if (z2 - z1 != 1)
    742                 goto errout;
    743 
    744         zone1 = zones.info[z1];
    745         zone2 = zones.info[z2];
    746         spinlock_lock(&zone1->lock);
    747         spinlock_lock(&zone2->lock);
    748 
    749         cframes = SIZE2FRAMES(zone_conf_size(zone2->base + zone2->count -
    750             zone1->base));
    751731        if (cframes == 1)
    752732                order = 0;
    753         else 
     733        else
    754734                order = fnzb(cframes - 1) + 1;
    755 
    756         /* Allocate zonedata inside one of the zones */
    757         if (zone_can_alloc(zone1, order))
    758                 pfn = zone1->base + zone_frame_alloc(zone1, order);
    759         else if (zone_can_alloc(zone2, order))
    760                 pfn = zone2->base + zone_frame_alloc(zone2, order);
    761         else
    762                 goto errout2;
    763 
    764         newzone = (zone_t *) PA2KA(PFN2ADDR(pfn));
    765 
    766         _zone_merge(newzone, zone1, zone2);
    767 
     735       
     736        /* Allocate merged zone data inside one of the zones */
     737        pfn_t pfn;
     738        if (zone_can_alloc(&zones.info[z1], order)) {
     739                pfn = zones.info[z1].base + zone_frame_alloc(&zones.info[z1], order);
     740        } else if (zone_can_alloc(&zones.info[z2], order)) {
     741                pfn = zones.info[z2].base + zone_frame_alloc(&zones.info[z2], order);
     742        } else {
     743                ret = false;
     744                goto errout;
     745        }
     746       
     747        /* Preserve original data from z1 */
     748        zone_t old_z1 = zones.info[z1];
     749        old_z1.buddy_system->data = (void *) &old_z1;
     750       
     751        /* Do zone merging */
     752        buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(pfn));
     753        zone_merge_internal(z1, z2, &old_z1, buddy);
     754       
    768755        /* Free unneeded config frames */
    769         zone_reduce_region(newzone, pfn - newzone->base,  cframes);
     756        zone_reduce_region(z1, pfn - zones.info[z1].base, cframes);
     757       
    770758        /* Subtract zone information from busy frames */
    771         newzone->busy_count -= cframes;
    772 
    773         /* Replace existing zones in zoneinfo list */
    774         zones.info[z1] = newzone;
     759        zones.info[z1].busy_count -= cframes;
     760       
     761        /* Free old zone information */
     762        return_config_frames(z1,
     763            ADDR2PFN(KA2PA((uintptr_t) old_z1.frames)), old_z1.count);
     764        return_config_frames(z1,
     765            ADDR2PFN(KA2PA((uintptr_t) zones.info[z2].frames)),
     766            zones.info[z2].count);
     767       
     768        /* Shift existing zones */
     769        count_t i;
    775770        for (i = z2 + 1; i < zones.count; i++)
    776771                zones.info[i - 1] = zones.info[i];
    777772        zones.count--;
    778 
    779         /* Free old zone information */
    780         return_config_frames(newzone, zone1);
    781         return_config_frames(newzone, zone2);
    782 errout2:
    783         /* Nobody is allowed to enter to zone, so we are safe
    784          * to touch the spinlocks last time */
    785         spinlock_unlock(&zone1->lock);
    786         spinlock_unlock(&zone2->lock);
     773       
    787774errout:
    788775        spinlock_unlock(&zones.lock);
    789776        interrupts_restore(ipl);
    790 }
    791 
    792 /** Merge all zones into one big zone.
    793  *
    794  * It is reasonable to do this on systems whose bios reports parts in chunks,
    795  * so that we could have 1 zone (it's faster).
     777       
     778        return ret;
     779}
     780
     781/** Merge all mergeable zones into one big zone.
     782 *
     783 * It is reasonable to do this on systems where
     784 * BIOS reports parts in chunks, so that we could
     785 * have 1 zone (it's faster).
     786 *
    796787 */
    797788void zone_merge_all(void)
    798789{
    799         int count = zones.count;
    800 
    801         while (zones.count > 1 && --count) {
    802                 zone_merge(0, 1);
    803                 break;
     790        count_t i = 0;
     791        while (i < zones.count) {
     792                if (!zone_merge(i, i + 1))
     793                        i++;
    804794        }
    805795}
     
    807797/** Create new frame zone.
    808798 *
    809  * @param start         Physical address of the first frame within the zone.
    810  * @param count         Count of frames in zone.
    811  * @param z             Address of configuration information of zone.
    812  * @param flags         Zone flags.
    813  *
    814  * @return              Initialized zone.
    815  */
    816 static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
    817 {
    818         unsigned int i;
    819         uint8_t max_order;
    820 
    821         spinlock_initialize(&z->lock, "zone_lock");
    822         z->base = start;
    823         z->count = count;
    824 
    825         /* Mask off flags that are calculated automatically. */
    826         flags &= ~FRAME_LOW_4_GiB;
    827         /* Determine calculated flags. */
    828         if (z->base + count < (1ULL << (32 - FRAME_WIDTH)))     /* 4 GiB */
    829                 flags |= FRAME_LOW_4_GiB;
    830 
    831         z->flags = flags;
    832 
    833         z->free_count = count;
    834         z->busy_count = 0;
    835 
    836         /*
    837          * Compute order for buddy system, initialize
    838          */
    839         max_order = fnzb(count);
    840         z->buddy_system = (buddy_system_t *)&z[1];
    841        
    842         buddy_system_create(z->buddy_system, max_order,
    843             &zone_buddy_system_operations, (void *) z);
    844        
    845         /* Allocate frames _after_ the conframe */
    846         /* Check sizes */
    847         z->frames = (frame_t *)((uint8_t *) z->buddy_system +
    848             buddy_conf_size(max_order));
    849         for (i = 0; i < count; i++) {
    850                 frame_initialize(&z->frames[i]);
    851         }
    852        
    853         /* Stuffing frames */
    854         for (i = 0; i < count; i++) {
    855                 z->frames[i].refcount = 0;
    856                 buddy_system_free(z->buddy_system, &z->frames[i].buddy_link);
    857         }
     799 * @param zone  Zone to construct.
     800 * @param buddy Address of buddy system configuration information.
     801 * @param start Physical address of the first frame within the zone.
     802 * @param count Count of frames in zone.
     803 * @param flags Zone flags.
     804 *
     805 * @return Initialized zone.
     806 *
     807 */
     808static void zone_construct(zone_t *zone, buddy_system_t *buddy, pfn_t start, count_t count, zone_flags_t flags)
     809{
     810        zone->base = start;
     811        zone->count = count;
     812        zone->flags = flags;
     813        zone->free_count = count;
     814        zone->busy_count = 0;
     815        zone->buddy_system = buddy;
     816       
     817        if (zone_flags_available(flags)) {
     818                /*
     819                 * Compute order for buddy system and initialize
     820                 */
     821                uint8_t order = fnzb(count);
     822                buddy_system_create(zone->buddy_system, order,
     823                    &zone_buddy_system_operations, (void *) zone);
     824               
     825                /* Allocate frames _after_ the confframe */
     826               
     827                /* Check sizes */
     828                zone->frames = (frame_t *) ((uint8_t *) zone->buddy_system +
     829                    buddy_conf_size(order));
     830               
     831                count_t i;
     832                for (i = 0; i < count; i++)
     833                        frame_initialize(&zone->frames[i]);
     834               
     835                /* Stuffing frames */
     836                for (i = 0; i < count; i++) {
     837                        zone->frames[i].refcount = 0;
     838                        buddy_system_free(zone->buddy_system, &zone->frames[i].buddy_link);
     839                }
     840        } else
     841                zone->frames = NULL;
    858842}
    859843
    860844/** Compute configuration data size for zone.
    861845 *
    862  * @param count         Size of zone in frames.
    863  * @return              Size of zone configuration info (in bytes).
     846 * @param count Size of zone in frames.
     847 *
     848 * @return Size of zone configuration info (in bytes).
     849 *
    864850 */
    865851uintptr_t zone_conf_size(count_t count)
    866852{
    867         int size = sizeof(zone_t) + count * sizeof(frame_t);
    868         int max_order;
    869 
    870         max_order = fnzb(count);
    871         size += buddy_conf_size(max_order);
    872         return size;
     853        return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
    873854}
    874855
    875856/** Create and add zone to system.
    876857 *
    877  * @param start         First frame number (absolute).
    878  * @param count         Size of zone in frames.
    879  * @param confframe     Where configuration frames are supposed to be.
    880  *                      Automatically checks, that we will not disturb the
    881  *                      kernel and possibly init.  If confframe is given
    882  *                      _outside_ this zone, it is expected, that the area is
    883  *                      already marked BUSY and big enough to contain
    884  *                      zone_conf_size() amount of data.  If the confframe is
    885  *                      inside the area, the zone free frame information is
    886  *                      modified not to include it.
    887  *
    888  * @return              Zone number or -1 on error.
    889  */
    890 int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
    891 {
    892         zone_t *z;
    893         uintptr_t addr;
    894         count_t confcount;
    895         unsigned int i;
    896         int znum;
    897 
    898         /* Theoretically we could have here 0, practically make sure
    899          * nobody tries to do that. If some platform requires, remove
    900          * the assert
    901          */
    902         ASSERT(confframe);
    903         /* If conframe is supposed to be inside our zone, then make sure
    904          * it does not span kernel & init
    905          */
    906         confcount = SIZE2FRAMES(zone_conf_size(count));
    907         if (confframe >= start && confframe < start + count) {
    908                 for (; confframe < start + count; confframe++) {
    909                         addr = PFN2ADDR(confframe);
    910                         if (overlaps(addr, PFN2ADDR(confcount),
    911                             KA2PA(config.base), config.kernel_size))
    912                                 continue;
     858 * @param start     First frame number (absolute).
     859 * @param count     Size of zone in frames.
     860 * @param confframe Where configuration frames are supposed to be.
     861 *                  Automatically checks, that we will not disturb the
     862 *                  kernel and possibly init. If confframe is given
     863 *                  _outside_ this zone, it is expected, that the area is
     864 *                  already marked BUSY and big enough to contain
     865 *                  zone_conf_size() amount of data. If the confframe is
     866 *                  inside the area, the zone free frame information is
     867 *                  modified not to include it.
     868 *
     869 * @return Zone number or -1 on error.
     870 *
     871 */
     872count_t zone_create(pfn_t start, count_t count, pfn_t confframe, zone_flags_t flags)
     873{
     874        ipl_t ipl = interrupts_disable();
     875        spinlock_lock(&zones.lock);
     876       
     877        if (zone_flags_available(flags)) {  /* Create available zone */
     878                /* Theoretically we could have NULL here, practically make sure
     879                 * nobody tries to do that. If some platform requires, remove
     880                 * the assert
     881                 */
     882                ASSERT(confframe != NULL);
     883               
     884                /* If confframe is supposed to be inside our zone, then make sure
     885                 * it does not span kernel & init
     886                 */
     887                count_t confcount = SIZE2FRAMES(zone_conf_size(count));
     888                if ((confframe >= start) && (confframe < start + count)) {
     889                        for (; confframe < start + count; confframe++) {
     890                                uintptr_t addr = PFN2ADDR(confframe);
     891                                if (overlaps(addr, PFN2ADDR(confcount),
     892                                    KA2PA(config.base), config.kernel_size))
     893                                        continue;
     894                               
     895                                if (overlaps(addr, PFN2ADDR(confcount),
     896                                    KA2PA(config.stack_base), config.stack_size))
     897                                        continue;
     898                               
     899                                bool overlap = false;
     900                                count_t i;
     901                                for (i = 0; i < init.cnt; i++)
     902                                        if (overlaps(addr, PFN2ADDR(confcount),
     903                                            KA2PA(init.tasks[i].addr),
     904                                            init.tasks[i].size)) {
     905                                                overlap = true;
     906                                                break;
     907                                        }
     908                                if (overlap)
     909                                        continue;
     910                               
     911                                break;
     912                        }
    913913                       
    914                         if (overlaps(addr, PFN2ADDR(confcount),
    915                             KA2PA(config.stack_base), config.stack_size))
    916                                 continue;
    917                        
    918                         bool overlap = false;
     914                        if (confframe >= start + count)
     915                                panic("Cannot find configuration data for zone.");
     916                }
     917               
     918                count_t znum = zones_insert_zone(start, count);
     919                if (znum == (count_t) -1) {
     920                        spinlock_unlock(&zones.lock);
     921                        interrupts_restore(ipl);
     922                        return (count_t) -1;
     923                }
     924               
     925                buddy_system_t *buddy = (buddy_system_t *) PA2KA(PFN2ADDR(confframe));
     926                zone_construct(&zones.info[znum], buddy, start, count, flags);
     927               
     928                /* If confdata in zone, mark as unavailable */
     929                if ((confframe >= start) && (confframe < start + count)) {
    919930                        count_t i;
    920                         for (i = 0; i < init.cnt; i++)
    921                                 if (overlaps(addr, PFN2ADDR(confcount),
    922                                     KA2PA(init.tasks[i].addr),
    923                                     init.tasks[i].size)) {
    924                                         overlap = true;
    925                                         break;
    926                                 }
    927                         if (overlap)
    928                                 continue;
    929                        
    930                         break;
     931                        for (i = confframe; i < confframe + confcount; i++)
     932                                zone_mark_unavailable(&zones.info[znum],
     933                                    i - zones.info[znum].base);
    931934                }
    932                 if (confframe >= start + count)
    933                         panic("Cannot find configuration data for zone.");
    934         }
    935 
    936         z = (zone_t *) PA2KA(PFN2ADDR(confframe));
    937         zone_construct(start, count, z, flags);
    938         znum = zones_add_zone(z);
    939         if (znum == -1)
    940                 return -1;
    941 
    942         mutex_lock(&mem_avail_mtx);
    943         mem_avail_frames += count;
    944         mutex_unlock(&mem_avail_mtx);
    945 
    946         /* If confdata in zone, mark as unavailable */
    947         if (confframe >= start && confframe < start + count)
    948                 for (i = confframe; i < confframe + confcount; i++) {
    949                         zone_mark_unavailable(z, i - z->base);
    950                 }
     935               
     936                spinlock_unlock(&zones.lock);
     937                interrupts_restore(ipl);
     938               
     939                return znum;
     940        }
     941       
     942        /* Non-available zone */
     943        count_t znum = zones_insert_zone(start, count);
     944        if (znum == (count_t) -1) {
     945                spinlock_unlock(&zones.lock);
     946                interrupts_restore(ipl);
     947                return (count_t) -1;
     948        }
     949        zone_construct(&zones.info[znum], NULL, start, count, flags);
     950       
     951        spinlock_unlock(&zones.lock);
     952        interrupts_restore(ipl);
    951953       
    952954        return znum;
    953955}
    954956
    955 /***************************************/
     957/*******************/
    956958/* Frame functions */
     959/*******************/
    957960
    958961/** Set parent of frame. */
    959 void frame_set_parent(pfn_t pfn, void *data, unsigned int hint)
    960 {
    961         zone_t *zone = find_zone_and_lock(pfn, &hint);
    962 
    963         ASSERT(zone);
    964 
    965         zone_get_frame(zone, pfn - zone->base)->parent = data;
    966         spinlock_unlock(&zone->lock);
    967 }
    968 
    969 void *frame_get_parent(pfn_t pfn, unsigned int hint)
    970 {
    971         zone_t *zone = find_zone_and_lock(pfn, &hint);
    972         void *res;
    973 
    974         ASSERT(zone);
    975         res = zone_get_frame(zone, pfn - zone->base)->parent;
    976        
    977         spinlock_unlock(&zone->lock);
     962void frame_set_parent(pfn_t pfn, void *data, count_t hint)
     963{
     964        ipl_t ipl = interrupts_disable();
     965        spinlock_lock(&zones.lock);
     966       
     967        count_t znum = find_zone(pfn, hint);
     968       
     969        ASSERT(znum != (count_t) -1);
     970       
     971        zone_get_frame(&zones.info[znum],
     972            pfn - zones.info[znum].base)->parent = data;
     973       
     974        spinlock_unlock(&zones.lock);
     975        interrupts_restore(ipl);
     976}
     977
     978void *frame_get_parent(pfn_t pfn, count_t hint)
     979{
     980        ipl_t ipl = interrupts_disable();
     981        spinlock_lock(&zones.lock);
     982       
     983        count_t znum = find_zone(pfn, hint);
     984       
     985        ASSERT(znum != (count_t) -1);
     986       
     987        void *res = zone_get_frame(&zones.info[znum],
     988            pfn - zones.info[znum].base)->parent;
     989       
     990        spinlock_unlock(&zones.lock);
     991        interrupts_restore(ipl);
     992       
    978993        return res;
    979994}
     
    981996/** Allocate power-of-two frames of physical memory.
    982997 *
    983  * @param order         Allocate exactly 2^order frames.
    984  * @param flags         Flags for host zone selection and address processing.
    985  * @param pzone         Preferred zone.
    986  *
    987  * @return              Physical address of the allocated frame.
    988  *
    989  */
    990 void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone)
    991 {
     998 * @param order Allocate exactly 2^order frames.
     999 * @param flags Flags for host zone selection and address processing.
     1000 * @param pzone Preferred zone.
     1001 *
     1002 * @return Physical address of the allocated frame.
     1003 *
     1004 */
     1005void *frame_alloc_generic(uint8_t order, frame_flags_t flags, count_t *pzone)
     1006{
     1007        count_t size = ((count_t) 1) << order;
    9921008        ipl_t ipl;
    993         int freed;
    994         pfn_t v;
    995         zone_t *zone;
    996         unsigned long gen = 0;
     1009        count_t hint = pzone ? (*pzone) : 0;
    9971010       
    9981011loop:
    9991012        ipl = interrupts_disable();
     1013        spinlock_lock(&zones.lock);
    10001014       
    10011015        /*
    10021016         * First, find suitable frame zone.
    10031017         */
    1004         zone = find_free_zone_and_lock(order, flags, pzone);
     1018        count_t znum = find_free_zone(order,
     1019            FRAME_TO_ZONE_FLAGS(flags), hint);
    10051020       
    10061021        /* If no memory, reclaim some slab memory,
    10071022           if it does not help, reclaim all */
    1008         if (!zone && !(flags & FRAME_NO_RECLAIM)) {
    1009                 freed = slab_reclaim(0);
    1010                 if (freed)
    1011                         zone = find_free_zone_and_lock(order, flags, pzone);
    1012                 if (!zone) {
     1023        if ((znum == (count_t) -1) && (!(flags & FRAME_NO_RECLAIM))) {
     1024                count_t freed = slab_reclaim(0);
     1025               
     1026                if (freed > 0)
     1027                        znum = find_free_zone(order,
     1028                            FRAME_TO_ZONE_FLAGS(flags), hint);
     1029               
     1030                if (znum == (count_t) -1) {
    10131031                        freed = slab_reclaim(SLAB_RECLAIM_ALL);
    1014                         if (freed)
    1015                                 zone = find_free_zone_and_lock(order, flags,
    1016                                     pzone);
     1032                        if (freed > 0)
     1033                                znum = find_free_zone(order,
     1034                                    FRAME_TO_ZONE_FLAGS(flags), hint);
    10171035                }
    10181036        }
    1019         if (!zone) {
     1037       
     1038        if (znum == (count_t) -1) {
     1039                if (flags & FRAME_ATOMIC) {
     1040                        spinlock_unlock(&zones.lock);
     1041                        interrupts_restore(ipl);
     1042                        return NULL;
     1043                }
     1044               
     1045#ifdef CONFIG_DEBUG
     1046                count_t avail = total_frames_free();
     1047#endif
     1048               
     1049                spinlock_unlock(&zones.lock);
     1050                interrupts_restore(ipl);
     1051               
    10201052                /*
    10211053                 * Sleep until some frames are available again.
    10221054                 */
    1023                 if (flags & FRAME_ATOMIC) {
    1024                         interrupts_restore(ipl);
    1025                         return 0;
    1026                 }
    10271055               
    10281056#ifdef CONFIG_DEBUG
    1029                 unsigned long avail;
    1030 
     1057                printf("Thread %" PRIu64 " waiting for %" PRIc " frames, "
     1058                    "%" PRIc " available.\n", THREAD->tid, size, avail);
     1059#endif
     1060               
    10311061                mutex_lock(&mem_avail_mtx);
    1032                 avail = mem_avail_frames;
     1062               
     1063                if (mem_avail_req > 0)
     1064                        mem_avail_req = min(mem_avail_req, size);
     1065                else
     1066                        mem_avail_req = size;
     1067                count_t gen = mem_avail_gen;
     1068               
     1069                while (gen == mem_avail_gen)
     1070                        condvar_wait(&mem_avail_cv, &mem_avail_mtx);
     1071               
    10331072                mutex_unlock(&mem_avail_mtx);
    1034 
    1035                 printf("Thread %" PRIu64 " waiting for %u frames, "
    1036                     "%u available.\n", THREAD->tid, 1ULL << order, avail);
     1073               
     1074#ifdef CONFIG_DEBUG
     1075                printf("Thread %" PRIu64 " woken up.\n", THREAD->tid);
    10371076#endif
    1038 
    1039                 mutex_lock(&mem_avail_mtx);
    1040                 while ((mem_avail_frames < (1ULL << order)) ||
    1041                     gen == mem_avail_gen)
    1042                         condvar_wait(&mem_avail_cv, &mem_avail_mtx);
    1043                 gen = mem_avail_gen;
    1044                 mutex_unlock(&mem_avail_mtx);
    1045 
    1046 #ifdef CONFIG_DEBUG
    1047                 mutex_lock(&mem_avail_mtx);
    1048                 avail = mem_avail_frames;
    1049                 mutex_unlock(&mem_avail_mtx);
    1050 
    1051                 printf("Thread %" PRIu64 " woken up, %u frames available.\n",
    1052                     THREAD->tid, avail);
    1053 #endif
    1054 
    1055                 interrupts_restore(ipl);
     1077               
    10561078                goto loop;
    10571079        }
    10581080       
    1059         v = zone_frame_alloc(zone, order);
    1060         v += zone->base;
    1061 
    1062         spinlock_unlock(&zone->lock);
    1063        
    1064         mutex_lock(&mem_avail_mtx);
    1065         mem_avail_frames -= (1ULL << order);
    1066         mutex_unlock(&mem_avail_mtx);
    1067 
     1081        pfn_t pfn = zone_frame_alloc(&zones.info[znum], order)
     1082            + zones.info[znum].base;
     1083       
     1084        spinlock_unlock(&zones.lock);
    10681085        interrupts_restore(ipl);
    1069 
     1086       
     1087        if (pzone)
     1088                *pzone = znum;
     1089       
    10701090        if (flags & FRAME_KA)
    1071                 return (void *)PA2KA(PFN2ADDR(v));
    1072         return (void *)PFN2ADDR(v);
     1091                return (void *) PA2KA(PFN2ADDR(pfn));
     1092       
     1093        return (void *) PFN2ADDR(pfn);
    10731094}
    10741095
     
    10761097 *
    10771098 * Find respective frame structure for supplied physical frame address.
    1078  * Decrement frame reference count.
    1079  * If it drops to zero, move the frame structure to free list.
    1080  *
    1081  * @param frame         Physical Address of of the frame to be freed.
     1099 * Decrement frame reference count. If it drops to zero, move the frame
     1100 * structure to free list.
     1101 *
     1102 * @param frame Physical Address of of the frame to be freed.
     1103 *
    10821104 */
    10831105void frame_free(uintptr_t frame)
    10841106{
    1085         ipl_t ipl;
    1086         zone_t *zone;
    1087         pfn_t pfn = ADDR2PFN(frame);
    1088 
    1089         ipl = interrupts_disable();
    1090 
     1107        ipl_t ipl = interrupts_disable();
     1108        spinlock_lock(&zones.lock);
     1109       
    10911110        /*
    10921111         * First, find host frame zone for addr.
    10931112         */
    1094         zone = find_zone_and_lock(pfn, NULL);
    1095         ASSERT(zone);
    1096        
    1097         zone_frame_free(zone, pfn - zone->base);
    1098        
    1099         spinlock_unlock(&zone->lock);
     1113        pfn_t pfn = ADDR2PFN(frame);
     1114        count_t znum = find_zone(pfn, NULL);
     1115       
     1116        ASSERT(znum != (count_t) -1);
     1117       
     1118        zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
     1119       
     1120        spinlock_unlock(&zones.lock);
     1121        interrupts_restore(ipl);
    11001122       
    11011123        /*
     
    11031125         */
    11041126        mutex_lock(&mem_avail_mtx);
    1105         mem_avail_frames++;
    1106         mem_avail_gen++;
    1107         condvar_broadcast(&mem_avail_cv);
     1127        if (mem_avail_req > 0)
     1128                mem_avail_req--;
     1129       
     1130        if (mem_avail_req == 0) {
     1131                mem_avail_gen++;
     1132                condvar_broadcast(&mem_avail_cv);
     1133        }
    11081134        mutex_unlock(&mem_avail_mtx);
    1109 
    1110         interrupts_restore(ipl);
    11111135}
    11121136
     
    11161140 * increment frame reference count.
    11171141 *
    1118  * @param pfn           Frame number of the frame to be freed.
     1142 * @param pfn Frame number of the frame to be freed.
     1143 *
    11191144 */
    11201145void frame_reference_add(pfn_t pfn)
    11211146{
    1122         ipl_t ipl;
    1123         zone_t *zone;
    1124         frame_t *frame;
    1125 
    1126         ipl = interrupts_disable();
     1147        ipl_t ipl = interrupts_disable();
     1148        spinlock_lock(&zones.lock);
    11271149       
    11281150        /*
    11291151         * First, find host frame zone for addr.
    11301152         */
    1131         zone = find_zone_and_lock(pfn, NULL);
    1132         ASSERT(zone);
    1133        
    1134         frame = &zone->frames[pfn - zone->base];
    1135         frame->refcount++;
    1136        
    1137         spinlock_unlock(&zone->lock);
     1153        count_t znum = find_zone(pfn, NULL);
     1154       
     1155        ASSERT(znum != (count_t) -1);
     1156       
     1157        zones.info[znum].frames[pfn - zones.info[znum].base].refcount++;
     1158       
     1159        spinlock_unlock(&zones.lock);
    11381160        interrupts_restore(ipl);
    11391161}
     
    11421164void frame_mark_unavailable(pfn_t start, count_t count)
    11431165{
    1144         unsigned int i;
    1145         zone_t *zone;
    1146         unsigned int prefzone = 0;
    1147        
     1166        ipl_t ipl = interrupts_disable();
     1167        spinlock_lock(&zones.lock);
     1168       
     1169        count_t i;
    11481170        for (i = 0; i < count; i++) {
    1149                 zone = find_zone_and_lock(start + i, &prefzone);
    1150                 if (!zone) /* PFN not found */
     1171                count_t znum = find_zone(start + i, 0);
     1172                if (znum == (count_t) -1) /* PFN not found */
    11511173                        continue;
    1152                 zone_mark_unavailable(zone, start + i - zone->base);
    1153 
    1154                 spinlock_unlock(&zone->lock);
    1155         }
     1174               
     1175                zone_mark_unavailable(&zones.info[znum],
     1176                    start + i - zones.info[znum].base);
     1177        }
     1178       
     1179        spinlock_unlock(&zones.lock);
     1180        interrupts_restore(ipl);
    11561181}
    11571182
     
    11651190                condvar_initialize(&mem_avail_cv);
    11661191        }
     1192       
    11671193        /* Tell the architecture to create some memory */
    11681194        frame_arch_init();
     
    11791205                            SIZE2FRAMES(init.tasks[i].size));
    11801206                }
    1181 
     1207               
    11821208                if (ballocs.size)
    11831209                        frame_mark_unavailable(ADDR2PFN(KA2PA(ballocs.base)),
    11841210                            SIZE2FRAMES(ballocs.size));
    1185 
     1211               
    11861212                /* Black list first frame, as allocating NULL would
    1187                  * fail in some places */
     1213                 * fail in some places
     1214                 */
    11881215                frame_mark_unavailable(0, 1);
    11891216        }
    11901217}
    1191 
    11921218
    11931219/** Return total size of all zones. */
    11941220uint64_t zone_total_size(void)
    11951221{
    1196         zone_t *zone = NULL;
    1197         unsigned int i;
    1198         ipl_t ipl;
     1222        ipl_t ipl = interrupts_disable();
     1223        spinlock_lock(&zones.lock);
     1224       
    11991225        uint64_t total = 0;
    1200 
    1201         ipl = interrupts_disable();
    1202         spinlock_lock(&zones.lock);
    1203        
    1204         for (i = 0; i < zones.count; i++) {
    1205                 zone = zones.info[i];
    1206                 spinlock_lock(&zone->lock);
    1207                 total += (uint64_t) FRAMES2SIZE(zone->count);
    1208                 spinlock_unlock(&zone->lock);
    1209         }
     1226        count_t i;
     1227        for (i = 0; i < zones.count; i++)
     1228                total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    12101229       
    12111230        spinlock_unlock(&zones.lock);
     
    12181237void zone_print_list(void)
    12191238{
    1220         zone_t *zone = NULL;
    1221         unsigned int i;
    1222         ipl_t ipl;
    1223 
    1224 #ifdef __32_BITS__     
    1225         printf("#  base address free frames  busy frames\n");
    1226         printf("-- ------------ ------------ ------------\n");
     1239#ifdef __32_BITS__
     1240        printf("#  base address flags    free frames  busy frames\n");
     1241        printf("-- ------------ -------- ------------ ------------\n");
    12271242#endif
    12281243
    12291244#ifdef __64_BITS__
    1230         printf("#  base address         free frames  busy frames\n");
    1231         printf("-- -------------------- ------------ ------------\n");
     1245        printf("#  base address         flags    free frames  busy frames\n");
     1246        printf("-- -------------------- -------- ------------ ------------\n");
    12321247#endif
    12331248       
     
    12421257         * the listing).
    12431258         */
    1244 
    1245         for (i = 0; ; i++) {
    1246                 uintptr_t base;
    1247                 count_t free_count;
    1248                 count_t busy_count;
    1249 
    1250                 ipl = interrupts_disable();
     1259       
     1260        count_t i;
     1261        for (i = 0;; i++) {
     1262                ipl_t ipl = interrupts_disable();
    12511263                spinlock_lock(&zones.lock);
    12521264               
     
    12561268                        break;
    12571269                }
    1258 
    1259                 zone = zones.info[i];
    1260                 spinlock_lock(&zone->lock);
    1261 
    1262                 base = PFN2ADDR(zone->base);
    1263                 free_count = zone->free_count;
    1264                 busy_count = zone->busy_count;
    1265 
    1266                 spinlock_unlock(&zone->lock);
     1270               
     1271                uintptr_t base = PFN2ADDR(zones.info[i].base);
     1272                zone_flags_t flags = zones.info[i].flags;
     1273                count_t free_count = zones.info[i].free_count;
     1274                count_t busy_count = zones.info[i].busy_count;
    12671275               
    12681276                spinlock_unlock(&zones.lock);
    12691277                interrupts_restore(ipl);
    1270 
     1278               
     1279                bool available = zone_flags_available(flags);
     1280               
    12711281#ifdef __32_BITS__
    1272                 printf("%-2u   %10p %12" PRIc " %12" PRIc "\n", i, base,
    1273                     free_count, busy_count);
     1282                printf("%-2" PRIc "   %10p %c%c%c      ", i, base,
     1283                    available ? 'A' : ' ',
     1284                    (flags & ZONE_RESERVED) ? 'R' : ' ',
     1285                    (flags & ZONE_FIRMWARE) ? 'F' : ' ');
    12741286#endif
    1275 
     1287               
    12761288#ifdef __64_BITS__
    1277                 printf("%-2u   %18p %12" PRIc " %12" PRIc "\n", i, base,
    1278                     free_count, busy_count);
     1289                printf("%-2" PRIc "   %18p %c%c%c      ", i, base,
     1290                    available ? 'A' : ' ',
     1291                    (flags & ZONE_RESERVED) ? 'R' : ' ',
     1292                    (flags & ZONE_FIRMWARE) ? 'F' : ' ');
    12791293#endif
    12801294               
     1295                if (available)
     1296                        printf("%12" PRIc " %12" PRIc,
     1297                            free_count, busy_count);
     1298                printf("\n");
    12811299        }
    12821300}
     
    12841302/** Prints zone details.
    12851303 *
    1286  * @param num           Zone base address or zone number.
    1287  */
    1288 void zone_print_one(unsigned int num)
    1289 {
    1290         zone_t *zone = NULL;
    1291         ipl_t ipl;
    1292         unsigned int i;
    1293         uintptr_t base;
    1294         count_t count;
    1295         count_t busy_count;
    1296         count_t free_count;
    1297 
    1298         ipl = interrupts_disable();
     1304 * @param num Zone base address or zone number.
     1305 *
     1306 */
     1307void zone_print_one(count_t num)
     1308{
     1309        ipl_t ipl = interrupts_disable();
    12991310        spinlock_lock(&zones.lock);
    1300 
     1311        count_t znum = (count_t) -1;
     1312       
     1313        count_t i;
    13011314        for (i = 0; i < zones.count; i++) {
    1302                 if ((i == num) || (PFN2ADDR(zones.info[i]->base) == num)) {
    1303                         zone = zones.info[i];
     1315                if ((i == num) || (PFN2ADDR(zones.info[i].base) == num)) {
     1316                        znum = i;
    13041317                        break;
    13051318                }
    13061319        }
    1307         if (!zone) {
     1320       
     1321        if (znum == (count_t) -1) {
    13081322                spinlock_unlock(&zones.lock);
    13091323                interrupts_restore(ipl);
     
    13121326        }
    13131327       
    1314         spinlock_lock(&zone->lock);
    1315         base = PFN2ADDR(zone->base);
    1316         count = zone->count;
    1317         busy_count = zone->busy_count;
    1318         free_count = zone->free_count;
    1319         spinlock_unlock(&zone->lock);
     1328        uintptr_t base = PFN2ADDR(zones.info[i].base);
     1329        zone_flags_t flags = zones.info[i].flags;
     1330        count_t count = zones.info[i].count;
     1331        count_t free_count = zones.info[i].free_count;
     1332        count_t busy_count = zones.info[i].busy_count;
     1333       
    13201334        spinlock_unlock(&zones.lock);
    13211335        interrupts_restore(ipl);
    1322 
     1336       
     1337        bool available = zone_flags_available(flags);
     1338       
     1339        printf("Zone number:       %" PRIc "\n", znum);
    13231340        printf("Zone base address: %p\n", base);
    1324         printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
     1341        printf("Zone size:         %" PRIc " frames (%" PRIs " KiB)\n", count,
    13251342            SIZE2KB(FRAMES2SIZE(count)));
    1326         printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
    1327             busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
    1328         printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
    1329             free_count, SIZE2KB(FRAMES2SIZE(free_count)));
     1343        printf("Zone flags:        %c%c%c\n",
     1344            available ? 'A' : ' ',
     1345            (flags & ZONE_RESERVED) ? 'R' : ' ',
     1346            (flags & ZONE_FIRMWARE) ? 'F' : ' ');
     1347       
     1348        if (available) {
     1349                printf("Allocated space:   %" PRIc " frames (%" PRIs " KiB)\n",
     1350                    busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
     1351                printf("Available space:   %" PRIc " frames (%" PRIs " KiB)\n",
     1352                    free_count, SIZE2KB(FRAMES2SIZE(free_count)));
     1353        }
    13301354}
    13311355
    13321356/** @}
    13331357 */
    1334 
  • kernel/generic/src/mm/slab.c

    r6b1de7a r5f0f29ce  
    174174        size_t fsize;
    175175        unsigned int i;
    176         unsigned int zone = 0;
     176        count_t zone = 0;
    177177       
    178178        data = frame_alloc_generic(cache->order, FRAME_KA | flags, &zone);
Note: See TracChangeset for help on using the changeset viewer.