Ignore:
File:
1 edited

Legend:

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

    rc964521 r97bdb4a  
    3333/**
    3434 * @file
    35  * @brief       Address space related functions.
     35 * @brief Address space related functions.
    3636 *
    3737 * This file contains address space manipulation functions.
     
    8686 * Each architecture decides what functions will be used to carry out
    8787 * address space operations such as creating or locking page tables.
     88 *
    8889 */
    8990as_operations_t *as_operations = NULL;
     
    9192/**
    9293 * Slab for as_t objects.
     94 *
    9395 */
    9496static slab_cache_t *as_slab;
     
    100102 * - as->asid for each as of the as_t type
    101103 * - asids_allocated counter
     104 *
    102105 */
    103106SPINLOCK_INITIALIZE(asidlock);
     
    106109 * This list contains address spaces that are not active on any
    107110 * processor and that have valid ASID.
     111 *
    108112 */
    109113LIST_INITIALIZE(inactive_as_with_asid_head);
     
    112116as_t *AS_KERNEL = NULL;
    113117
    114 static int area_flags_to_page_flags(int);
    115 static as_area_t *find_area_and_lock(as_t *, uintptr_t);
    116 static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
    117 static void sh_info_remove_reference(share_info_t *);
    118 
    119 static int as_constructor(void *obj, int flags)
     118NO_TRACE static int as_constructor(void *obj, unsigned int flags)
    120119{
    121120        as_t *as = (as_t *) obj;
    122         int rc;
    123 
     121       
    124122        link_initialize(&as->inactive_as_with_asid_link);
    125123        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    126124       
    127         rc = as_constructor_arch(as, flags);
     125        int rc = as_constructor_arch(as, flags);
    128126       
    129127        return rc;
    130128}
    131129
    132 static int as_destructor(void *obj)
     130NO_TRACE static size_t as_destructor(void *obj)
    133131{
    134132        as_t *as = (as_t *) obj;
    135 
    136133        return as_destructor_arch(as);
    137134}
     
    141138{
    142139        as_arch_init();
    143 
     140       
    144141        as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
    145142            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
     
    157154/** Create address space.
    158155 *
    159  * @param flags         Flags that influence the way in wich the address space
    160  *                      is created.
    161  */
    162 as_t *as_create(int flags)
    163 {
    164         as_t *as;
    165 
    166         as = (as_t *) slab_alloc(as_slab, 0);
     156 * @param flags Flags that influence the way in wich the address
     157 *              space is created.
     158 *
     159 */
     160as_t *as_create(unsigned int flags)
     161{
     162        as_t *as = (as_t *) slab_alloc(as_slab, 0);
    167163        (void) as_create_arch(as, 0);
    168164       
     
    176172        atomic_set(&as->refcount, 0);
    177173        as->cpu_refcount = 0;
     174       
    178175#ifdef AS_PAGE_TABLE
    179176        as->genarch.page_table = page_table_create(flags);
     
    192189 * We know that we don't hold any spinlock.
    193190 *
    194  * @param as            Address space to be destroyed.
     191 * @param as Address space to be destroyed.
     192 *
    195193 */
    196194void as_destroy(as_t *as)
    197195{
    198         ipl_t ipl;
    199         bool cond;
    200196        DEADLOCK_PROBE_INIT(p_asidlock);
    201197
     
    214210         * disabled to prevent nested context switches. We also depend on the
    215211         * fact that so far no spinlocks are held.
     212         *
    216213         */
    217214        preemption_disable();
    218         ipl = interrupts_read();
     215        ipl_t ipl = interrupts_read();
     216       
    219217retry:
    220218        interrupts_disable();
     
    224222                goto retry;
    225223        }
    226         preemption_enable();    /* Interrupts disabled, enable preemption */
    227         if (as->asid != ASID_INVALID && as != AS_KERNEL) {
     224       
     225        /* Interrupts disabled, enable preemption */
     226        preemption_enable();
     227       
     228        if ((as->asid != ASID_INVALID) && (as != AS_KERNEL)) {
    228229                if (as->cpu_refcount == 0)
    229230                        list_remove(&as->inactive_as_with_asid_link);
     231               
    230232                asid_put(as->asid);
    231233        }
     234       
    232235        spinlock_unlock(&asidlock);
    233 
     236        interrupts_restore(ipl);
     237
     238       
    234239        /*
    235240         * Destroy address space areas of the address space.
    236241         * The B+tree must be walked carefully because it is
    237242         * also being destroyed.
    238          */     
    239         for (cond = true; cond; ) {
    240                 btree_node_t *node;
    241 
     243         *
     244         */
     245        bool cond = true;
     246        while (cond) {
    242247                ASSERT(!list_empty(&as->as_area_btree.leaf_head));
    243                 node = list_get_instance(as->as_area_btree.leaf_head.next,
     248               
     249                btree_node_t *node =
     250                    list_get_instance(as->as_area_btree.leaf_head.next,
    244251                    btree_node_t, leaf_link);
    245 
    246                 if ((cond = node->keys)) {
     252               
     253                if ((cond = node->keys))
    247254                        as_area_destroy(as, node->key[0]);
    248                 }
    249         }
    250 
     255        }
     256       
    251257        btree_destroy(&as->as_area_btree);
     258       
    252259#ifdef AS_PAGE_TABLE
    253260        page_table_destroy(as->genarch.page_table);
     
    255262        page_table_destroy(NULL);
    256263#endif
    257 
    258         interrupts_restore(ipl);
    259 
     264       
    260265        slab_free(as_slab, as);
    261266}
     
    266271 * space.
    267272 *
    268  * @param a             Address space to be held.
    269  */
    270 void as_hold(as_t *as)
     273 * @param as Address space to be held.
     274 *
     275 */
     276NO_TRACE void as_hold(as_t *as)
    271277{
    272278        atomic_inc(&as->refcount);
     
    278284 * space.
    279285 *
    280  * @param a             Address space to be released.
    281  */
    282 void as_release(as_t *as)
     286 * @param asAddress space to be released.
     287 *
     288 */
     289NO_TRACE void as_release(as_t *as)
    283290{
    284291        if (atomic_predec(&as->refcount) == 0)
     
    286293}
    287294
     295/** Check area conflicts with other areas.
     296 *
     297 * @param as         Address space.
     298 * @param va         Starting virtual address of the area being tested.
     299 * @param size       Size of the area being tested.
     300 * @param avoid_area Do not touch this area.
     301 *
     302 * @return True if there is no conflict, false otherwise.
     303 *
     304 */
     305NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
     306    as_area_t *avoid_area)
     307{
     308        ASSERT(mutex_locked(&as->lock));
     309       
     310        /*
     311         * We don't want any area to have conflicts with NULL page.
     312         *
     313         */
     314        if (overlaps(va, size, NULL, PAGE_SIZE))
     315                return false;
     316       
     317        /*
     318         * The leaf node is found in O(log n), where n is proportional to
     319         * the number of address space areas belonging to as.
     320         * The check for conflicts is then attempted on the rightmost
     321         * record in the left neighbour, the leftmost record in the right
     322         * neighbour and all records in the leaf node itself.
     323         *
     324         */
     325        btree_node_t *leaf;
     326        as_area_t *area =
     327            (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     328        if (area) {
     329                if (area != avoid_area)
     330                        return false;
     331        }
     332       
     333        /* First, check the two border cases. */
     334        btree_node_t *node =
     335            btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     336        if (node) {
     337                area = (as_area_t *) node->value[node->keys - 1];
     338               
     339                mutex_lock(&area->lock);
     340               
     341                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     342                        mutex_unlock(&area->lock);
     343                        return false;
     344                }
     345               
     346                mutex_unlock(&area->lock);
     347        }
     348       
     349        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
     350        if (node) {
     351                area = (as_area_t *) node->value[0];
     352               
     353                mutex_lock(&area->lock);
     354               
     355                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     356                        mutex_unlock(&area->lock);
     357                        return false;
     358                }
     359               
     360                mutex_unlock(&area->lock);
     361        }
     362       
     363        /* Second, check the leaf node. */
     364        btree_key_t i;
     365        for (i = 0; i < leaf->keys; i++) {
     366                area = (as_area_t *) leaf->value[i];
     367               
     368                if (area == avoid_area)
     369                        continue;
     370               
     371                mutex_lock(&area->lock);
     372               
     373                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     374                        mutex_unlock(&area->lock);
     375                        return false;
     376                }
     377               
     378                mutex_unlock(&area->lock);
     379        }
     380       
     381        /*
     382         * So far, the area does not conflict with other areas.
     383         * Check if it doesn't conflict with kernel address space.
     384         *
     385         */
     386        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
     387                return !overlaps(va, size,
     388                    KERNEL_ADDRESS_SPACE_START,
     389                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     390        }
     391       
     392        return true;
     393}
     394
    288395/** Create address space area of common attributes.
    289396 *
    290397 * The created address space area is added to the target address space.
    291398 *
    292  * @param as            Target address space.
    293  * @param flags         Flags of the area memory.
    294  * @param size          Size of area.
    295  * @param base          Base address of area.
    296  * @param attrs         Attributes of the area.
    297  * @param backend       Address space area backend. NULL if no backend is used.
    298  * @param backend_data  NULL or a pointer to an array holding two void *.
    299  *
    300  * @return              Address space area on success or NULL on failure.
    301  */
    302 as_area_t *
    303 as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs,
    304     mem_backend_t *backend, mem_backend_data_t *backend_data)
    305 {
    306         ipl_t ipl;
    307         as_area_t *a;
    308        
     399 * @param as           Target address space.
     400 * @param flags        Flags of the area memory.
     401 * @param size         Size of area.
     402 * @param base         Base address of area.
     403 * @param attrs        Attributes of the area.
     404 * @param backend      Address space area backend. NULL if no backend is used.
     405 * @param backend_data NULL or a pointer to an array holding two void *.
     406 *
     407 * @return Address space area on success or NULL on failure.
     408 *
     409 */
     410as_area_t *as_area_create(as_t *as, unsigned int flags, size_t size,
     411    uintptr_t base, unsigned int attrs, mem_backend_t *backend,
     412    mem_backend_data_t *backend_data)
     413{
    309414        if (base % PAGE_SIZE)
    310415                return NULL;
    311 
     416       
    312417        if (!size)
    313418                return NULL;
    314 
     419       
    315420        /* Writeable executable areas are not supported. */
    316421        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    317422                return NULL;
    318423       
    319         ipl = interrupts_disable();
    320424        mutex_lock(&as->lock);
    321425       
    322426        if (!check_area_conflicts(as, base, size, NULL)) {
    323427                mutex_unlock(&as->lock);
    324                 interrupts_restore(ipl);
    325428                return NULL;
    326429        }
    327430       
    328         a = (as_area_t *) malloc(sizeof(as_area_t), 0);
    329 
    330         mutex_initialize(&a->lock, MUTEX_PASSIVE);
    331        
    332         a->as = as;
    333         a->flags = flags;
    334         a->attributes = attrs;
    335         a->pages = SIZE2FRAMES(size);
    336         a->base = base;
    337         a->sh_info = NULL;
    338         a->backend = backend;
     431        as_area_t *area = (as_area_t *) malloc(sizeof(as_area_t), 0);
     432       
     433        mutex_initialize(&area->lock, MUTEX_PASSIVE);
     434       
     435        area->as = as;
     436        area->flags = flags;
     437        area->attributes = attrs;
     438        area->pages = SIZE2FRAMES(size);
     439        area->base = base;
     440        area->sh_info = NULL;
     441        area->backend = backend;
     442       
    339443        if (backend_data)
    340                 a->backend_data = *backend_data;
     444                area->backend_data = *backend_data;
    341445        else
    342                 memsetb(&a->backend_data, sizeof(a->backend_data), 0);
    343 
    344         btree_create(&a->used_space);
    345        
    346         btree_insert(&as->as_area_btree, base, (void *) a, NULL);
    347 
     446                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
     447       
     448        btree_create(&area->used_space);
     449        btree_insert(&as->as_area_btree, base, (void *) area, NULL);
     450       
    348451        mutex_unlock(&as->lock);
    349         interrupts_restore(ipl);
    350 
    351         return a;
     452       
     453        return area;
     454}
     455
     456/** Find address space area and lock it.
     457 *
     458 * @param as Address space.
     459 * @param va Virtual address.
     460 *
     461 * @return Locked address space area containing va on success or
     462 *         NULL on failure.
     463 *
     464 */
     465NO_TRACE static as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
     466{
     467        ASSERT(mutex_locked(&as->lock));
     468       
     469        btree_node_t *leaf;
     470        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     471        if (area) {
     472                /* va is the base address of an address space area */
     473                mutex_lock(&area->lock);
     474                return area;
     475        }
     476       
     477        /*
     478         * Search the leaf node and the righmost record of its left neighbour
     479         * to find out whether this is a miss or va belongs to an address
     480         * space area found there.
     481         *
     482         */
     483       
     484        /* First, search the leaf node itself. */
     485        btree_key_t i;
     486       
     487        for (i = 0; i < leaf->keys; i++) {
     488                area = (as_area_t *) leaf->value[i];
     489               
     490                mutex_lock(&area->lock);
     491               
     492                if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     493                        return area;
     494               
     495                mutex_unlock(&area->lock);
     496        }
     497       
     498        /*
     499         * Second, locate the left neighbour and test its last record.
     500         * Because of its position in the B+tree, it must have base < va.
     501         *
     502         */
     503        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     504        if (lnode) {
     505                area = (as_area_t *) lnode->value[lnode->keys - 1];
     506               
     507                mutex_lock(&area->lock);
     508               
     509                if (va < area->base + area->pages * PAGE_SIZE)
     510                        return area;
     511               
     512                mutex_unlock(&area->lock);
     513        }
     514       
     515        return NULL;
    352516}
    353517
    354518/** Find address space area and change it.
    355519 *
    356  * @param as            Address space.
    357  * @param address       Virtual address belonging to the area to be changed.
    358  *                      Must be page-aligned.
    359  * @param size          New size of the virtual memory block starting at
    360  *                      address.
    361  * @param flags         Flags influencing the remap operation. Currently unused.
    362  *
    363  * @return              Zero on success or a value from @ref errno.h otherwise.
    364  */
    365 int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags)
    366 {
    367         as_area_t *area;
    368         ipl_t ipl;
    369         size_t pages;
    370        
    371         ipl = interrupts_disable();
     520 * @param as      Address space.
     521 * @param address Virtual address belonging to the area to be changed.
     522 *                Must be page-aligned.
     523 * @param size    New size of the virtual memory block starting at
     524 *                address.
     525 * @param flags   Flags influencing the remap operation. Currently unused.
     526 *
     527 * @return Zero on success or a value from @ref errno.h otherwise.
     528 *
     529 */
     530int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags)
     531{
    372532        mutex_lock(&as->lock);
    373533       
    374534        /*
    375535         * Locate the area.
    376          */
    377         area = find_area_and_lock(as, address);
     536         *
     537         */
     538        as_area_t *area = find_area_and_lock(as, address);
    378539        if (!area) {
    379540                mutex_unlock(&as->lock);
    380                 interrupts_restore(ipl);
    381541                return ENOENT;
    382542        }
    383 
     543       
    384544        if (area->backend == &phys_backend) {
    385545                /*
    386546                 * Remapping of address space areas associated
    387547                 * with memory mapped devices is not supported.
     548                 *
    388549                 */
    389550                mutex_unlock(&area->lock);
    390551                mutex_unlock(&as->lock);
    391                 interrupts_restore(ipl);
    392552                return ENOTSUP;
    393553        }
     554       
    394555        if (area->sh_info) {
    395556                /*
    396                  * Remapping of shared address space areas 
     557                 * Remapping of shared address space areas
    397558                 * is not supported.
     559                 *
    398560                 */
    399561                mutex_unlock(&area->lock);
    400562                mutex_unlock(&as->lock);
    401                 interrupts_restore(ipl);
    402563                return ENOTSUP;
    403564        }
    404 
    405         pages = SIZE2FRAMES((address - area->base) + size);
     565       
     566        size_t pages = SIZE2FRAMES((address - area->base) + size);
    406567        if (!pages) {
    407568                /*
    408569                 * Zero size address space areas are not allowed.
     570                 *
    409571                 */
    410572                mutex_unlock(&area->lock);
    411573                mutex_unlock(&as->lock);
    412                 interrupts_restore(ipl);
    413574                return EPERM;
    414575        }
    415576       
    416577        if (pages < area->pages) {
    417                 bool cond;
    418578                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    419 
     579               
    420580                /*
    421581                 * Shrinking the area.
    422582                 * No need to check for overlaps.
    423                  */
    424 
     583                 *
     584                 */
     585               
    425586                page_table_lock(as, false);
    426 
     587               
    427588                /*
    428589                 * Start TLB shootdown sequence.
    429                  */
    430                 tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
    431                     pages * PAGE_SIZE, area->pages - pages);
    432 
     590                 *
     591                 */
     592                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
     593                    area->base + pages * PAGE_SIZE, area->pages - pages);
     594               
    433595                /*
    434596                 * Remove frames belonging to used space starting from
     
    437599                 * is also the right way to remove part of the used_space
    438600                 * B+tree leaf list.
    439                  */             
    440                 for (cond = true; cond;) {
    441                         btree_node_t *node;
    442                
     601                 *
     602                 */
     603                bool cond = true;
     604                while (cond) {
    443605                        ASSERT(!list_empty(&area->used_space.leaf_head));
    444                         node =
     606                       
     607                        btree_node_t *node =
    445608                            list_get_instance(area->used_space.leaf_head.prev,
    446609                            btree_node_t, leaf_link);
     610                       
    447611                        if ((cond = (bool) node->keys)) {
    448                                 uintptr_t b = node->key[node->keys - 1];
    449                                 size_t c =
     612                                uintptr_t ptr = node->key[node->keys - 1];
     613                                size_t size =
    450614                                    (size_t) node->value[node->keys - 1];
    451                                 unsigned int i = 0;
    452                        
    453                                 if (overlaps(b, c * PAGE_SIZE, area->base,
     615                                size_t i = 0;
     616                               
     617                                if (overlaps(ptr, size * PAGE_SIZE, area->base,
    454618                                    pages * PAGE_SIZE)) {
    455619                                       
    456                                         if (b + c * PAGE_SIZE <= start_free) {
     620                                        if (ptr + size * PAGE_SIZE <= start_free) {
    457621                                                /*
    458622                                                 * The whole interval fits
    459623                                                 * completely in the resized
    460624                                                 * address space area.
     625                                                 *
    461626                                                 */
    462627                                                break;
    463628                                        }
    464                
     629                                       
    465630                                        /*
    466631                                         * Part of the interval corresponding
    467632                                         * to b and c overlaps with the resized
    468633                                         * address space area.
     634                                         *
    469635                                         */
    470                
    471                                         cond = false;   /* we are almost done */
    472                                         i = (start_free - b) >> PAGE_WIDTH;
     636                                       
     637                                        /* We are almost done */
     638                                        cond = false;
     639                                        i = (start_free - ptr) >> PAGE_WIDTH;
    473640                                        if (!used_space_remove(area, start_free,
    474                                             c - i))
    475                                                 panic("Cannot remove used "
    476                                                     "space.");
     641                                            size - i))
     642                                                panic("Cannot remove used space.");
    477643                                } else {
    478644                                        /*
     
    480646                                         * completely removed.
    481647                                         */
    482                                         if (!used_space_remove(area, b, c))
    483                                                 panic("Cannot remove used "
    484                                                     "space.");
     648                                        if (!used_space_remove(area, ptr, size))
     649                                                panic("Cannot remove used space.");
    485650                                }
    486                        
    487                                 for (; i < c; i++) {
    488                                         pte_t *pte;
    489                        
    490                                         pte = page_mapping_find(as, b +
     651                               
     652                                for (; i < size; i++) {
     653                                        pte_t *pte = page_mapping_find(as, ptr +
    491654                                            i * PAGE_SIZE);
    492                                         ASSERT(pte && PTE_VALID(pte) &&
    493                                             PTE_PRESENT(pte));
    494                                         if (area->backend &&
    495                                             area->backend->frame_free) {
     655                                       
     656                                        ASSERT(pte);
     657                                        ASSERT(PTE_VALID(pte));
     658                                        ASSERT(PTE_PRESENT(pte));
     659                                       
     660                                        if ((area->backend) &&
     661                                            (area->backend->frame_free)) {
    496662                                                area->backend->frame_free(area,
    497                                                     b + i * PAGE_SIZE,
     663                                                    ptr + i * PAGE_SIZE,
    498664                                                    PTE_GET_FRAME(pte));
    499665                                        }
    500                                         page_mapping_remove(as, b +
     666                                       
     667                                        page_mapping_remove(as, ptr +
    501668                                            i * PAGE_SIZE);
    502669                                }
    503670                        }
    504671                }
    505 
     672               
    506673                /*
    507674                 * Finish TLB shootdown sequence.
    508                  */
    509 
     675                 *
     676                 */
     677               
    510678                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    511679                    area->pages - pages);
    512 
     680               
    513681                /*
    514682                 * Invalidate software translation caches (e.g. TSB on sparc64).
     683                 *
    515684                 */
    516685                as_invalidate_translation_cache(as, area->base +
    517686                    pages * PAGE_SIZE, area->pages - pages);
    518                 tlb_shootdown_finalize();
    519 
     687                tlb_shootdown_finalize(ipl);
     688               
    520689                page_table_unlock(as, false);
    521                
    522690        } else {
    523691                /*
    524692                 * Growing the area.
    525693                 * Check for overlaps with other address space areas.
     694                 *
    526695                 */
    527696                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    528697                    area)) {
    529698                        mutex_unlock(&area->lock);
    530                         mutex_unlock(&as->lock);               
    531                         interrupts_restore(ipl);
     699                        mutex_unlock(&as->lock);
    532700                        return EADDRNOTAVAIL;
    533701                }
    534         } 
    535 
     702        }
     703       
    536704        area->pages = pages;
    537705       
    538706        mutex_unlock(&area->lock);
    539707        mutex_unlock(&as->lock);
    540         interrupts_restore(ipl);
    541 
     708       
    542709        return 0;
    543710}
    544711
     712/** Remove reference to address space area share info.
     713 *
     714 * If the reference count drops to 0, the sh_info is deallocated.
     715 *
     716 * @param sh_info Pointer to address space area share info.
     717 *
     718 */
     719NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)
     720{
     721        bool dealloc = false;
     722       
     723        mutex_lock(&sh_info->lock);
     724        ASSERT(sh_info->refcount);
     725       
     726        if (--sh_info->refcount == 0) {
     727                dealloc = true;
     728                link_t *cur;
     729               
     730                /*
     731                 * Now walk carefully the pagemap B+tree and free/remove
     732                 * reference from all frames found there.
     733                 */
     734                for (cur = sh_info->pagemap.leaf_head.next;
     735                    cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
     736                        btree_node_t *node
     737                            = list_get_instance(cur, btree_node_t, leaf_link);
     738                        btree_key_t i;
     739                       
     740                        for (i = 0; i < node->keys; i++)
     741                                frame_free((uintptr_t) node->value[i]);
     742                }
     743               
     744        }
     745        mutex_unlock(&sh_info->lock);
     746       
     747        if (dealloc) {
     748                btree_destroy(&sh_info->pagemap);
     749                free(sh_info);
     750        }
     751}
     752
    545753/** Destroy address space area.
    546754 *
    547  * @param as            Address space.
    548  * @param address       Address within the area to be deleted.
    549  *
    550  * @return              Zero on success or a value from @ref errno.h on failure.
     755 * @param as      Address space.
     756 * @param address Address within the area to be deleted.
     757 *
     758 * @return Zero on success or a value from @ref errno.h on failure.
     759 *
    551760 */
    552761int as_area_destroy(as_t *as, uintptr_t address)
    553762{
    554         as_area_t *area;
    555         uintptr_t base;
    556         link_t *cur;
    557         ipl_t ipl;
    558 
    559         ipl = interrupts_disable();
    560763        mutex_lock(&as->lock);
    561 
    562         area = find_area_and_lock(as, address);
     764       
     765        as_area_t *area = find_area_and_lock(as, address);
    563766        if (!area) {
    564767                mutex_unlock(&as->lock);
    565                 interrupts_restore(ipl);
    566768                return ENOENT;
    567769        }
    568 
    569         base = area->base;
    570 
     770       
     771        uintptr_t base = area->base;
     772       
    571773        page_table_lock(as, false);
    572 
     774       
    573775        /*
    574776         * Start TLB shootdown sequence.
    575777         */
    576         tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    577 
     778        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     779            area->pages);
     780       
    578781        /*
    579782         * Visit only the pages mapped by used_space B+tree.
    580783         */
     784        link_t *cur;
    581785        for (cur = area->used_space.leaf_head.next;
    582786            cur != &area->used_space.leaf_head; cur = cur->next) {
    583787                btree_node_t *node;
    584                 unsigned int i;
     788                btree_key_t i;
    585789               
    586790                node = list_get_instance(cur, btree_node_t, leaf_link);
    587791                for (i = 0; i < node->keys; i++) {
    588                         uintptr_t b = node->key[i];
    589                         size_t j;
    590                         pte_t *pte;
     792                        uintptr_t ptr = node->key[i];
     793                        size_t size;
    591794                       
    592                         for (j = 0; j < (size_t) node->value[i]; j++) {
    593                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    594                                 ASSERT(pte && PTE_VALID(pte) &&
    595                                     PTE_PRESENT(pte));
    596                                 if (area->backend &&
    597                                     area->backend->frame_free) {
    598                                         area->backend->frame_free(area, b +
    599                                             j * PAGE_SIZE, PTE_GET_FRAME(pte));
     795                        for (size = 0; size < (size_t) node->value[i]; size++) {
     796                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     797                               
     798                                ASSERT(pte);
     799                                ASSERT(PTE_VALID(pte));
     800                                ASSERT(PTE_PRESENT(pte));
     801                               
     802                                if ((area->backend) &&
     803                                    (area->backend->frame_free)) {
     804                                        area->backend->frame_free(area,
     805                                            ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
    600806                                }
    601                                 page_mapping_remove(as, b + j * PAGE_SIZE);                             
     807                               
     808                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    602809                        }
    603810                }
    604811        }
    605 
     812       
    606813        /*
    607814         * Finish TLB shootdown sequence.
    608          */
    609 
     815         *
     816         */
     817       
    610818        tlb_invalidate_pages(as->asid, area->base, area->pages);
    611 
     819       
    612820        /*
    613821         * Invalidate potential software translation caches (e.g. TSB on
    614822         * sparc64).
     823         *
    615824         */
    616825        as_invalidate_translation_cache(as, area->base, area->pages);
    617         tlb_shootdown_finalize();
    618 
     826        tlb_shootdown_finalize(ipl);
     827       
    619828        page_table_unlock(as, false);
    620829       
    621830        btree_destroy(&area->used_space);
    622 
     831       
    623832        area->attributes |= AS_AREA_ATTR_PARTIAL;
    624833       
    625834        if (area->sh_info)
    626835                sh_info_remove_reference(area->sh_info);
    627                
     836       
    628837        mutex_unlock(&area->lock);
    629 
     838       
    630839        /*
    631840         * Remove the empty area from address space.
     841         *
    632842         */
    633843        btree_remove(&as->as_area_btree, base, NULL);
     
    636846       
    637847        mutex_unlock(&as->lock);
    638         interrupts_restore(ipl);
    639848        return 0;
    640849}
     
    647856 * sh_info of the source area. The process of duplicating the
    648857 * mapping is done through the backend share function.
    649  * 
    650  * @param src_as        Pointer to source address space.
    651  * @param src_base      Base address of the source address space area.
    652  * @param acc_size      Expected size of the source area.
    653  * @param dst_as        Pointer to destination address space.
    654  * @param dst_base      Target base address.
     858 *
     859 * @param src_as         Pointer to source address space.
     860 * @param src_base       Base address of the source address space area.
     861 * @param acc_size       Expected size of the source area.
     862 * @param dst_as         Pointer to destination address space.
     863 * @param dst_base       Target base address.
    655864 * @param dst_flags_mask Destination address space area flags mask.
    656865 *
    657  * @return              Zero on success or ENOENT if there is no such task or if
    658  *                      there is no such address space area, EPERM if there was
    659  *                      a problem in accepting the area or ENOMEM if there was a
    660  *                      problem in allocating destination address space area.
    661  *                      ENOTSUP is returned if the address space area backend
    662  *                      does not support sharing.
     866 * @return Zero on success.
     867 * @return ENOENT if there is no such task or such address space.
     868 * @return EPERM if there was a problem in accepting the area.
     869 * @return ENOMEM if there was a problem in allocating destination
     870 *         address space area.
     871 * @return ENOTSUP if the address space area backend does not support
     872 *         sharing.
     873 *
    663874 */
    664875int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
    665     as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
    666 {
    667         ipl_t ipl;
    668         int src_flags;
    669         size_t src_size;
    670         as_area_t *src_area, *dst_area;
    671         share_info_t *sh_info;
    672         mem_backend_t *src_backend;
    673         mem_backend_data_t src_backend_data;
    674        
    675         ipl = interrupts_disable();
     876    as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
     877{
    676878        mutex_lock(&src_as->lock);
    677         src_area = find_area_and_lock(src_as, src_base);
     879        as_area_t *src_area = find_area_and_lock(src_as, src_base);
    678880        if (!src_area) {
    679881                /*
    680882                 * Could not find the source address space area.
     883                 *
    681884                 */
    682885                mutex_unlock(&src_as->lock);
    683                 interrupts_restore(ipl);
    684886                return ENOENT;
    685887        }
    686 
    687         if (!src_area->backend || !src_area->backend->share) {
     888       
     889        if ((!src_area->backend) || (!src_area->backend->share)) {
    688890                /*
    689891                 * There is no backend or the backend does not
    690892                 * know how to share the area.
     893                 *
    691894                 */
    692895                mutex_unlock(&src_area->lock);
    693896                mutex_unlock(&src_as->lock);
    694                 interrupts_restore(ipl);
    695897                return ENOTSUP;
    696898        }
    697899       
    698         src_size = src_area->pages * PAGE_SIZE;
    699         src_flags = src_area->flags;
    700         src_backend = src_area->backend;
    701         src_backend_data = src_area->backend_data;
    702 
     900        size_t src_size = src_area->pages * PAGE_SIZE;
     901        unsigned int src_flags = src_area->flags;
     902        mem_backend_t *src_backend = src_area->backend;
     903        mem_backend_data_t src_backend_data = src_area->backend_data;
     904       
    703905        /* Share the cacheable flag from the original mapping */
    704906        if (src_flags & AS_AREA_CACHEABLE)
    705907                dst_flags_mask |= AS_AREA_CACHEABLE;
    706 
    707         if (src_size != acc_size ||
    708             (src_flags & dst_flags_mask) != dst_flags_mask) {
     908       
     909        if ((src_size != acc_size) ||
     910            ((src_flags & dst_flags_mask) != dst_flags_mask)) {
    709911                mutex_unlock(&src_area->lock);
    710912                mutex_unlock(&src_as->lock);
    711                 interrupts_restore(ipl);
    712913                return EPERM;
    713914        }
    714 
     915       
    715916        /*
    716917         * Now we are committed to sharing the area.
    717918         * First, prepare the area for sharing.
    718919         * Then it will be safe to unlock it.
    719          */
    720         sh_info = src_area->sh_info;
     920         *
     921         */
     922        share_info_t *sh_info = src_area->sh_info;
    721923        if (!sh_info) {
    722924                sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
     
    725927                btree_create(&sh_info->pagemap);
    726928                src_area->sh_info = sh_info;
     929               
    727930                /*
    728931                 * Call the backend to setup sharing.
     932                 *
    729933                 */
    730934                src_area->backend->share(src_area);
     
    734938                mutex_unlock(&sh_info->lock);
    735939        }
    736 
     940       
    737941        mutex_unlock(&src_area->lock);
    738942        mutex_unlock(&src_as->lock);
    739 
     943       
    740944        /*
    741945         * Create copy of the source address space area.
     
    745949         * The flags of the source area are masked against dst_flags_mask
    746950         * to support sharing in less privileged mode.
    747          */
    748         dst_area = as_area_create(dst_as, dst_flags_mask, src_size, dst_base,
    749             AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
     951         *
     952         */
     953        as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
     954            dst_base, AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
    750955        if (!dst_area) {
    751956                /*
     
    754959                sh_info_remove_reference(sh_info);
    755960               
    756                 interrupts_restore(ipl);
    757961                return ENOMEM;
    758962        }
    759 
     963       
    760964        /*
    761965         * Now the destination address space area has been
    762966         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    763967         * attribute and set the sh_info.
    764          */     
    765         mutex_lock(&dst_as->lock);     
     968         *
     969         */
     970        mutex_lock(&dst_as->lock);
    766971        mutex_lock(&dst_area->lock);
    767972        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
    768973        dst_area->sh_info = sh_info;
    769974        mutex_unlock(&dst_area->lock);
    770         mutex_unlock(&dst_as->lock);   
    771 
    772         interrupts_restore(ipl);
     975        mutex_unlock(&dst_as->lock);
    773976       
    774977        return 0;
     
    777980/** Check access mode for address space area.
    778981 *
    779  * The address space area must be locked prior to this call.
    780  *
    781  * @param area          Address space area.
    782  * @param access        Access mode.
    783  *
    784  * @return              False if access violates area's permissions, true
    785  *                      otherwise.
    786  */
    787 bool as_area_check_access(as_area_t *area, pf_access_t access)
     982 * @param area   Address space area.
     983 * @param access Access mode.
     984 *
     985 * @return False if access violates area's permissions, true
     986 *         otherwise.
     987 *
     988 */
     989NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
    788990{
    789991        int flagmap[] = {
     
    793995        };
    794996
     997        ASSERT(mutex_locked(&area->lock));
     998       
    795999        if (!(area->flags & flagmap[access]))
    7961000                return false;
    7971001       
    7981002        return true;
     1003}
     1004
     1005/** Convert address space area flags to page flags.
     1006 *
     1007 * @param aflags Flags of some address space area.
     1008 *
     1009 * @return Flags to be passed to page_mapping_insert().
     1010 *
     1011 */
     1012NO_TRACE static unsigned int area_flags_to_page_flags(unsigned int aflags)
     1013{
     1014        unsigned int flags = PAGE_USER | PAGE_PRESENT;
     1015       
     1016        if (aflags & AS_AREA_READ)
     1017                flags |= PAGE_READ;
     1018               
     1019        if (aflags & AS_AREA_WRITE)
     1020                flags |= PAGE_WRITE;
     1021       
     1022        if (aflags & AS_AREA_EXEC)
     1023                flags |= PAGE_EXEC;
     1024       
     1025        if (aflags & AS_AREA_CACHEABLE)
     1026                flags |= PAGE_CACHEABLE;
     1027       
     1028        return flags;
    7991029}
    8001030
     
    8131043 *
    8141044 */
    815 int as_area_change_flags(as_t *as, int flags, uintptr_t address)
    816 {
    817         as_area_t *area;
    818         link_t *cur;
    819         ipl_t ipl;
    820         int page_flags;
    821         uintptr_t *old_frame;
    822         size_t frame_idx;
    823         size_t used_pages;
    824        
     1045int as_area_change_flags(as_t *as, unsigned int flags, uintptr_t address)
     1046{
    8251047        /* Flags for the new memory mapping */
    826         page_flags = area_flags_to_page_flags(flags);
    827 
    828         ipl = interrupts_disable();
     1048        unsigned int page_flags = area_flags_to_page_flags(flags);
     1049       
    8291050        mutex_lock(&as->lock);
    830 
    831         area = find_area_and_lock(as, address);
     1051       
     1052        as_area_t *area = find_area_and_lock(as, address);
    8321053        if (!area) {
    8331054                mutex_unlock(&as->lock);
    834                 interrupts_restore(ipl);
    8351055                return ENOENT;
    8361056        }
    837 
     1057       
    8381058        if ((area->sh_info) || (area->backend != &anon_backend)) {
    8391059                /* Copying shared areas not supported yet */
     
    8411061                mutex_unlock(&area->lock);
    8421062                mutex_unlock(&as->lock);
    843                 interrupts_restore(ipl);
    8441063                return ENOTSUP;
    8451064        }
    846 
     1065       
    8471066        /*
    8481067         * Compute total number of used pages in the used_space B+tree
    849          */
    850         used_pages = 0;
    851 
     1068         *
     1069         */
     1070        size_t used_pages = 0;
     1071        link_t *cur;
     1072       
    8521073        for (cur = area->used_space.leaf_head.next;
    8531074            cur != &area->used_space.leaf_head; cur = cur->next) {
    854                 btree_node_t *node;
    855                 unsigned int i;
    856                
    857                 node = list_get_instance(cur, btree_node_t, leaf_link);
    858                 for (i = 0; i < node->keys; i++) {
     1075                btree_node_t *node
     1076                    = list_get_instance(cur, btree_node_t, leaf_link);
     1077                btree_key_t i;
     1078               
     1079                for (i = 0; i < node->keys; i++)
    8591080                        used_pages += (size_t) node->value[i];
    860                 }
    861         }
    862 
     1081        }
     1082       
    8631083        /* An array for storing frame numbers */
    864         old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    865 
     1084        uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     1085       
    8661086        page_table_lock(as, false);
    867 
     1087       
    8681088        /*
    8691089         * Start TLB shootdown sequence.
    870          */
    871         tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    872 
     1090         *
     1091         */
     1092        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     1093            area->pages);
     1094       
    8731095        /*
    8741096         * Remove used pages from page tables and remember their frame
    8751097         * numbers.
    876          */
    877         frame_idx = 0;
    878 
     1098         *
     1099         */
     1100        size_t frame_idx = 0;
     1101       
    8791102        for (cur = area->used_space.leaf_head.next;
    8801103            cur != &area->used_space.leaf_head; cur = cur->next) {
    881                 btree_node_t *node;
    882                 unsigned int i;
    883                
    884                 node = list_get_instance(cur, btree_node_t, leaf_link);
     1104                btree_node_t *node
     1105                    = list_get_instance(cur, btree_node_t, leaf_link);
     1106                btree_key_t i;
     1107               
    8851108                for (i = 0; i < node->keys; i++) {
    886                         uintptr_t b = node->key[i];
    887                         size_t j;
    888                         pte_t *pte;
     1109                        uintptr_t ptr = node->key[i];
     1110                        size_t size;
    8891111                       
    890                         for (j = 0; j < (size_t) node->value[i]; j++) {
    891                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    892                                 ASSERT(pte && PTE_VALID(pte) &&
    893                                     PTE_PRESENT(pte));
     1112                        for (size = 0; size < (size_t) node->value[i]; size++) {
     1113                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     1114                               
     1115                                ASSERT(pte);
     1116                                ASSERT(PTE_VALID(pte));
     1117                                ASSERT(PTE_PRESENT(pte));
     1118                               
    8941119                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
    895 
     1120                               
    8961121                                /* Remove old mapping */
    897                                 page_mapping_remove(as, b + j * PAGE_SIZE);
     1122                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    8981123                        }
    8991124                }
    9001125        }
    901 
     1126       
    9021127        /*
    9031128         * Finish TLB shootdown sequence.
    904          */
    905 
     1129         *
     1130         */
     1131       
    9061132        tlb_invalidate_pages(as->asid, area->base, area->pages);
    9071133       
     
    9091135         * Invalidate potential software translation caches (e.g. TSB on
    9101136         * sparc64).
     1137         *
    9111138         */
    9121139        as_invalidate_translation_cache(as, area->base, area->pages);
    913         tlb_shootdown_finalize();
    914 
     1140        tlb_shootdown_finalize(ipl);
     1141       
    9151142        page_table_unlock(as, false);
    916 
     1143       
    9171144        /*
    9181145         * Set the new flags.
    9191146         */
    9201147        area->flags = flags;
    921 
     1148       
    9221149        /*
    9231150         * Map pages back in with new flags. This step is kept separate
     
    9261153         */
    9271154        frame_idx = 0;
    928 
     1155       
    9291156        for (cur = area->used_space.leaf_head.next;
    9301157            cur != &area->used_space.leaf_head; cur = cur->next) {
    931                 btree_node_t *node;
    932                 unsigned int i;
    933                
    934                 node = list_get_instance(cur, btree_node_t, leaf_link);
     1158                btree_node_t *node
     1159                    = list_get_instance(cur, btree_node_t, leaf_link);
     1160                btree_key_t i;
     1161               
    9351162                for (i = 0; i < node->keys; i++) {
    936                         uintptr_t b = node->key[i];
    937                         size_t j;
     1163                        uintptr_t ptr = node->key[i];
     1164                        size_t size;
    9381165                       
    939                         for (j = 0; j < (size_t) node->value[i]; j++) {
     1166                        for (size = 0; size < (size_t) node->value[i]; size++) {
    9401167                                page_table_lock(as, false);
    941 
     1168                               
    9421169                                /* Insert the new mapping */
    943                                 page_mapping_insert(as, b + j * PAGE_SIZE,
     1170                                page_mapping_insert(as, ptr + size * PAGE_SIZE,
    9441171                                    old_frame[frame_idx++], page_flags);
    945 
     1172                               
    9461173                                page_table_unlock(as, false);
    9471174                        }
    9481175                }
    9491176        }
    950 
     1177       
    9511178        free(old_frame);
    952 
     1179       
    9531180        mutex_unlock(&area->lock);
    9541181        mutex_unlock(&as->lock);
    955         interrupts_restore(ipl);
    956 
     1182       
    9571183        return 0;
    9581184}
    959 
    9601185
    9611186/** Handle page fault within the current address space.
     
    9671192 * Interrupts are assumed disabled.
    9681193 *
    969  * @param page          Faulting page.
    970  * @param access        Access mode that caused the page fault (i.e.
    971  *                      read/write/exec).
    972  * @param istate        Pointer to the interrupted state.
    973  *
    974  * @return              AS_PF_FAULT on page fault, AS_PF_OK on success or
    975  *                      AS_PF_DEFER if the fault was caused by copy_to_uspace()
    976  *                      or copy_from_uspace().
     1194 * @param page   Faulting page.
     1195 * @param access Access mode that caused the page fault (i.e.
     1196 *               read/write/exec).
     1197 * @param istate Pointer to the interrupted state.
     1198 *
     1199 * @return AS_PF_FAULT on page fault.
     1200 * @return AS_PF_OK on success.
     1201 * @return AS_PF_DEFER if the fault was caused by copy_to_uspace()
     1202 *         or copy_from_uspace().
     1203 *
    9771204 */
    9781205int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    9791206{
    980         pte_t *pte;
    981         as_area_t *area;
    982        
    9831207        if (!THREAD)
    9841208                return AS_PF_FAULT;
     
    9881212       
    9891213        mutex_lock(&AS->lock);
    990         area = find_area_and_lock(AS, page);
     1214        as_area_t *area = find_area_and_lock(AS, page);
    9911215        if (!area) {
    9921216                /*
    9931217                 * No area contained mapping for 'page'.
    9941218                 * Signal page fault to low-level handler.
     1219                 *
    9951220                 */
    9961221                mutex_unlock(&AS->lock);
    9971222                goto page_fault;
    9981223        }
    999 
     1224       
    10001225        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    10011226                /*
     
    10051230                mutex_unlock(&area->lock);
    10061231                mutex_unlock(&AS->lock);
    1007                 goto page_fault;               
    1008         }
    1009 
    1010         if (!area->backend || !area->backend->page_fault) {
     1232                goto page_fault;
     1233        }
     1234       
     1235        if ((!area->backend) || (!area->backend->page_fault)) {
    10111236                /*
    10121237                 * The address space area is not backed by any backend
    10131238                 * or the backend cannot handle page faults.
     1239                 *
    10141240                 */
    10151241                mutex_unlock(&area->lock);
    10161242                mutex_unlock(&AS->lock);
    1017                 goto page_fault;               
    1018         }
    1019 
     1243                goto page_fault;
     1244        }
     1245       
    10201246        page_table_lock(AS, false);
    10211247       
     
    10231249         * To avoid race condition between two page faults on the same address,
    10241250         * we need to make sure the mapping has not been already inserted.
    1025          */
     1251         *
     1252         */
     1253        pte_t *pte;
    10261254        if ((pte = page_mapping_find(AS, page))) {
    10271255                if (PTE_PRESENT(pte)) {
     
    10391267        /*
    10401268         * Resort to the backend page fault handler.
     1269         *
    10411270         */
    10421271        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    10511280        mutex_unlock(&AS->lock);
    10521281        return AS_PF_OK;
    1053 
     1282       
    10541283page_fault:
    10551284        if (THREAD->in_copy_from_uspace) {
     
    10641293                return AS_PF_FAULT;
    10651294        }
    1066 
     1295       
    10671296        return AS_PF_DEFER;
    10681297}
     
    10761305 * When this function is enetered, no spinlocks may be held.
    10771306 *
    1078  * @param old           Old address space or NULL.
    1079  * @param new           New address space.
     1307 * @param old Old address space or NULL.
     1308 * @param new New address space.
     1309 *
    10801310 */
    10811311void as_switch(as_t *old_as, as_t *new_as)
     
    10831313        DEADLOCK_PROBE_INIT(p_asidlock);
    10841314        preemption_disable();
     1315       
    10851316retry:
    10861317        (void) interrupts_disable();
    10871318        if (!spinlock_trylock(&asidlock)) {
    1088                 /* 
     1319                /*
    10891320                 * Avoid deadlock with TLB shootdown.
    10901321                 * We can enable interrupts here because
    10911322                 * preemption is disabled. We should not be
    10921323                 * holding any other lock.
     1324                 *
    10931325                 */
    10941326                (void) interrupts_enable();
     
    10971329        }
    10981330        preemption_enable();
    1099 
     1331       
    11001332        /*
    11011333         * First, take care of the old address space.
    1102          */     
     1334         */
    11031335        if (old_as) {
    11041336                ASSERT(old_as->cpu_refcount);
    1105                 if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
     1337               
     1338                if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    11061339                        /*
    11071340                         * The old address space is no longer active on
     
    11091342                         * list of inactive address spaces with assigned
    11101343                         * ASID.
     1344                         *
    11111345                         */
    11121346                        ASSERT(old_as->asid != ASID_INVALID);
     1347                       
    11131348                        list_append(&old_as->inactive_as_with_asid_link,
    11141349                            &inactive_as_with_asid_head);
    11151350                }
    1116 
     1351               
    11171352                /*
    11181353                 * Perform architecture-specific tasks when the address space
    11191354                 * is being removed from the CPU.
     1355                 *
    11201356                 */
    11211357                as_deinstall_arch(old_as);
    11221358        }
    1123 
     1359       
    11241360        /*
    11251361         * Second, prepare the new address space.
     1362         *
    11261363         */
    11271364        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    11311368                        new_as->asid = asid_get();
    11321369        }
     1370       
    11331371#ifdef AS_PAGE_TABLE
    11341372        SET_PTL0_ADDRESS(new_as->genarch.page_table);
     
    11381376         * Perform architecture-specific steps.
    11391377         * (e.g. write ASID to hardware register etc.)
     1378         *
    11401379         */
    11411380        as_install_arch(new_as);
    1142 
     1381       
    11431382        spinlock_unlock(&asidlock);
    11441383       
     
    11461385}
    11471386
    1148 /** Convert address space area flags to page flags.
    1149  *
    1150  * @param aflags        Flags of some address space area.
    1151  *
    1152  * @return              Flags to be passed to page_mapping_insert().
    1153  */
    1154 int area_flags_to_page_flags(int aflags)
    1155 {
    1156         int flags;
    1157 
    1158         flags = PAGE_USER | PAGE_PRESENT;
    1159        
    1160         if (aflags & AS_AREA_READ)
    1161                 flags |= PAGE_READ;
    1162                
    1163         if (aflags & AS_AREA_WRITE)
    1164                 flags |= PAGE_WRITE;
    1165        
    1166         if (aflags & AS_AREA_EXEC)
    1167                 flags |= PAGE_EXEC;
    1168        
    1169         if (aflags & AS_AREA_CACHEABLE)
    1170                 flags |= PAGE_CACHEABLE;
    1171                
    1172         return flags;
    1173 }
    1174 
    11751387/** Compute flags for virtual address translation subsytem.
    11761388 *
    1177  * The address space area must be locked.
    1178  * Interrupts must be disabled.
    1179  *
    1180  * @param a             Address space area.
    1181  *
    1182  * @return              Flags to be used in page_mapping_insert().
    1183  */
    1184 int as_area_get_flags(as_area_t *a)
    1185 {
    1186         return area_flags_to_page_flags(a->flags);
     1389 * @param area Address space area.
     1390 *
     1391 * @return Flags to be used in page_mapping_insert().
     1392 *
     1393 */
     1394NO_TRACE unsigned int as_area_get_flags(as_area_t *area)
     1395{
     1396        ASSERT(mutex_locked(&area->lock));
     1397
     1398        return area_flags_to_page_flags(area->flags);
    11871399}
    11881400
     
    11921404 * table.
    11931405 *
    1194  * @param flags         Flags saying whether the page table is for the kernel
    1195  *                      address space.
    1196  *
    1197  * @return              First entry of the page table.
    1198  */
    1199 pte_t *page_table_create(int flags)
     1406 * @param flags Flags saying whether the page table is for the kernel
     1407 *              address space.
     1408 *
     1409 * @return First entry of the page table.
     1410 *
     1411 */
     1412NO_TRACE pte_t *page_table_create(unsigned int flags)
    12001413{
    12011414        ASSERT(as_operations);
     
    12091422 * Destroy page table in architecture specific way.
    12101423 *
    1211  * @param page_table    Physical address of PTL0.
    1212  */
    1213 void page_table_destroy(pte_t *page_table)
     1424 * @param page_table Physical address of PTL0.
     1425 *
     1426 */
     1427NO_TRACE void page_table_destroy(pte_t *page_table)
    12141428{
    12151429        ASSERT(as_operations);
     
    12231437 * This function should be called before any page_mapping_insert(),
    12241438 * page_mapping_remove() and page_mapping_find().
    1225  * 
     1439 *
    12261440 * Locking order is such that address space areas must be locked
    12271441 * prior to this call. Address space can be locked prior to this
    12281442 * call in which case the lock argument is false.
    12291443 *
    1230  * @param as            Address space.
    1231  * @param lock          If false, do not attempt to lock as->lock.
    1232  */
    1233 void page_table_lock(as_t *as, bool lock)
     1444 * @param as   Address space.
     1445 * @param lock If false, do not attempt to lock as->lock.
     1446 *
     1447 */
     1448NO_TRACE void page_table_lock(as_t *as, bool lock)
    12341449{
    12351450        ASSERT(as_operations);
     
    12411456/** Unlock page table.
    12421457 *
    1243  * @param as            Address space.
    1244  * @param unlock        If false, do not attempt to unlock as->lock.
    1245  */
    1246 void page_table_unlock(as_t *as, bool unlock)
     1458 * @param as     Address space.
     1459 * @param unlock If false, do not attempt to unlock as->lock.
     1460 *
     1461 */
     1462NO_TRACE void page_table_unlock(as_t *as, bool unlock)
    12471463{
    12481464        ASSERT(as_operations);
     
    12521468}
    12531469
    1254 
    1255 /** Find address space area and lock it.
    1256  *
    1257  * The address space must be locked and interrupts must be disabled.
    1258  *
    1259  * @param as            Address space.
    1260  * @param va            Virtual address.
    1261  *
    1262  * @return              Locked address space area containing va on success or
    1263  *                      NULL on failure.
    1264  */
    1265 as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
    1266 {
    1267         as_area_t *a;
    1268         btree_node_t *leaf, *lnode;
    1269         unsigned int i;
    1270        
    1271         a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    1272         if (a) {
    1273                 /* va is the base address of an address space area */
    1274                 mutex_lock(&a->lock);
    1275                 return a;
    1276         }
    1277        
    1278         /*
    1279          * Search the leaf node and the righmost record of its left neighbour
    1280          * to find out whether this is a miss or va belongs to an address
    1281          * space area found there.
    1282          */
    1283        
    1284         /* First, search the leaf node itself. */
    1285         for (i = 0; i < leaf->keys; i++) {
    1286                 a = (as_area_t *) leaf->value[i];
    1287                 mutex_lock(&a->lock);
    1288                 if ((a->base <= va) && (va < a->base + a->pages * PAGE_SIZE)) {
    1289                         return a;
    1290                 }
    1291                 mutex_unlock(&a->lock);
    1292         }
    1293 
    1294         /*
    1295          * Second, locate the left neighbour and test its last record.
    1296          * Because of its position in the B+tree, it must have base < va.
    1297          */
    1298         lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    1299         if (lnode) {
    1300                 a = (as_area_t *) lnode->value[lnode->keys - 1];
    1301                 mutex_lock(&a->lock);
    1302                 if (va < a->base + a->pages * PAGE_SIZE) {
    1303                         return a;
    1304                 }
    1305                 mutex_unlock(&a->lock);
    1306         }
    1307 
    1308         return NULL;
    1309 }
    1310 
    1311 /** Check area conflicts with other areas.
    1312  *
    1313  * The address space must be locked and interrupts must be disabled.
    1314  *
    1315  * @param as            Address space.
    1316  * @param va            Starting virtual address of the area being tested.
    1317  * @param size          Size of the area being tested.
    1318  * @param avoid_area    Do not touch this area.
    1319  *
    1320  * @return              True if there is no conflict, false otherwise.
    1321  */
    1322 bool
    1323 check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
    1324 {
    1325         as_area_t *a;
    1326         btree_node_t *leaf, *node;
    1327         unsigned int i;
    1328        
    1329         /*
    1330          * We don't want any area to have conflicts with NULL page.
    1331          */
    1332         if (overlaps(va, size, NULL, PAGE_SIZE))
    1333                 return false;
    1334        
    1335         /*
    1336          * The leaf node is found in O(log n), where n is proportional to
    1337          * the number of address space areas belonging to as.
    1338          * The check for conflicts is then attempted on the rightmost
    1339          * record in the left neighbour, the leftmost record in the right
    1340          * neighbour and all records in the leaf node itself.
    1341          */
    1342        
    1343         if ((a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf))) {
    1344                 if (a != avoid_area)
    1345                         return false;
    1346         }
    1347        
    1348         /* First, check the two border cases. */
    1349         if ((node = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
    1350                 a = (as_area_t *) node->value[node->keys - 1];
    1351                 mutex_lock(&a->lock);
    1352                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1353                         mutex_unlock(&a->lock);
    1354                         return false;
    1355                 }
    1356                 mutex_unlock(&a->lock);
    1357         }
    1358         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    1359         if (node) {
    1360                 a = (as_area_t *) node->value[0];
    1361                 mutex_lock(&a->lock);
    1362                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1363                         mutex_unlock(&a->lock);
    1364                         return false;
    1365                 }
    1366                 mutex_unlock(&a->lock);
    1367         }
    1368        
    1369         /* Second, check the leaf node. */
    1370         for (i = 0; i < leaf->keys; i++) {
    1371                 a = (as_area_t *) leaf->value[i];
    1372        
    1373                 if (a == avoid_area)
    1374                         continue;
    1375        
    1376                 mutex_lock(&a->lock);
    1377                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1378                         mutex_unlock(&a->lock);
    1379                         return false;
    1380                 }
    1381                 mutex_unlock(&a->lock);
    1382         }
    1383 
    1384         /*
    1385          * So far, the area does not conflict with other areas.
    1386          * Check if it doesn't conflict with kernel address space.
    1387          */     
    1388         if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    1389                 return !overlaps(va, size,
    1390                     KERNEL_ADDRESS_SPACE_START,
    1391                     KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    1392         }
    1393 
    1394         return true;
     1470/** Test whether page tables are locked.
     1471 *
     1472 * @param as Address space where the page tables belong.
     1473 *
     1474 * @return True if the page tables belonging to the address soace
     1475 *         are locked, otherwise false.
     1476 */
     1477NO_TRACE bool page_table_locked(as_t *as)
     1478{
     1479        ASSERT(as_operations);
     1480        ASSERT(as_operations->page_table_locked);
     1481
     1482        return as_operations->page_table_locked(as);
    13951483}
    13961484
    13971485/** Return size of the address space area with given base.
    13981486 *
    1399  * @param base          Arbitrary address insede the address space area.
    1400  *
    1401  * @return              Size of the address space area in bytes or zero if it
    1402  *                      does not exist.
     1487 * @param base Arbitrary address inside the address space area.
     1488 *
     1489 * @return Size of the address space area in bytes or zero if it
     1490 *         does not exist.
     1491 *
    14031492 */
    14041493size_t as_area_get_size(uintptr_t base)
    14051494{
    1406         ipl_t ipl;
    1407         as_area_t *src_area;
    14081495        size_t size;
    1409 
    1410         ipl = interrupts_disable();
    1411         src_area = find_area_and_lock(AS, base);
     1496       
     1497        page_table_lock(AS, true);
     1498        as_area_t *src_area = find_area_and_lock(AS, base);
     1499       
    14121500        if (src_area) {
    14131501                size = src_area->pages * PAGE_SIZE;
    14141502                mutex_unlock(&src_area->lock);
    1415         } else {
     1503        } else
    14161504                size = 0;
    1417         }
    1418         interrupts_restore(ipl);
     1505       
     1506        page_table_unlock(AS, true);
    14191507        return size;
    14201508}
     
    14241512 * The address space area must be already locked.
    14251513 *
    1426  * @param a             Address space area.
    1427  * @param page          First page to be marked.
    1428  * @param count         Number of page to be marked.
    1429  *
    1430  * @return              Zero on failure and non-zero on success.
    1431  */
    1432 int used_space_insert(as_area_t *a, uintptr_t page, size_t count)
    1433 {
    1434         btree_node_t *leaf, *node;
    1435         size_t pages;
    1436         unsigned int i;
    1437 
     1514 * @param area  Address space area.
     1515 * @param page  First page to be marked.
     1516 * @param count Number of page to be marked.
     1517 *
     1518 * @return Zero on failure and non-zero on success.
     1519 *
     1520 */
     1521int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
     1522{
     1523        ASSERT(mutex_locked(&area->lock));
    14381524        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    14391525        ASSERT(count);
    1440 
    1441         pages = (size_t) btree_search(&a->used_space, page, &leaf);
     1526       
     1527        btree_node_t *leaf;
     1528        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    14421529        if (pages) {
    14431530                /*
    14441531                 * We hit the beginning of some used space.
     1532                 *
    14451533                 */
    14461534                return 0;
    14471535        }
    1448 
     1536       
    14491537        if (!leaf->keys) {
    1450                 btree_insert(&a->used_space, page, (void *) count, leaf);
     1538                btree_insert(&area->used_space, page, (void *) count, leaf);
    14511539                return 1;
    14521540        }
    1453 
    1454         node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
     1541       
     1542        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    14551543        if (node) {
    14561544                uintptr_t left_pg = node->key[node->keys - 1];
     
    14631551                 * somewhere between the rightmost interval of
    14641552                 * the left neigbour and the first interval of the leaf.
    1465                  */
    1466                  
     1553                 *
     1554                 */
     1555               
    14671556                if (page >= right_pg) {
    14681557                        /* Do nothing. */
     
    14741563                    right_cnt * PAGE_SIZE)) {
    14751564                        /* The interval intersects with the right interval. */
    1476                         return 0;                       
     1565                        return 0;
    14771566                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    14781567                    (page + count * PAGE_SIZE == right_pg)) {
     
    14801569                         * The interval can be added by merging the two already
    14811570                         * present intervals.
     1571                         *
    14821572                         */
    14831573                        node->value[node->keys - 1] += count + right_cnt;
    1484                         btree_remove(&a->used_space, right_pg, leaf);
    1485                         return 1; 
     1574                        btree_remove(&area->used_space, right_pg, leaf);
     1575                        return 1;
    14861576                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    1487                         /* 
     1577                        /*
    14881578                         * The interval can be added by simply growing the left
    14891579                         * interval.
     1580                         *
    14901581                         */
    14911582                        node->value[node->keys - 1] += count;
     
    14961587                         * the right interval down and increasing its size
    14971588                         * accordingly.
     1589                         *
    14981590                         */
    14991591                        leaf->value[0] += count;
     
    15041596                         * The interval is between both neigbouring intervals,
    15051597                         * but cannot be merged with any of them.
     1598                         *
    15061599                         */
    1507                         btree_insert(&a->used_space, page, (void *) count,
     1600                        btree_insert(&area->used_space, page, (void *) count,
    15081601                            leaf);
    15091602                        return 1;
     
    15121605                uintptr_t right_pg = leaf->key[0];
    15131606                size_t right_cnt = (size_t) leaf->value[0];
    1514        
     1607               
    15151608                /*
    15161609                 * Investigate the border case in which the left neighbour does
    15171610                 * not exist but the interval fits from the left.
    1518                  */
    1519                  
     1611                 *
     1612                 */
     1613               
    15201614                if (overlaps(page, count * PAGE_SIZE, right_pg,
    15211615                    right_cnt * PAGE_SIZE)) {
     
    15271621                         * right interval down and increasing its size
    15281622                         * accordingly.
     1623                         *
    15291624                         */
    15301625                        leaf->key[0] = page;
     
    15351630                         * The interval doesn't adjoin with the right interval.
    15361631                         * It must be added individually.
     1632                         *
    15371633                         */
    1538                         btree_insert(&a->used_space, page, (void *) count,
     1634                        btree_insert(&area->used_space, page, (void *) count,
    15391635                            leaf);
    15401636                        return 1;
    15411637                }
    15421638        }
    1543 
    1544         node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
     1639       
     1640        node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
    15451641        if (node) {
    15461642                uintptr_t left_pg = leaf->key[leaf->keys - 1];
     
    15531649                 * somewhere between the leftmost interval of
    15541650                 * the right neigbour and the last interval of the leaf.
    1555                  */
    1556 
     1651                 *
     1652                 */
     1653               
    15571654                if (page < left_pg) {
    15581655                        /* Do nothing. */
     
    15641661                    right_cnt * PAGE_SIZE)) {
    15651662                        /* The interval intersects with the right interval. */
    1566                         return 0;                       
     1663                        return 0;
    15671664                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    15681665                    (page + count * PAGE_SIZE == right_pg)) {
     
    15701667                         * The interval can be added by merging the two already
    15711668                         * present intervals.
    1572                          * */
     1669                         *
     1670                         */
    15731671                        leaf->value[leaf->keys - 1] += count + right_cnt;
    1574                         btree_remove(&a->used_space, right_pg, node);
    1575                         return 1; 
     1672                        btree_remove(&area->used_space, right_pg, node);
     1673                        return 1;
    15761674                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    15771675                        /*
    15781676                         * The interval can be added by simply growing the left
    15791677                         * interval.
    1580                          * */
     1678                         *
     1679                         */
    15811680                        leaf->value[leaf->keys - 1] +=  count;
    15821681                        return 1;
     
    15861685                         * the right interval down and increasing its size
    15871686                         * accordingly.
     1687                         *
    15881688                         */
    15891689                        node->value[0] += count;
     
    15941694                         * The interval is between both neigbouring intervals,
    15951695                         * but cannot be merged with any of them.
     1696                         *
    15961697                         */
    1597                         btree_insert(&a->used_space, page, (void *) count,
     1698                        btree_insert(&area->used_space, page, (void *) count,
    15981699                            leaf);
    15991700                        return 1;
     
    16021703                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    16031704                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1604        
     1705               
    16051706                /*
    16061707                 * Investigate the border case in which the right neighbour
    16071708                 * does not exist but the interval fits from the right.
    1608                  */
    1609                  
     1709                 *
     1710                 */
     1711               
    16101712                if (overlaps(page, count * PAGE_SIZE, left_pg,
    16111713                    left_cnt * PAGE_SIZE)) {
     
    16161718                         * The interval can be added by growing the left
    16171719                         * interval.
     1720                         *
    16181721                         */
    16191722                        leaf->value[leaf->keys - 1] += count;
     
    16231726                         * The interval doesn't adjoin with the left interval.
    16241727                         * It must be added individually.
     1728                         *
    16251729                         */
    1626                         btree_insert(&a->used_space, page, (void *) count,
     1730                        btree_insert(&area->used_space, page, (void *) count,
    16271731                            leaf);
    16281732                        return 1;
     
    16341738         * only between two other intervals of the leaf. The two border cases
    16351739         * were already resolved.
    1636          */
     1740         *
     1741         */
     1742        btree_key_t i;
    16371743        for (i = 1; i < leaf->keys; i++) {
    16381744                if (page < leaf->key[i]) {
     
    16411747                        size_t left_cnt = (size_t) leaf->value[i - 1];
    16421748                        size_t right_cnt = (size_t) leaf->value[i];
    1643 
     1749                       
    16441750                        /*
    16451751                         * The interval fits between left_pg and right_pg.
     1752                         *
    16461753                         */
    1647 
     1754                       
    16481755                        if (overlaps(page, count * PAGE_SIZE, left_pg,
    16491756                            left_cnt * PAGE_SIZE)) {
     
    16511758                                 * The interval intersects with the left
    16521759                                 * interval.
     1760                                 *
    16531761                                 */
    16541762                                return 0;
     
    16581766                                 * The interval intersects with the right
    16591767                                 * interval.
     1768                                 *
    16601769                                 */
    1661                                 return 0;                       
     1770                                return 0;
    16621771                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    16631772                            (page + count * PAGE_SIZE == right_pg)) {
     
    16651774                                 * The interval can be added by merging the two
    16661775                                 * already present intervals.
     1776                                 *
    16671777                                 */
    16681778                                leaf->value[i - 1] += count + right_cnt;
    1669                                 btree_remove(&a->used_space, right_pg, leaf);
    1670                                 return 1; 
     1779                                btree_remove(&area->used_space, right_pg, leaf);
     1780                                return 1;
    16711781                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16721782                                /*
    16731783                                 * The interval can be added by simply growing
    16741784                                 * the left interval.
     1785                                 *
    16751786                                 */
    16761787                                leaf->value[i - 1] += count;
     
    16781789                        } else if (page + count * PAGE_SIZE == right_pg) {
    16791790                                /*
    1680                                 * The interval can be addded by simply moving
     1791                                * The interval can be addded by simply moving
    16811792                                 * base of the right interval down and
    16821793                                 * increasing its size accordingly.
    1683                                  */
     1794                                 *
     1795                                 */
    16841796                                leaf->value[i] += count;
    16851797                                leaf->key[i] = page;
     
    16901802                                 * intervals, but cannot be merged with any of
    16911803                                 * them.
     1804                                 *
    16921805                                 */
    1693                                 btree_insert(&a->used_space, page,
     1806                                btree_insert(&area->used_space, page,
    16941807                                    (void *) count, leaf);
    16951808                                return 1;
     
    16971810                }
    16981811        }
    1699 
     1812       
    17001813        panic("Inconsistency detected while adding %" PRIs " pages of used "
    17011814            "space at %p.", count, page);
     
    17061819 * The address space area must be already locked.
    17071820 *
    1708  * @param a             Address space area.
    1709  * @param page          First page to be marked.
    1710  * @param count         Number of page to be marked.
    1711  *
    1712  * @return              Zero on failure and non-zero on success.
    1713  */
    1714 int used_space_remove(as_area_t *a, uintptr_t page, size_t count)
    1715 {
    1716         btree_node_t *leaf, *node;
    1717         size_t pages;
    1718         unsigned int i;
    1719 
     1821 * @param area  Address space area.
     1822 * @param page  First page to be marked.
     1823 * @param count Number of page to be marked.
     1824 *
     1825 * @return Zero on failure and non-zero on success.
     1826 *
     1827 */
     1828int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
     1829{
     1830        ASSERT(mutex_locked(&area->lock));
    17201831        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    17211832        ASSERT(count);
    1722 
    1723         pages = (size_t) btree_search(&a->used_space, page, &leaf);
     1833       
     1834        btree_node_t *leaf;
     1835        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    17241836        if (pages) {
    17251837                /*
    17261838                 * We are lucky, page is the beginning of some interval.
     1839                 *
    17271840                 */
    17281841                if (count > pages) {
    17291842                        return 0;
    17301843                } else if (count == pages) {
    1731                         btree_remove(&a->used_space, page, leaf);
     1844                        btree_remove(&area->used_space, page, leaf);
    17321845                        return 1;
    17331846                } else {
     
    17351848                         * Find the respective interval.
    17361849                         * Decrease its size and relocate its start address.
     1850                         *
    17371851                         */
     1852                        btree_key_t i;
    17381853                        for (i = 0; i < leaf->keys; i++) {
    17391854                                if (leaf->key[i] == page) {
     
    17461861                }
    17471862        }
    1748 
    1749         node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
    1750         if (node && page < leaf->key[0]) {
     1863       
     1864        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1865        if ((node) && (page < leaf->key[0])) {
    17511866                uintptr_t left_pg = node->key[node->keys - 1];
    17521867                size_t left_cnt = (size_t) node->value[node->keys - 1];
    1753 
     1868               
    17541869                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17551870                    count * PAGE_SIZE)) {
     
    17611876                                 * removed by updating the size of the bigger
    17621877                                 * interval.
     1878                                 *
    17631879                                 */
    17641880                                node->value[node->keys - 1] -= count;
     
    17661882                        } else if (page + count * PAGE_SIZE <
    17671883                            left_pg + left_cnt*PAGE_SIZE) {
    1768                                 size_t new_cnt;
    1769                                
    17701884                                /*
    17711885                                 * The interval is contained in the rightmost
     
    17741888                                 * the original interval and also inserting a
    17751889                                 * new interval.
     1890                                 *
    17761891                                 */
    1777                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1892                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    17781893                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    17791894                                node->value[node->keys - 1] -= count + new_cnt;
    1780                                 btree_insert(&a->used_space, page +
     1895                                btree_insert(&area->used_space, page +
    17811896                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    17821897                                return 1;
     
    17841899                }
    17851900                return 0;
    1786         } else if (page < leaf->key[0]) {
     1901        } else if (page < leaf->key[0])
    17871902                return 0;
    1788         }
    17891903       
    17901904        if (page > leaf->key[leaf->keys - 1]) {
    17911905                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    17921906                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1793 
     1907               
    17941908                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17951909                    count * PAGE_SIZE)) {
    1796                         if (page + count * PAGE_SIZE == 
     1910                        if (page + count * PAGE_SIZE ==
    17971911                            left_pg + left_cnt * PAGE_SIZE) {
    17981912                                /*
     
    18001914                                 * interval of the leaf and can be removed by
    18011915                                 * updating the size of the bigger interval.
     1916                                 *
    18021917                                 */
    18031918                                leaf->value[leaf->keys - 1] -= count;
     
    18051920                        } else if (page + count * PAGE_SIZE < left_pg +
    18061921                            left_cnt * PAGE_SIZE) {
    1807                                 size_t new_cnt;
    1808                                
    18091922                                /*
    18101923                                 * The interval is contained in the rightmost
     
    18131926                                 * original interval and also inserting a new
    18141927                                 * interval.
     1928                                 *
    18151929                                 */
    1816                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1930                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    18171931                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    18181932                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    1819                                 btree_insert(&a->used_space, page +
     1933                                btree_insert(&area->used_space, page +
    18201934                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    18211935                                return 1;
     
    18231937                }
    18241938                return 0;
    1825         }       
     1939        }
    18261940       
    18271941        /*
     
    18291943         * Now the interval can be only between intervals of the leaf.
    18301944         */
     1945        btree_key_t i;
    18311946        for (i = 1; i < leaf->keys - 1; i++) {
    18321947                if (page < leaf->key[i]) {
    18331948                        uintptr_t left_pg = leaf->key[i - 1];
    18341949                        size_t left_cnt = (size_t) leaf->value[i - 1];
    1835 
     1950                       
    18361951                        /*
    18371952                         * Now the interval is between intervals corresponding
     
    18471962                                         * be removed by updating the size of
    18481963                                         * the bigger interval.
     1964                                         *
    18491965                                         */
    18501966                                        leaf->value[i - 1] -= count;
     
    18521968                                } else if (page + count * PAGE_SIZE <
    18531969                                    left_pg + left_cnt * PAGE_SIZE) {
    1854                                         size_t new_cnt;
    1855                                
    18561970                                        /*
    18571971                                         * The interval is contained in the
     
    18611975                                         * also inserting a new interval.
    18621976                                         */
    1863                                         new_cnt = ((left_pg +
     1977                                        size_t new_cnt = ((left_pg +
    18641978                                            left_cnt * PAGE_SIZE) -
    18651979                                            (page + count * PAGE_SIZE)) >>
    18661980                                            PAGE_WIDTH;
    18671981                                        leaf->value[i - 1] -= count + new_cnt;
    1868                                         btree_insert(&a->used_space, page +
     1982                                        btree_insert(&area->used_space, page +
    18691983                                            count * PAGE_SIZE, (void *) new_cnt,
    18701984                                            leaf);
     
    18751989                }
    18761990        }
    1877 
     1991       
    18781992error:
    18791993        panic("Inconsistency detected while removing %" PRIs " pages of used "
     
    18811995}
    18821996
    1883 /** Remove reference to address space area share info.
    1884  *
    1885  * If the reference count drops to 0, the sh_info is deallocated.
    1886  *
    1887  * @param sh_info       Pointer to address space area share info.
    1888  */
    1889 void sh_info_remove_reference(share_info_t *sh_info)
    1890 {
    1891         bool dealloc = false;
    1892 
    1893         mutex_lock(&sh_info->lock);
    1894         ASSERT(sh_info->refcount);
    1895         if (--sh_info->refcount == 0) {
    1896                 dealloc = true;
    1897                 link_t *cur;
    1898                
    1899                 /*
    1900                  * Now walk carefully the pagemap B+tree and free/remove
    1901                  * reference from all frames found there.
    1902                  */
    1903                 for (cur = sh_info->pagemap.leaf_head.next;
    1904                     cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
    1905                         btree_node_t *node;
    1906                         unsigned int i;
    1907                        
    1908                         node = list_get_instance(cur, btree_node_t, leaf_link);
    1909                         for (i = 0; i < node->keys; i++)
    1910                                 frame_free((uintptr_t) node->value[i]);
    1911                 }
    1912                
    1913         }
    1914         mutex_unlock(&sh_info->lock);
    1915        
    1916         if (dealloc) {
    1917                 btree_destroy(&sh_info->pagemap);
    1918                 free(sh_info);
    1919         }
    1920 }
    1921 
    19221997/*
    19231998 * Address space related syscalls.
     
    19252000
    19262001/** Wrapper for as_area_create(). */
    1927 unative_t sys_as_area_create(uintptr_t address, size_t size, int flags)
     2002unative_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
    19282003{
    19292004        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
     
    19352010
    19362011/** Wrapper for as_area_resize(). */
    1937 unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
     2012unative_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
    19382013{
    19392014        return (unative_t) as_area_resize(AS, address, size, 0);
     
    19412016
    19422017/** Wrapper for as_area_change_flags(). */
    1943 unative_t sys_as_area_change_flags(uintptr_t address, int flags)
     2018unative_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
    19442019{
    19452020        return (unative_t) as_area_change_flags(AS, flags, address);
     
    19542029/** Get list of adress space areas.
    19552030 *
    1956  * @param as            Address space.
    1957  * @param obuf          Place to save pointer to returned buffer.
    1958  * @param osize         Place to save size of returned buffer.
     2031 * @param as    Address space.
     2032 * @param obuf  Place to save pointer to returned buffer.
     2033 * @param osize Place to save size of returned buffer.
     2034 *
    19592035 */
    19602036void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
    19612037{
    1962         ipl_t ipl;
    1963         size_t area_cnt, area_idx, i;
     2038        mutex_lock(&as->lock);
     2039       
     2040        /* First pass, count number of areas. */
     2041       
     2042        size_t area_cnt = 0;
    19642043        link_t *cur;
    1965 
    1966         as_area_info_t *info;
    1967         size_t isize;
    1968 
    1969         ipl = interrupts_disable();
    1970         mutex_lock(&as->lock);
    1971 
    1972         /* First pass, count number of areas. */
    1973 
    1974         area_cnt = 0;
    1975 
     2044       
    19762045        for (cur = as->as_area_btree.leaf_head.next;
    19772046            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1978                 btree_node_t *node;
    1979 
    1980                 node = list_get_instance(cur, btree_node_t, leaf_link);
     2047                btree_node_t *node =
     2048                    list_get_instance(cur, btree_node_t, leaf_link);
    19812049                area_cnt += node->keys;
    19822050        }
    1983 
    1984         isize = area_cnt * sizeof(as_area_info_t);
    1985         info = malloc(isize, 0);
    1986 
     2051       
     2052        size_t isize = area_cnt * sizeof(as_area_info_t);
     2053        as_area_info_t *info = malloc(isize, 0);
     2054       
    19872055        /* Second pass, record data. */
    1988 
    1989         area_idx = 0;
    1990 
     2056       
     2057        size_t area_idx = 0;
     2058       
    19912059        for (cur = as->as_area_btree.leaf_head.next;
    19922060            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1993                 btree_node_t *node;
    1994 
    1995                 node = list_get_instance(cur, btree_node_t, leaf_link);
    1996 
     2061                btree_node_t *node =
     2062                    list_get_instance(cur, btree_node_t, leaf_link);
     2063                btree_key_t i;
     2064               
    19972065                for (i = 0; i < node->keys; i++) {
    19982066                        as_area_t *area = node->value[i];
    1999 
     2067                       
    20002068                        ASSERT(area_idx < area_cnt);
    20012069                        mutex_lock(&area->lock);
    2002 
     2070                       
    20032071                        info[area_idx].start_addr = area->base;
    20042072                        info[area_idx].size = FRAMES2SIZE(area->pages);
    20052073                        info[area_idx].flags = area->flags;
    20062074                        ++area_idx;
    2007 
     2075                       
    20082076                        mutex_unlock(&area->lock);
    20092077                }
    20102078        }
    2011 
     2079       
    20122080        mutex_unlock(&as->lock);
    2013         interrupts_restore(ipl);
    2014 
     2081       
    20152082        *obuf = info;
    20162083        *osize = isize;
    20172084}
    20182085
    2019 
    20202086/** Print out information about address space.
    20212087 *
    2022  * @param as            Address space.
     2088 * @param as Address space.
     2089 *
    20232090 */
    20242091void as_print(as_t *as)
    20252092{
    2026         ipl_t ipl;
    2027        
    2028         ipl = interrupts_disable();
    20292093        mutex_lock(&as->lock);
    20302094       
     
    20332097        for (cur = as->as_area_btree.leaf_head.next;
    20342098            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2035                 btree_node_t *node;
    2036                
    2037                 node = list_get_instance(cur, btree_node_t, leaf_link);
    2038                
    2039                 unsigned int i;
     2099                btree_node_t *node
     2100                    = list_get_instance(cur, btree_node_t, leaf_link);
     2101                btree_key_t i;
     2102               
    20402103                for (i = 0; i < node->keys; i++) {
    20412104                        as_area_t *area = node->value[i];
    2042                
     2105                       
    20432106                        mutex_lock(&area->lock);
    20442107                        printf("as_area: %p, base=%p, pages=%" PRIs
     
    20502113       
    20512114        mutex_unlock(&as->lock);
    2052         interrupts_restore(ipl);
    20532115}
    20542116
Note: See TracChangeset for help on using the changeset viewer.