Ignore:
File:
1 edited

Legend:

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

    r336db295 r7e752b2  
    11/*
    2  * Copyright (c) 2001-2006 Jakub Jermar
     2 * Copyright (c) 2010 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3333/**
    3434 * @file
    35  * @brief       Address space related functions.
     35 * @brief Address space related functions.
    3636 *
    3737 * This file contains address space manipulation functions.
     
    7575#include <config.h>
    7676#include <align.h>
    77 #include <arch/types.h>
     77#include <typedefs.h>
    7878#include <syscall/copy.h>
    7979#include <arch/interrupt.h>
     
    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);
     
    152149         * reference count never drops to zero.
    153150         */
    154         atomic_set(&AS_KERNEL->refcount, 1);
     151        as_hold(AS_KERNEL);
    155152}
    156153
    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
     198        ASSERT(as != AS);
    202199        ASSERT(atomic_get(&as->refcount) == 0);
    203200       
    204201        /*
    205          * Since there is no reference to this area,
    206          * it is safe not to lock its mutex.
     202         * Since there is no reference to this address space, it is safe not to
     203         * lock its mutex.
    207204         */
    208205
     
    213210         * disabled to prevent nested context switches. We also depend on the
    214211         * fact that so far no spinlocks are held.
     212         *
    215213         */
    216214        preemption_disable();
    217         ipl = interrupts_read();
     215        ipl_t ipl = interrupts_read();
     216       
    218217retry:
    219218        interrupts_disable();
     
    223222                goto retry;
    224223        }
    225         preemption_enable();    /* Interrupts disabled, enable preemption */
    226         if (as->asid != ASID_INVALID && as != AS_KERNEL) {
    227                 if (as != AS && as->cpu_refcount == 0)
     224       
     225        /* Interrupts disabled, enable preemption */
     226        preemption_enable();
     227       
     228        if ((as->asid != ASID_INVALID) && (as != AS_KERNEL)) {
     229                if (as->cpu_refcount == 0)
    228230                        list_remove(&as->inactive_as_with_asid_link);
     231               
    229232                asid_put(as->asid);
    230233        }
     234       
    231235        spinlock_unlock(&asidlock);
    232 
     236        interrupts_restore(ipl);
     237
     238       
    233239        /*
    234240         * Destroy address space areas of the address space.
    235241         * The B+tree must be walked carefully because it is
    236242         * also being destroyed.
    237          */     
    238         for (cond = true; cond; ) {
    239                 btree_node_t *node;
    240 
     243         *
     244         */
     245        bool cond = true;
     246        while (cond) {
    241247                ASSERT(!list_empty(&as->as_area_btree.leaf_head));
    242                 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,
    243251                    btree_node_t, leaf_link);
    244 
    245                 if ((cond = node->keys)) {
     252               
     253                if ((cond = node->keys))
    246254                        as_area_destroy(as, node->key[0]);
    247                 }
    248         }
    249 
     255        }
     256       
    250257        btree_destroy(&as->as_area_btree);
     258       
    251259#ifdef AS_PAGE_TABLE
    252260        page_table_destroy(as->genarch.page_table);
     
    254262        page_table_destroy(NULL);
    255263#endif
    256 
    257         interrupts_restore(ipl);
    258 
     264       
    259265        slab_free(as_slab, as);
    260266}
    261267
     268/** Hold a reference to an address space.
     269 *
     270 * Holding a reference to an address space prevents destruction of that address
     271 * space.
     272 *
     273 * @param as Address space to be held.
     274 *
     275 */
     276NO_TRACE void as_hold(as_t *as)
     277{
     278        atomic_inc(&as->refcount);
     279}
     280
     281/** Release a reference to an address space.
     282 *
     283 * The last one to release a reference to an address space destroys the address
     284 * space.
     285 *
     286 * @param asAddress space to be released.
     287 *
     288 */
     289NO_TRACE void as_release(as_t *as)
     290{
     291        if (atomic_predec(&as->refcount) == 0)
     292                as_destroy(as);
     293}
     294
     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, (uintptr_t) 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
    262395/** Create address space area of common attributes.
    263396 *
    264397 * The created address space area is added to the target address space.
    265398 *
    266  * @param as            Target address space.
    267  * @param flags         Flags of the area memory.
    268  * @param size          Size of area.
    269  * @param base          Base address of area.
    270  * @param attrs         Attributes of the area.
    271  * @param backend       Address space area backend. NULL if no backend is used.
    272  * @param backend_data  NULL or a pointer to an array holding two void *.
    273  *
    274  * @return              Address space area on success or NULL on failure.
    275  */
    276 as_area_t *
    277 as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs,
    278     mem_backend_t *backend, mem_backend_data_t *backend_data)
    279 {
    280         ipl_t ipl;
    281         as_area_t *a;
    282        
     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{
    283414        if (base % PAGE_SIZE)
    284415                return NULL;
    285 
     416       
    286417        if (!size)
    287418                return NULL;
    288 
     419       
    289420        /* Writeable executable areas are not supported. */
    290421        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    291422                return NULL;
    292423       
    293         ipl = interrupts_disable();
    294424        mutex_lock(&as->lock);
    295425       
    296426        if (!check_area_conflicts(as, base, size, NULL)) {
    297427                mutex_unlock(&as->lock);
    298                 interrupts_restore(ipl);
    299428                return NULL;
    300429        }
    301430       
    302         a = (as_area_t *) malloc(sizeof(as_area_t), 0);
    303 
    304         mutex_initialize(&a->lock, MUTEX_PASSIVE);
    305        
    306         a->as = as;
    307         a->flags = flags;
    308         a->attributes = attrs;
    309         a->pages = SIZE2FRAMES(size);
    310         a->base = base;
    311         a->sh_info = NULL;
    312         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       
    313443        if (backend_data)
    314                 a->backend_data = *backend_data;
     444                area->backend_data = *backend_data;
    315445        else
    316                 memsetb(&a->backend_data, sizeof(a->backend_data), 0);
    317 
    318         btree_create(&a->used_space);
    319        
    320         btree_insert(&as->as_area_btree, base, (void *) a, NULL);
    321 
     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       
    322451        mutex_unlock(&as->lock);
    323         interrupts_restore(ipl);
    324 
    325         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;
    326516}
    327517
    328518/** Find address space area and change it.
    329519 *
    330  * @param as            Address space.
    331  * @param address       Virtual address belonging to the area to be changed.
    332  *                      Must be page-aligned.
    333  * @param size          New size of the virtual memory block starting at
    334  *                      address.
    335  * @param flags         Flags influencing the remap operation. Currently unused.
    336  *
    337  * @return              Zero on success or a value from @ref errno.h otherwise.
    338  */
    339 int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags)
    340 {
    341         as_area_t *area;
    342         ipl_t ipl;
    343         size_t pages;
    344        
    345         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{
    346532        mutex_lock(&as->lock);
    347533       
    348534        /*
    349535         * Locate the area.
    350          */
    351         area = find_area_and_lock(as, address);
     536         *
     537         */
     538        as_area_t *area = find_area_and_lock(as, address);
    352539        if (!area) {
    353540                mutex_unlock(&as->lock);
    354                 interrupts_restore(ipl);
    355541                return ENOENT;
    356542        }
    357 
     543       
    358544        if (area->backend == &phys_backend) {
    359545                /*
    360546                 * Remapping of address space areas associated
    361547                 * with memory mapped devices is not supported.
     548                 *
    362549                 */
    363550                mutex_unlock(&area->lock);
    364551                mutex_unlock(&as->lock);
    365                 interrupts_restore(ipl);
    366552                return ENOTSUP;
    367553        }
     554       
    368555        if (area->sh_info) {
    369556                /*
    370                  * Remapping of shared address space areas 
     557                 * Remapping of shared address space areas
    371558                 * is not supported.
     559                 *
    372560                 */
    373561                mutex_unlock(&area->lock);
    374562                mutex_unlock(&as->lock);
    375                 interrupts_restore(ipl);
    376563                return ENOTSUP;
    377564        }
    378 
    379         pages = SIZE2FRAMES((address - area->base) + size);
     565       
     566        size_t pages = SIZE2FRAMES((address - area->base) + size);
    380567        if (!pages) {
    381568                /*
    382569                 * Zero size address space areas are not allowed.
     570                 *
    383571                 */
    384572                mutex_unlock(&area->lock);
    385573                mutex_unlock(&as->lock);
    386                 interrupts_restore(ipl);
    387574                return EPERM;
    388575        }
    389576       
    390577        if (pages < area->pages) {
    391                 bool cond;
    392578                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    393 
     579               
    394580                /*
    395581                 * Shrinking the area.
    396582                 * No need to check for overlaps.
    397                  */
    398 
     583                 *
     584                 */
     585               
     586                page_table_lock(as, false);
     587               
    399588                /*
    400589                 * Start TLB shootdown sequence.
    401                  */
    402                 tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
    403                     pages * PAGE_SIZE, area->pages - pages);
    404 
     590                 *
     591                 */
     592                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
     593                    area->base + pages * PAGE_SIZE, area->pages - pages);
     594               
    405595                /*
    406596                 * Remove frames belonging to used space starting from
     
    409599                 * is also the right way to remove part of the used_space
    410600                 * B+tree leaf list.
    411                  */             
    412                 for (cond = true; cond;) {
    413                         btree_node_t *node;
    414                
     601                 *
     602                 */
     603                bool cond = true;
     604                while (cond) {
    415605                        ASSERT(!list_empty(&area->used_space.leaf_head));
    416                         node =
     606                       
     607                        btree_node_t *node =
    417608                            list_get_instance(area->used_space.leaf_head.prev,
    418609                            btree_node_t, leaf_link);
     610                       
    419611                        if ((cond = (bool) node->keys)) {
    420                                 uintptr_t b = node->key[node->keys - 1];
    421                                 size_t c =
     612                                uintptr_t ptr = node->key[node->keys - 1];
     613                                size_t size =
    422614                                    (size_t) node->value[node->keys - 1];
    423                                 unsigned int i = 0;
    424                        
    425                                 if (overlaps(b, c * PAGE_SIZE, area->base,
     615                                size_t i = 0;
     616                               
     617                                if (overlaps(ptr, size * PAGE_SIZE, area->base,
    426618                                    pages * PAGE_SIZE)) {
    427619                                       
    428                                         if (b + c * PAGE_SIZE <= start_free) {
     620                                        if (ptr + size * PAGE_SIZE <= start_free) {
    429621                                                /*
    430622                                                 * The whole interval fits
    431623                                                 * completely in the resized
    432624                                                 * address space area.
     625                                                 *
    433626                                                 */
    434627                                                break;
    435628                                        }
    436                
     629                                       
    437630                                        /*
    438631                                         * Part of the interval corresponding
    439632                                         * to b and c overlaps with the resized
    440633                                         * address space area.
     634                                         *
    441635                                         */
    442                
    443                                         cond = false;   /* we are almost done */
    444                                         i = (start_free - b) >> PAGE_WIDTH;
     636                                       
     637                                        /* We are almost done */
     638                                        cond = false;
     639                                        i = (start_free - ptr) >> PAGE_WIDTH;
    445640                                        if (!used_space_remove(area, start_free,
    446                                             c - i))
    447                                                 panic("Cannot remove used "
    448                                                     "space.");
     641                                            size - i))
     642                                                panic("Cannot remove used space.");
    449643                                } else {
    450644                                        /*
     
    452646                                         * completely removed.
    453647                                         */
    454                                         if (!used_space_remove(area, b, c))
    455                                                 panic("Cannot remove used "
    456                                                     "space.");
     648                                        if (!used_space_remove(area, ptr, size))
     649                                                panic("Cannot remove used space.");
    457650                                }
    458                        
    459                                 for (; i < c; i++) {
    460                                         pte_t *pte;
    461                        
    462                                         page_table_lock(as, false);
    463                                         pte = page_mapping_find(as, b +
     651                               
     652                                for (; i < size; i++) {
     653                                        pte_t *pte = page_mapping_find(as, ptr +
    464654                                            i * PAGE_SIZE);
    465                                         ASSERT(pte && PTE_VALID(pte) &&
    466                                             PTE_PRESENT(pte));
    467                                         if (area->backend &&
    468                                             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)) {
    469662                                                area->backend->frame_free(area,
    470                                                     b + i * PAGE_SIZE,
     663                                                    ptr + i * PAGE_SIZE,
    471664                                                    PTE_GET_FRAME(pte));
    472665                                        }
    473                                         page_mapping_remove(as, b +
     666                                       
     667                                        page_mapping_remove(as, ptr +
    474668                                            i * PAGE_SIZE);
    475                                         page_table_unlock(as, false);
    476669                                }
    477670                        }
    478671                }
    479 
     672               
    480673                /*
    481674                 * Finish TLB shootdown sequence.
    482                  */
    483 
     675                 *
     676                 */
     677               
    484678                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    485679                    area->pages - pages);
     680               
    486681                /*
    487682                 * Invalidate software translation caches (e.g. TSB on sparc64).
     683                 *
    488684                 */
    489685                as_invalidate_translation_cache(as, area->base +
    490686                    pages * PAGE_SIZE, area->pages - pages);
    491                 tlb_shootdown_finalize();
    492                
     687                tlb_shootdown_finalize(ipl);
     688               
     689                page_table_unlock(as, false);
    493690        } else {
    494691                /*
    495692                 * Growing the area.
    496693                 * Check for overlaps with other address space areas.
     694                 *
    497695                 */
    498696                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    499697                    area)) {
    500698                        mutex_unlock(&area->lock);
    501                         mutex_unlock(&as->lock);               
    502                         interrupts_restore(ipl);
     699                        mutex_unlock(&as->lock);
    503700                        return EADDRNOTAVAIL;
    504701                }
    505         } 
    506 
     702        }
     703       
    507704        area->pages = pages;
    508705       
    509706        mutex_unlock(&area->lock);
    510707        mutex_unlock(&as->lock);
    511         interrupts_restore(ipl);
    512 
     708       
    513709        return 0;
    514710}
    515711
     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
    516753/** Destroy address space area.
    517754 *
    518  * @param as            Address space.
    519  * @param address       Address within the area to be deleted.
    520  *
    521  * @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 *
    522760 */
    523761int as_area_destroy(as_t *as, uintptr_t address)
    524762{
    525         as_area_t *area;
    526         uintptr_t base;
    527         link_t *cur;
    528         ipl_t ipl;
    529 
    530         ipl = interrupts_disable();
    531763        mutex_lock(&as->lock);
    532 
    533         area = find_area_and_lock(as, address);
     764       
     765        as_area_t *area = find_area_and_lock(as, address);
    534766        if (!area) {
    535767                mutex_unlock(&as->lock);
    536                 interrupts_restore(ipl);
    537768                return ENOENT;
    538769        }
    539 
    540         base = area->base;
    541 
     770       
     771        uintptr_t base = area->base;
     772       
     773        page_table_lock(as, false);
     774       
    542775        /*
    543776         * Start TLB shootdown sequence.
    544777         */
    545         tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    546 
     778        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     779            area->pages);
     780       
    547781        /*
    548782         * Visit only the pages mapped by used_space B+tree.
    549783         */
     784        link_t *cur;
    550785        for (cur = area->used_space.leaf_head.next;
    551786            cur != &area->used_space.leaf_head; cur = cur->next) {
    552787                btree_node_t *node;
    553                 unsigned int i;
     788                btree_key_t i;
    554789               
    555790                node = list_get_instance(cur, btree_node_t, leaf_link);
    556791                for (i = 0; i < node->keys; i++) {
    557                         uintptr_t b = node->key[i];
    558                         size_t j;
    559                         pte_t *pte;
     792                        uintptr_t ptr = node->key[i];
     793                        size_t size;
    560794                       
    561                         for (j = 0; j < (size_t) node->value[i]; j++) {
    562                                 page_table_lock(as, false);
    563                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    564                                 ASSERT(pte && PTE_VALID(pte) &&
    565                                     PTE_PRESENT(pte));
    566                                 if (area->backend &&
    567                                     area->backend->frame_free) {
    568                                         area->backend->frame_free(area, b +
    569                                             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));
    570806                                }
    571                                 page_mapping_remove(as, b + j * PAGE_SIZE);                             
    572                                 page_table_unlock(as, false);
     807                               
     808                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    573809                        }
    574810                }
    575811        }
    576 
     812       
    577813        /*
    578814         * Finish TLB shootdown sequence.
    579          */
    580 
     815         *
     816         */
     817       
    581818        tlb_invalidate_pages(as->asid, area->base, area->pages);
     819       
    582820        /*
    583821         * Invalidate potential software translation caches (e.g. TSB on
    584822         * sparc64).
     823         *
    585824         */
    586825        as_invalidate_translation_cache(as, area->base, area->pages);
    587         tlb_shootdown_finalize();
     826        tlb_shootdown_finalize(ipl);
     827       
     828        page_table_unlock(as, false);
    588829       
    589830        btree_destroy(&area->used_space);
    590 
     831       
    591832        area->attributes |= AS_AREA_ATTR_PARTIAL;
    592833       
    593834        if (area->sh_info)
    594835                sh_info_remove_reference(area->sh_info);
    595                
     836       
    596837        mutex_unlock(&area->lock);
    597 
     838       
    598839        /*
    599840         * Remove the empty area from address space.
     841         *
    600842         */
    601843        btree_remove(&as->as_area_btree, base, NULL);
     
    604846       
    605847        mutex_unlock(&as->lock);
    606         interrupts_restore(ipl);
    607848        return 0;
    608849}
     
    615856 * sh_info of the source area. The process of duplicating the
    616857 * mapping is done through the backend share function.
    617  * 
    618  * @param src_as        Pointer to source address space.
    619  * @param src_base      Base address of the source address space area.
    620  * @param acc_size      Expected size of the source area.
    621  * @param dst_as        Pointer to destination address space.
    622  * @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.
    623864 * @param dst_flags_mask Destination address space area flags mask.
    624865 *
    625  * @return              Zero on success or ENOENT if there is no such task or if
    626  *                      there is no such address space area, EPERM if there was
    627  *                      a problem in accepting the area or ENOMEM if there was a
    628  *                      problem in allocating destination address space area.
    629  *                      ENOTSUP is returned if the address space area backend
    630  *                      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 *
    631874 */
    632875int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
    633     as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
    634 {
    635         ipl_t ipl;
    636         int src_flags;
    637         size_t src_size;
    638         as_area_t *src_area, *dst_area;
    639         share_info_t *sh_info;
    640         mem_backend_t *src_backend;
    641         mem_backend_data_t src_backend_data;
    642        
    643         ipl = interrupts_disable();
     876    as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
     877{
    644878        mutex_lock(&src_as->lock);
    645         src_area = find_area_and_lock(src_as, src_base);
     879        as_area_t *src_area = find_area_and_lock(src_as, src_base);
    646880        if (!src_area) {
    647881                /*
    648882                 * Could not find the source address space area.
     883                 *
    649884                 */
    650885                mutex_unlock(&src_as->lock);
    651                 interrupts_restore(ipl);
    652886                return ENOENT;
    653887        }
    654 
    655         if (!src_area->backend || !src_area->backend->share) {
     888       
     889        if ((!src_area->backend) || (!src_area->backend->share)) {
    656890                /*
    657891                 * There is no backend or the backend does not
    658892                 * know how to share the area.
     893                 *
    659894                 */
    660895                mutex_unlock(&src_area->lock);
    661896                mutex_unlock(&src_as->lock);
    662                 interrupts_restore(ipl);
    663897                return ENOTSUP;
    664898        }
    665899       
    666         src_size = src_area->pages * PAGE_SIZE;
    667         src_flags = src_area->flags;
    668         src_backend = src_area->backend;
    669         src_backend_data = src_area->backend_data;
    670 
     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       
    671905        /* Share the cacheable flag from the original mapping */
    672906        if (src_flags & AS_AREA_CACHEABLE)
    673907                dst_flags_mask |= AS_AREA_CACHEABLE;
    674 
    675         if (src_size != acc_size ||
    676             (src_flags & dst_flags_mask) != dst_flags_mask) {
     908       
     909        if ((src_size != acc_size) ||
     910            ((src_flags & dst_flags_mask) != dst_flags_mask)) {
    677911                mutex_unlock(&src_area->lock);
    678912                mutex_unlock(&src_as->lock);
    679                 interrupts_restore(ipl);
    680913                return EPERM;
    681914        }
    682 
     915       
    683916        /*
    684917         * Now we are committed to sharing the area.
    685918         * First, prepare the area for sharing.
    686919         * Then it will be safe to unlock it.
    687          */
    688         sh_info = src_area->sh_info;
     920         *
     921         */
     922        share_info_t *sh_info = src_area->sh_info;
    689923        if (!sh_info) {
    690924                sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
     
    693927                btree_create(&sh_info->pagemap);
    694928                src_area->sh_info = sh_info;
     929               
    695930                /*
    696931                 * Call the backend to setup sharing.
     932                 *
    697933                 */
    698934                src_area->backend->share(src_area);
     
    702938                mutex_unlock(&sh_info->lock);
    703939        }
    704 
     940       
    705941        mutex_unlock(&src_area->lock);
    706942        mutex_unlock(&src_as->lock);
    707 
     943       
    708944        /*
    709945         * Create copy of the source address space area.
     
    713949         * The flags of the source area are masked against dst_flags_mask
    714950         * to support sharing in less privileged mode.
    715          */
    716         dst_area = as_area_create(dst_as, dst_flags_mask, src_size, dst_base,
    717             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);
    718955        if (!dst_area) {
    719956                /*
     
    722959                sh_info_remove_reference(sh_info);
    723960               
    724                 interrupts_restore(ipl);
    725961                return ENOMEM;
    726962        }
    727 
     963       
    728964        /*
    729965         * Now the destination address space area has been
    730966         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    731967         * attribute and set the sh_info.
    732          */     
    733         mutex_lock(&dst_as->lock);     
     968         *
     969         */
     970        mutex_lock(&dst_as->lock);
    734971        mutex_lock(&dst_area->lock);
    735972        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
    736973        dst_area->sh_info = sh_info;
    737974        mutex_unlock(&dst_area->lock);
    738         mutex_unlock(&dst_as->lock);   
    739 
    740         interrupts_restore(ipl);
     975        mutex_unlock(&dst_as->lock);
    741976       
    742977        return 0;
     
    745980/** Check access mode for address space area.
    746981 *
    747  * The address space area must be locked prior to this call.
    748  *
    749  * @param area          Address space area.
    750  * @param access        Access mode.
    751  *
    752  * @return              False if access violates area's permissions, true
    753  *                      otherwise.
    754  */
    755 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)
    756990{
    757991        int flagmap[] = {
     
    761995        };
    762996
     997        ASSERT(mutex_locked(&area->lock));
     998       
    763999        if (!(area->flags & flagmap[access]))
    7641000                return false;
    7651001       
    7661002        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;
    7671029}
    7681030
     
    7811043 *
    7821044 */
    783 int as_area_change_flags(as_t *as, int flags, uintptr_t address)
    784 {
    785         as_area_t *area;
    786         uintptr_t base;
    787         link_t *cur;
    788         ipl_t ipl;
    789         int page_flags;
    790         uintptr_t *old_frame;
    791         size_t frame_idx;
    792         size_t used_pages;
    793        
     1045int as_area_change_flags(as_t *as, unsigned int flags, uintptr_t address)
     1046{
    7941047        /* Flags for the new memory mapping */
    795         page_flags = area_flags_to_page_flags(flags);
    796 
    797         ipl = interrupts_disable();
     1048        unsigned int page_flags = area_flags_to_page_flags(flags);
     1049       
    7981050        mutex_lock(&as->lock);
    799 
    800         area = find_area_and_lock(as, address);
     1051       
     1052        as_area_t *area = find_area_and_lock(as, address);
    8011053        if (!area) {
    8021054                mutex_unlock(&as->lock);
    803                 interrupts_restore(ipl);
    8041055                return ENOENT;
    8051056        }
    806 
     1057       
    8071058        if ((area->sh_info) || (area->backend != &anon_backend)) {
    8081059                /* Copying shared areas not supported yet */
     
    8101061                mutex_unlock(&area->lock);
    8111062                mutex_unlock(&as->lock);
    812                 interrupts_restore(ipl);
    8131063                return ENOTSUP;
    8141064        }
    815 
    816         base = area->base;
    817 
     1065       
    8181066        /*
    8191067         * Compute total number of used pages in the used_space B+tree
    820          */
    821         used_pages = 0;
    822 
     1068         *
     1069         */
     1070        size_t used_pages = 0;
     1071        link_t *cur;
     1072       
    8231073        for (cur = area->used_space.leaf_head.next;
    8241074            cur != &area->used_space.leaf_head; cur = cur->next) {
    825                 btree_node_t *node;
    826                 unsigned int i;
    827                
    828                 node = list_get_instance(cur, btree_node_t, leaf_link);
    829                 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++)
    8301080                        used_pages += (size_t) node->value[i];
    831                 }
    832         }
    833 
     1081        }
     1082       
    8341083        /* An array for storing frame numbers */
    835         old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    836 
     1084        uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     1085       
     1086        page_table_lock(as, false);
     1087       
    8371088        /*
    8381089         * Start TLB shootdown sequence.
    839          */
    840         tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
    841 
     1090         *
     1091         */
     1092        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     1093            area->pages);
     1094       
    8421095        /*
    8431096         * Remove used pages from page tables and remember their frame
    8441097         * numbers.
    845          */
    846         frame_idx = 0;
    847 
     1098         *
     1099         */
     1100        size_t frame_idx = 0;
     1101       
    8481102        for (cur = area->used_space.leaf_head.next;
    8491103            cur != &area->used_space.leaf_head; cur = cur->next) {
    850                 btree_node_t *node;
    851                 unsigned int i;
    852                
    853                 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               
    8541108                for (i = 0; i < node->keys; i++) {
    855                         uintptr_t b = node->key[i];
    856                         size_t j;
    857                         pte_t *pte;
     1109                        uintptr_t ptr = node->key[i];
     1110                        size_t size;
    8581111                       
    859                         for (j = 0; j < (size_t) node->value[i]; j++) {
     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                               
     1119                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
     1120                               
     1121                                /* Remove old mapping */
     1122                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
     1123                        }
     1124                }
     1125        }
     1126       
     1127        /*
     1128         * Finish TLB shootdown sequence.
     1129         *
     1130         */
     1131       
     1132        tlb_invalidate_pages(as->asid, area->base, area->pages);
     1133       
     1134        /*
     1135         * Invalidate potential software translation caches (e.g. TSB on
     1136         * sparc64).
     1137         *
     1138         */
     1139        as_invalidate_translation_cache(as, area->base, area->pages);
     1140        tlb_shootdown_finalize(ipl);
     1141       
     1142        page_table_unlock(as, false);
     1143       
     1144        /*
     1145         * Set the new flags.
     1146         */
     1147        area->flags = flags;
     1148       
     1149        /*
     1150         * Map pages back in with new flags. This step is kept separate
     1151         * so that the memory area could not be accesed with both the old and
     1152         * the new flags at once.
     1153         */
     1154        frame_idx = 0;
     1155       
     1156        for (cur = area->used_space.leaf_head.next;
     1157            cur != &area->used_space.leaf_head; cur = cur->next) {
     1158                btree_node_t *node
     1159                    = list_get_instance(cur, btree_node_t, leaf_link);
     1160                btree_key_t i;
     1161               
     1162                for (i = 0; i < node->keys; i++) {
     1163                        uintptr_t ptr = node->key[i];
     1164                        size_t size;
     1165                       
     1166                        for (size = 0; size < (size_t) node->value[i]; size++) {
    8601167                                page_table_lock(as, false);
    861                                 pte = page_mapping_find(as, b + j * PAGE_SIZE);
    862                                 ASSERT(pte && PTE_VALID(pte) &&
    863                                     PTE_PRESENT(pte));
    864                                 old_frame[frame_idx++] = PTE_GET_FRAME(pte);
    865 
    866                                 /* Remove old mapping */
    867                                 page_mapping_remove(as, b + j * PAGE_SIZE);
     1168                               
     1169                                /* Insert the new mapping */
     1170                                page_mapping_insert(as, ptr + size * PAGE_SIZE,
     1171                                    old_frame[frame_idx++], page_flags);
     1172                               
    8681173                                page_table_unlock(as, false);
    8691174                        }
    8701175                }
    8711176        }
    872 
    873         /*
    874          * Finish TLB shootdown sequence.
    875          */
    876 
    877         tlb_invalidate_pages(as->asid, area->base, area->pages);
    878        
    879         /*
    880          * Invalidate potential software translation caches (e.g. TSB on
    881          * sparc64).
    882          */
    883         as_invalidate_translation_cache(as, area->base, area->pages);
    884         tlb_shootdown_finalize();
    885 
    886         /*
    887          * Set the new flags.
    888          */
    889         area->flags = flags;
    890 
    891         /*
    892          * Map pages back in with new flags. This step is kept separate
    893          * so that the memory area could not be accesed with both the old and
    894          * the new flags at once.
    895          */
    896         frame_idx = 0;
    897 
    898         for (cur = area->used_space.leaf_head.next;
    899             cur != &area->used_space.leaf_head; cur = cur->next) {
    900                 btree_node_t *node;
    901                 unsigned int i;
    902                
    903                 node = list_get_instance(cur, btree_node_t, leaf_link);
    904                 for (i = 0; i < node->keys; i++) {
    905                         uintptr_t b = node->key[i];
    906                         size_t j;
    907                        
    908                         for (j = 0; j < (size_t) node->value[i]; j++) {
    909                                 page_table_lock(as, false);
    910 
    911                                 /* Insert the new mapping */
    912                                 page_mapping_insert(as, b + j * PAGE_SIZE,
    913                                     old_frame[frame_idx++], page_flags);
    914 
    915                                 page_table_unlock(as, false);
    916                         }
    917                 }
    918         }
    919 
     1177       
    9201178        free(old_frame);
    921 
     1179       
    9221180        mutex_unlock(&area->lock);
    9231181        mutex_unlock(&as->lock);
    924         interrupts_restore(ipl);
    925 
     1182       
    9261183        return 0;
    9271184}
    928 
    9291185
    9301186/** Handle page fault within the current address space.
     
    9361192 * Interrupts are assumed disabled.
    9371193 *
    938  * @param page          Faulting page.
    939  * @param access        Access mode that caused the page fault (i.e.
    940  *                      read/write/exec).
    941  * @param istate        Pointer to the interrupted state.
    942  *
    943  * @return              AS_PF_FAULT on page fault, AS_PF_OK on success or
    944  *                      AS_PF_DEFER if the fault was caused by copy_to_uspace()
    945  *                      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 *
    9461204 */
    9471205int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    9481206{
    949         pte_t *pte;
    950         as_area_t *area;
    951        
    9521207        if (!THREAD)
    9531208                return AS_PF_FAULT;
    954                
    955         ASSERT(AS);
    956 
     1209       
     1210        if (!AS)
     1211                return AS_PF_FAULT;
     1212       
    9571213        mutex_lock(&AS->lock);
    958         area = find_area_and_lock(AS, page);   
     1214        as_area_t *area = find_area_and_lock(AS, page);
    9591215        if (!area) {
    9601216                /*
    9611217                 * No area contained mapping for 'page'.
    9621218                 * Signal page fault to low-level handler.
     1219                 *
    9631220                 */
    9641221                mutex_unlock(&AS->lock);
    9651222                goto page_fault;
    9661223        }
    967 
     1224       
    9681225        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    9691226                /*
     
    9731230                mutex_unlock(&area->lock);
    9741231                mutex_unlock(&AS->lock);
    975                 goto page_fault;               
    976         }
    977 
    978         if (!area->backend || !area->backend->page_fault) {
     1232                goto page_fault;
     1233        }
     1234       
     1235        if ((!area->backend) || (!area->backend->page_fault)) {
    9791236                /*
    9801237                 * The address space area is not backed by any backend
    9811238                 * or the backend cannot handle page faults.
     1239                 *
    9821240                 */
    9831241                mutex_unlock(&area->lock);
    9841242                mutex_unlock(&AS->lock);
    985                 goto page_fault;               
    986         }
    987 
     1243                goto page_fault;
     1244        }
     1245       
    9881246        page_table_lock(AS, false);
    9891247       
     
    9911249         * To avoid race condition between two page faults on the same address,
    9921250         * we need to make sure the mapping has not been already inserted.
    993          */
     1251         *
     1252         */
     1253        pte_t *pte;
    9941254        if ((pte = page_mapping_find(AS, page))) {
    9951255                if (PTE_PRESENT(pte)) {
     
    10071267        /*
    10081268         * Resort to the backend page fault handler.
     1269         *
    10091270         */
    10101271        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    10191280        mutex_unlock(&AS->lock);
    10201281        return AS_PF_OK;
    1021 
     1282       
    10221283page_fault:
    10231284        if (THREAD->in_copy_from_uspace) {
     
    10321293                return AS_PF_FAULT;
    10331294        }
    1034 
     1295       
    10351296        return AS_PF_DEFER;
    10361297}
     
    10441305 * When this function is enetered, no spinlocks may be held.
    10451306 *
    1046  * @param old           Old address space or NULL.
    1047  * @param new           New address space.
     1307 * @param old Old address space or NULL.
     1308 * @param new New address space.
     1309 *
    10481310 */
    10491311void as_switch(as_t *old_as, as_t *new_as)
     
    10511313        DEADLOCK_PROBE_INIT(p_asidlock);
    10521314        preemption_disable();
     1315       
    10531316retry:
    10541317        (void) interrupts_disable();
    10551318        if (!spinlock_trylock(&asidlock)) {
    1056                 /* 
     1319                /*
    10571320                 * Avoid deadlock with TLB shootdown.
    10581321                 * We can enable interrupts here because
    10591322                 * preemption is disabled. We should not be
    10601323                 * holding any other lock.
     1324                 *
    10611325                 */
    10621326                (void) interrupts_enable();
     
    10651329        }
    10661330        preemption_enable();
    1067 
     1331       
    10681332        /*
    10691333         * First, take care of the old address space.
    1070          */     
     1334         */
    10711335        if (old_as) {
    10721336                ASSERT(old_as->cpu_refcount);
    1073                 if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
     1337               
     1338                if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    10741339                        /*
    10751340                         * The old address space is no longer active on
     
    10771342                         * list of inactive address spaces with assigned
    10781343                         * ASID.
     1344                         *
    10791345                         */
    10801346                        ASSERT(old_as->asid != ASID_INVALID);
     1347                       
    10811348                        list_append(&old_as->inactive_as_with_asid_link,
    10821349                            &inactive_as_with_asid_head);
    10831350                }
    1084 
     1351               
    10851352                /*
    10861353                 * Perform architecture-specific tasks when the address space
    10871354                 * is being removed from the CPU.
     1355                 *
    10881356                 */
    10891357                as_deinstall_arch(old_as);
    10901358        }
    1091 
     1359       
    10921360        /*
    10931361         * Second, prepare the new address space.
     1362         *
    10941363         */
    10951364        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    10991368                        new_as->asid = asid_get();
    11001369        }
     1370       
    11011371#ifdef AS_PAGE_TABLE
    11021372        SET_PTL0_ADDRESS(new_as->genarch.page_table);
     
    11061376         * Perform architecture-specific steps.
    11071377         * (e.g. write ASID to hardware register etc.)
     1378         *
    11081379         */
    11091380        as_install_arch(new_as);
    1110 
     1381       
    11111382        spinlock_unlock(&asidlock);
    11121383       
     
    11141385}
    11151386
    1116 /** Convert address space area flags to page flags.
    1117  *
    1118  * @param aflags        Flags of some address space area.
    1119  *
    1120  * @return              Flags to be passed to page_mapping_insert().
    1121  */
    1122 int area_flags_to_page_flags(int aflags)
    1123 {
    1124         int flags;
    1125 
    1126         flags = PAGE_USER | PAGE_PRESENT;
    1127        
    1128         if (aflags & AS_AREA_READ)
    1129                 flags |= PAGE_READ;
    1130                
    1131         if (aflags & AS_AREA_WRITE)
    1132                 flags |= PAGE_WRITE;
    1133        
    1134         if (aflags & AS_AREA_EXEC)
    1135                 flags |= PAGE_EXEC;
    1136        
    1137         if (aflags & AS_AREA_CACHEABLE)
    1138                 flags |= PAGE_CACHEABLE;
    1139                
    1140         return flags;
    1141 }
    1142 
    11431387/** Compute flags for virtual address translation subsytem.
    11441388 *
    1145  * The address space area must be locked.
    1146  * Interrupts must be disabled.
    1147  *
    1148  * @param a             Address space area.
    1149  *
    1150  * @return              Flags to be used in page_mapping_insert().
    1151  */
    1152 int as_area_get_flags(as_area_t *a)
    1153 {
    1154         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);
    11551399}
    11561400
     
    11601404 * table.
    11611405 *
    1162  * @param flags         Flags saying whether the page table is for the kernel
    1163  *                      address space.
    1164  *
    1165  * @return              First entry of the page table.
    1166  */
    1167 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)
    11681413{
    11691414        ASSERT(as_operations);
     
    11771422 * Destroy page table in architecture specific way.
    11781423 *
    1179  * @param page_table    Physical address of PTL0.
    1180  */
    1181 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)
    11821428{
    11831429        ASSERT(as_operations);
     
    11911437 * This function should be called before any page_mapping_insert(),
    11921438 * page_mapping_remove() and page_mapping_find().
    1193  * 
     1439 *
    11941440 * Locking order is such that address space areas must be locked
    11951441 * prior to this call. Address space can be locked prior to this
    11961442 * call in which case the lock argument is false.
    11971443 *
    1198  * @param as            Address space.
    1199  * @param lock          If false, do not attempt to lock as->lock.
    1200  */
    1201 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)
    12021449{
    12031450        ASSERT(as_operations);
     
    12091456/** Unlock page table.
    12101457 *
    1211  * @param as            Address space.
    1212  * @param unlock        If false, do not attempt to unlock as->lock.
    1213  */
    1214 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)
    12151463{
    12161464        ASSERT(as_operations);
     
    12201468}
    12211469
    1222 
    1223 /** Find address space area and lock it.
    1224  *
    1225  * The address space must be locked and interrupts must be disabled.
    1226  *
    1227  * @param as            Address space.
    1228  * @param va            Virtual address.
    1229  *
    1230  * @return              Locked address space area containing va on success or
    1231  *                      NULL on failure.
    1232  */
    1233 as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
    1234 {
    1235         as_area_t *a;
    1236         btree_node_t *leaf, *lnode;
    1237         unsigned int i;
    1238        
    1239         a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    1240         if (a) {
    1241                 /* va is the base address of an address space area */
    1242                 mutex_lock(&a->lock);
    1243                 return a;
    1244         }
    1245        
    1246         /*
    1247          * Search the leaf node and the righmost record of its left neighbour
    1248          * to find out whether this is a miss or va belongs to an address
    1249          * space area found there.
    1250          */
    1251        
    1252         /* First, search the leaf node itself. */
    1253         for (i = 0; i < leaf->keys; i++) {
    1254                 a = (as_area_t *) leaf->value[i];
    1255                 mutex_lock(&a->lock);
    1256                 if ((a->base <= va) && (va < a->base + a->pages * PAGE_SIZE)) {
    1257                         return a;
    1258                 }
    1259                 mutex_unlock(&a->lock);
    1260         }
    1261 
    1262         /*
    1263          * Second, locate the left neighbour and test its last record.
    1264          * Because of its position in the B+tree, it must have base < va.
    1265          */
    1266         lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    1267         if (lnode) {
    1268                 a = (as_area_t *) lnode->value[lnode->keys - 1];
    1269                 mutex_lock(&a->lock);
    1270                 if (va < a->base + a->pages * PAGE_SIZE) {
    1271                         return a;
    1272                 }
    1273                 mutex_unlock(&a->lock);
    1274         }
    1275 
    1276         return NULL;
    1277 }
    1278 
    1279 /** Check area conflicts with other areas.
    1280  *
    1281  * The address space must be locked and interrupts must be disabled.
    1282  *
    1283  * @param as            Address space.
    1284  * @param va            Starting virtual address of the area being tested.
    1285  * @param size          Size of the area being tested.
    1286  * @param avoid_area    Do not touch this area.
    1287  *
    1288  * @return              True if there is no conflict, false otherwise.
    1289  */
    1290 bool
    1291 check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
    1292 {
    1293         as_area_t *a;
    1294         btree_node_t *leaf, *node;
    1295         unsigned int i;
    1296        
    1297         /*
    1298          * We don't want any area to have conflicts with NULL page.
    1299          */
    1300         if (overlaps(va, size, NULL, PAGE_SIZE))
    1301                 return false;
    1302        
    1303         /*
    1304          * The leaf node is found in O(log n), where n is proportional to
    1305          * the number of address space areas belonging to as.
    1306          * The check for conflicts is then attempted on the rightmost
    1307          * record in the left neighbour, the leftmost record in the right
    1308          * neighbour and all records in the leaf node itself.
    1309          */
    1310        
    1311         if ((a = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf))) {
    1312                 if (a != avoid_area)
    1313                         return false;
    1314         }
    1315        
    1316         /* First, check the two border cases. */
    1317         if ((node = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf))) {
    1318                 a = (as_area_t *) node->value[node->keys - 1];
    1319                 mutex_lock(&a->lock);
    1320                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1321                         mutex_unlock(&a->lock);
    1322                         return false;
    1323                 }
    1324                 mutex_unlock(&a->lock);
    1325         }
    1326         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    1327         if (node) {
    1328                 a = (as_area_t *) node->value[0];
    1329                 mutex_lock(&a->lock);
    1330                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1331                         mutex_unlock(&a->lock);
    1332                         return false;
    1333                 }
    1334                 mutex_unlock(&a->lock);
    1335         }
    1336        
    1337         /* Second, check the leaf node. */
    1338         for (i = 0; i < leaf->keys; i++) {
    1339                 a = (as_area_t *) leaf->value[i];
    1340        
    1341                 if (a == avoid_area)
    1342                         continue;
    1343        
    1344                 mutex_lock(&a->lock);
    1345                 if (overlaps(va, size, a->base, a->pages * PAGE_SIZE)) {
    1346                         mutex_unlock(&a->lock);
    1347                         return false;
    1348                 }
    1349                 mutex_unlock(&a->lock);
    1350         }
    1351 
    1352         /*
    1353          * So far, the area does not conflict with other areas.
    1354          * Check if it doesn't conflict with kernel address space.
    1355          */     
    1356         if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    1357                 return !overlaps(va, size,
    1358                     KERNEL_ADDRESS_SPACE_START,
    1359                     KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    1360         }
    1361 
    1362         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);
    13631483}
    13641484
    13651485/** Return size of the address space area with given base.
    13661486 *
    1367  * @param base          Arbitrary address insede the address space area.
    1368  *
    1369  * @return              Size of the address space area in bytes or zero if it
    1370  *                      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 *
    13711492 */
    13721493size_t as_area_get_size(uintptr_t base)
    13731494{
    1374         ipl_t ipl;
    1375         as_area_t *src_area;
    13761495        size_t size;
    1377 
    1378         ipl = interrupts_disable();
    1379         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       
    13801500        if (src_area) {
    13811501                size = src_area->pages * PAGE_SIZE;
    13821502                mutex_unlock(&src_area->lock);
    1383         } else {
     1503        } else
    13841504                size = 0;
    1385         }
    1386         interrupts_restore(ipl);
     1505       
     1506        page_table_unlock(AS, true);
    13871507        return size;
    13881508}
     
    13921512 * The address space area must be already locked.
    13931513 *
    1394  * @param a             Address space area.
    1395  * @param page          First page to be marked.
    1396  * @param count         Number of page to be marked.
    1397  *
    1398  * @return              Zero on failure and non-zero on success.
    1399  */
    1400 int used_space_insert(as_area_t *a, uintptr_t page, size_t count)
    1401 {
    1402         btree_node_t *leaf, *node;
    1403         size_t pages;
    1404         unsigned int i;
    1405 
     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));
    14061524        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    14071525        ASSERT(count);
    1408 
    1409         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);
    14101529        if (pages) {
    14111530                /*
    14121531                 * We hit the beginning of some used space.
     1532                 *
    14131533                 */
    14141534                return 0;
    14151535        }
    1416 
     1536       
    14171537        if (!leaf->keys) {
    1418                 btree_insert(&a->used_space, page, (void *) count, leaf);
     1538                btree_insert(&area->used_space, page, (void *) count, leaf);
    14191539                return 1;
    14201540        }
    1421 
    1422         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);
    14231543        if (node) {
    14241544                uintptr_t left_pg = node->key[node->keys - 1];
     
    14311551                 * somewhere between the rightmost interval of
    14321552                 * the left neigbour and the first interval of the leaf.
    1433                  */
    1434                  
     1553                 *
     1554                 */
     1555               
    14351556                if (page >= right_pg) {
    14361557                        /* Do nothing. */
     
    14421563                    right_cnt * PAGE_SIZE)) {
    14431564                        /* The interval intersects with the right interval. */
    1444                         return 0;                       
     1565                        return 0;
    14451566                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    14461567                    (page + count * PAGE_SIZE == right_pg)) {
     
    14481569                         * The interval can be added by merging the two already
    14491570                         * present intervals.
     1571                         *
    14501572                         */
    14511573                        node->value[node->keys - 1] += count + right_cnt;
    1452                         btree_remove(&a->used_space, right_pg, leaf);
    1453                         return 1; 
     1574                        btree_remove(&area->used_space, right_pg, leaf);
     1575                        return 1;
    14541576                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    1455                         /* 
     1577                        /*
    14561578                         * The interval can be added by simply growing the left
    14571579                         * interval.
     1580                         *
    14581581                         */
    14591582                        node->value[node->keys - 1] += count;
     
    14641587                         * the right interval down and increasing its size
    14651588                         * accordingly.
     1589                         *
    14661590                         */
    14671591                        leaf->value[0] += count;
     
    14721596                         * The interval is between both neigbouring intervals,
    14731597                         * but cannot be merged with any of them.
     1598                         *
    14741599                         */
    1475                         btree_insert(&a->used_space, page, (void *) count,
     1600                        btree_insert(&area->used_space, page, (void *) count,
    14761601                            leaf);
    14771602                        return 1;
     
    14801605                uintptr_t right_pg = leaf->key[0];
    14811606                size_t right_cnt = (size_t) leaf->value[0];
    1482        
     1607               
    14831608                /*
    14841609                 * Investigate the border case in which the left neighbour does
    14851610                 * not exist but the interval fits from the left.
    1486                  */
    1487                  
     1611                 *
     1612                 */
     1613               
    14881614                if (overlaps(page, count * PAGE_SIZE, right_pg,
    14891615                    right_cnt * PAGE_SIZE)) {
     
    14951621                         * right interval down and increasing its size
    14961622                         * accordingly.
     1623                         *
    14971624                         */
    14981625                        leaf->key[0] = page;
     
    15031630                         * The interval doesn't adjoin with the right interval.
    15041631                         * It must be added individually.
     1632                         *
    15051633                         */
    1506                         btree_insert(&a->used_space, page, (void *) count,
     1634                        btree_insert(&area->used_space, page, (void *) count,
    15071635                            leaf);
    15081636                        return 1;
    15091637                }
    15101638        }
    1511 
    1512         node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
     1639       
     1640        node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
    15131641        if (node) {
    15141642                uintptr_t left_pg = leaf->key[leaf->keys - 1];
     
    15211649                 * somewhere between the leftmost interval of
    15221650                 * the right neigbour and the last interval of the leaf.
    1523                  */
    1524 
     1651                 *
     1652                 */
     1653               
    15251654                if (page < left_pg) {
    15261655                        /* Do nothing. */
     
    15321661                    right_cnt * PAGE_SIZE)) {
    15331662                        /* The interval intersects with the right interval. */
    1534                         return 0;                       
     1663                        return 0;
    15351664                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    15361665                    (page + count * PAGE_SIZE == right_pg)) {
     
    15381667                         * The interval can be added by merging the two already
    15391668                         * present intervals.
    1540                          * */
     1669                         *
     1670                         */
    15411671                        leaf->value[leaf->keys - 1] += count + right_cnt;
    1542                         btree_remove(&a->used_space, right_pg, node);
    1543                         return 1; 
     1672                        btree_remove(&area->used_space, right_pg, node);
     1673                        return 1;
    15441674                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    15451675                        /*
    15461676                         * The interval can be added by simply growing the left
    15471677                         * interval.
    1548                          * */
     1678                         *
     1679                         */
    15491680                        leaf->value[leaf->keys - 1] +=  count;
    15501681                        return 1;
     
    15541685                         * the right interval down and increasing its size
    15551686                         * accordingly.
     1687                         *
    15561688                         */
    15571689                        node->value[0] += count;
     
    15621694                         * The interval is between both neigbouring intervals,
    15631695                         * but cannot be merged with any of them.
     1696                         *
    15641697                         */
    1565                         btree_insert(&a->used_space, page, (void *) count,
     1698                        btree_insert(&area->used_space, page, (void *) count,
    15661699                            leaf);
    15671700                        return 1;
     
    15701703                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    15711704                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1572        
     1705               
    15731706                /*
    15741707                 * Investigate the border case in which the right neighbour
    15751708                 * does not exist but the interval fits from the right.
    1576                  */
    1577                  
     1709                 *
     1710                 */
     1711               
    15781712                if (overlaps(page, count * PAGE_SIZE, left_pg,
    15791713                    left_cnt * PAGE_SIZE)) {
     
    15841718                         * The interval can be added by growing the left
    15851719                         * interval.
     1720                         *
    15861721                         */
    15871722                        leaf->value[leaf->keys - 1] += count;
     
    15911726                         * The interval doesn't adjoin with the left interval.
    15921727                         * It must be added individually.
     1728                         *
    15931729                         */
    1594                         btree_insert(&a->used_space, page, (void *) count,
     1730                        btree_insert(&area->used_space, page, (void *) count,
    15951731                            leaf);
    15961732                        return 1;
     
    16021738         * only between two other intervals of the leaf. The two border cases
    16031739         * were already resolved.
    1604          */
     1740         *
     1741         */
     1742        btree_key_t i;
    16051743        for (i = 1; i < leaf->keys; i++) {
    16061744                if (page < leaf->key[i]) {
     
    16091747                        size_t left_cnt = (size_t) leaf->value[i - 1];
    16101748                        size_t right_cnt = (size_t) leaf->value[i];
    1611 
     1749                       
    16121750                        /*
    16131751                         * The interval fits between left_pg and right_pg.
     1752                         *
    16141753                         */
    1615 
     1754                       
    16161755                        if (overlaps(page, count * PAGE_SIZE, left_pg,
    16171756                            left_cnt * PAGE_SIZE)) {
     
    16191758                                 * The interval intersects with the left
    16201759                                 * interval.
     1760                                 *
    16211761                                 */
    16221762                                return 0;
     
    16261766                                 * The interval intersects with the right
    16271767                                 * interval.
     1768                                 *
    16281769                                 */
    1629                                 return 0;                       
     1770                                return 0;
    16301771                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    16311772                            (page + count * PAGE_SIZE == right_pg)) {
     
    16331774                                 * The interval can be added by merging the two
    16341775                                 * already present intervals.
     1776                                 *
    16351777                                 */
    16361778                                leaf->value[i - 1] += count + right_cnt;
    1637                                 btree_remove(&a->used_space, right_pg, leaf);
    1638                                 return 1; 
     1779                                btree_remove(&area->used_space, right_pg, leaf);
     1780                                return 1;
    16391781                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16401782                                /*
    16411783                                 * The interval can be added by simply growing
    16421784                                 * the left interval.
     1785                                 *
    16431786                                 */
    16441787                                leaf->value[i - 1] += count;
     
    16461789                        } else if (page + count * PAGE_SIZE == right_pg) {
    16471790                                /*
    1648                                 * The interval can be addded by simply moving
     1791                                * The interval can be addded by simply moving
    16491792                                 * base of the right interval down and
    16501793                                 * increasing its size accordingly.
    1651                                  */
     1794                                 *
     1795                                 */
    16521796                                leaf->value[i] += count;
    16531797                                leaf->key[i] = page;
     
    16581802                                 * intervals, but cannot be merged with any of
    16591803                                 * them.
     1804                                 *
    16601805                                 */
    1661                                 btree_insert(&a->used_space, page,
     1806                                btree_insert(&area->used_space, page,
    16621807                                    (void *) count, leaf);
    16631808                                return 1;
     
    16651810                }
    16661811        }
    1667 
    1668         panic("Inconsistency detected while adding %" PRIs " pages of used "
    1669             "space at %p.", count, page);
     1812       
     1813        panic("Inconsistency detected while adding %zu pages of used "
     1814            "space at %p.", count, (void *) page);
    16701815}
    16711816
     
    16741819 * The address space area must be already locked.
    16751820 *
    1676  * @param a             Address space area.
    1677  * @param page          First page to be marked.
    1678  * @param count         Number of page to be marked.
    1679  *
    1680  * @return              Zero on failure and non-zero on success.
    1681  */
    1682 int used_space_remove(as_area_t *a, uintptr_t page, size_t count)
    1683 {
    1684         btree_node_t *leaf, *node;
    1685         size_t pages;
    1686         unsigned int i;
    1687 
     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));
    16881831        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    16891832        ASSERT(count);
    1690 
    1691         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);
    16921836        if (pages) {
    16931837                /*
    16941838                 * We are lucky, page is the beginning of some interval.
     1839                 *
    16951840                 */
    16961841                if (count > pages) {
    16971842                        return 0;
    16981843                } else if (count == pages) {
    1699                         btree_remove(&a->used_space, page, leaf);
     1844                        btree_remove(&area->used_space, page, leaf);
    17001845                        return 1;
    17011846                } else {
     
    17031848                         * Find the respective interval.
    17041849                         * Decrease its size and relocate its start address.
     1850                         *
    17051851                         */
     1852                        btree_key_t i;
    17061853                        for (i = 0; i < leaf->keys; i++) {
    17071854                                if (leaf->key[i] == page) {
     
    17141861                }
    17151862        }
    1716 
    1717         node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
    1718         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])) {
    17191866                uintptr_t left_pg = node->key[node->keys - 1];
    17201867                size_t left_cnt = (size_t) node->value[node->keys - 1];
    1721 
     1868               
    17221869                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17231870                    count * PAGE_SIZE)) {
     
    17291876                                 * removed by updating the size of the bigger
    17301877                                 * interval.
     1878                                 *
    17311879                                 */
    17321880                                node->value[node->keys - 1] -= count;
     
    17341882                        } else if (page + count * PAGE_SIZE <
    17351883                            left_pg + left_cnt*PAGE_SIZE) {
    1736                                 size_t new_cnt;
    1737                                
    17381884                                /*
    17391885                                 * The interval is contained in the rightmost
     
    17421888                                 * the original interval and also inserting a
    17431889                                 * new interval.
     1890                                 *
    17441891                                 */
    1745                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1892                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    17461893                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    17471894                                node->value[node->keys - 1] -= count + new_cnt;
    1748                                 btree_insert(&a->used_space, page +
     1895                                btree_insert(&area->used_space, page +
    17491896                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    17501897                                return 1;
     
    17521899                }
    17531900                return 0;
    1754         } else if (page < leaf->key[0]) {
     1901        } else if (page < leaf->key[0])
    17551902                return 0;
    1756         }
    17571903       
    17581904        if (page > leaf->key[leaf->keys - 1]) {
    17591905                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    17601906                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1761 
     1907               
    17621908                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    17631909                    count * PAGE_SIZE)) {
    1764                         if (page + count * PAGE_SIZE == 
     1910                        if (page + count * PAGE_SIZE ==
    17651911                            left_pg + left_cnt * PAGE_SIZE) {
    17661912                                /*
     
    17681914                                 * interval of the leaf and can be removed by
    17691915                                 * updating the size of the bigger interval.
     1916                                 *
    17701917                                 */
    17711918                                leaf->value[leaf->keys - 1] -= count;
     
    17731920                        } else if (page + count * PAGE_SIZE < left_pg +
    17741921                            left_cnt * PAGE_SIZE) {
    1775                                 size_t new_cnt;
    1776                                
    17771922                                /*
    17781923                                 * The interval is contained in the rightmost
     
    17811926                                 * original interval and also inserting a new
    17821927                                 * interval.
     1928                                 *
    17831929                                 */
    1784                                 new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1930                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    17851931                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    17861932                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    1787                                 btree_insert(&a->used_space, page +
     1933                                btree_insert(&area->used_space, page +
    17881934                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    17891935                                return 1;
     
    17911937                }
    17921938                return 0;
    1793         }       
     1939        }
    17941940       
    17951941        /*
     
    17971943         * Now the interval can be only between intervals of the leaf.
    17981944         */
     1945        btree_key_t i;
    17991946        for (i = 1; i < leaf->keys - 1; i++) {
    18001947                if (page < leaf->key[i]) {
    18011948                        uintptr_t left_pg = leaf->key[i - 1];
    18021949                        size_t left_cnt = (size_t) leaf->value[i - 1];
    1803 
     1950                       
    18041951                        /*
    18051952                         * Now the interval is between intervals corresponding
     
    18151962                                         * be removed by updating the size of
    18161963                                         * the bigger interval.
     1964                                         *
    18171965                                         */
    18181966                                        leaf->value[i - 1] -= count;
     
    18201968                                } else if (page + count * PAGE_SIZE <
    18211969                                    left_pg + left_cnt * PAGE_SIZE) {
    1822                                         size_t new_cnt;
    1823                                
    18241970                                        /*
    18251971                                         * The interval is contained in the
     
    18291975                                         * also inserting a new interval.
    18301976                                         */
    1831                                         new_cnt = ((left_pg +
     1977                                        size_t new_cnt = ((left_pg +
    18321978                                            left_cnt * PAGE_SIZE) -
    18331979                                            (page + count * PAGE_SIZE)) >>
    18341980                                            PAGE_WIDTH;
    18351981                                        leaf->value[i - 1] -= count + new_cnt;
    1836                                         btree_insert(&a->used_space, page +
     1982                                        btree_insert(&area->used_space, page +
    18371983                                            count * PAGE_SIZE, (void *) new_cnt,
    18381984                                            leaf);
     
    18431989                }
    18441990        }
    1845 
     1991       
    18461992error:
    1847         panic("Inconsistency detected while removing %" PRIs " pages of used "
    1848             "space from %p.", count, page);
    1849 }
    1850 
    1851 /** Remove reference to address space area share info.
    1852  *
    1853  * If the reference count drops to 0, the sh_info is deallocated.
    1854  *
    1855  * @param sh_info       Pointer to address space area share info.
    1856  */
    1857 void sh_info_remove_reference(share_info_t *sh_info)
    1858 {
    1859         bool dealloc = false;
    1860 
    1861         mutex_lock(&sh_info->lock);
    1862         ASSERT(sh_info->refcount);
    1863         if (--sh_info->refcount == 0) {
    1864                 dealloc = true;
    1865                 link_t *cur;
    1866                
    1867                 /*
    1868                  * Now walk carefully the pagemap B+tree and free/remove
    1869                  * reference from all frames found there.
    1870                  */
    1871                 for (cur = sh_info->pagemap.leaf_head.next;
    1872                     cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
    1873                         btree_node_t *node;
    1874                         unsigned int i;
    1875                        
    1876                         node = list_get_instance(cur, btree_node_t, leaf_link);
    1877                         for (i = 0; i < node->keys; i++)
    1878                                 frame_free((uintptr_t) node->value[i]);
    1879                 }
    1880                
    1881         }
    1882         mutex_unlock(&sh_info->lock);
    1883        
    1884         if (dealloc) {
    1885                 btree_destroy(&sh_info->pagemap);
    1886                 free(sh_info);
    1887         }
     1993        panic("Inconsistency detected while removing %zu pages of used "
     1994            "space from %p.", count, (void *) page);
    18881995}
    18891996
     
    18932000
    18942001/** Wrapper for as_area_create(). */
    1895 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)
    18962003{
    18972004        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
     
    19032010
    19042011/** Wrapper for as_area_resize(). */
    1905 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)
    19062013{
    19072014        return (unative_t) as_area_resize(AS, address, size, 0);
     
    19092016
    19102017/** Wrapper for as_area_change_flags(). */
    1911 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)
    19122019{
    19132020        return (unative_t) as_area_change_flags(AS, flags, address);
     
    19222029/** Get list of adress space areas.
    19232030 *
    1924  * @param as            Address space.
    1925  * @param obuf          Place to save pointer to returned buffer.
    1926  * @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 *
    19272035 */
    19282036void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
    19292037{
    1930         ipl_t ipl;
    1931         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;
    19322043        link_t *cur;
    1933 
    1934         as_area_info_t *info;
    1935         size_t isize;
    1936 
    1937         ipl = interrupts_disable();
    1938         mutex_lock(&as->lock);
    1939 
    1940         /* First pass, count number of areas. */
    1941 
    1942         area_cnt = 0;
    1943 
     2044       
    19442045        for (cur = as->as_area_btree.leaf_head.next;
    19452046            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1946                 btree_node_t *node;
    1947 
    1948                 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);
    19492049                area_cnt += node->keys;
    19502050        }
    1951 
    1952         isize = area_cnt * sizeof(as_area_info_t);
    1953         info = malloc(isize, 0);
    1954 
     2051       
     2052        size_t isize = area_cnt * sizeof(as_area_info_t);
     2053        as_area_info_t *info = malloc(isize, 0);
     2054       
    19552055        /* Second pass, record data. */
    1956 
    1957         area_idx = 0;
    1958 
     2056       
     2057        size_t area_idx = 0;
     2058       
    19592059        for (cur = as->as_area_btree.leaf_head.next;
    19602060            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1961                 btree_node_t *node;
    1962 
    1963                 node = list_get_instance(cur, btree_node_t, leaf_link);
    1964 
     2061                btree_node_t *node =
     2062                    list_get_instance(cur, btree_node_t, leaf_link);
     2063                btree_key_t i;
     2064               
    19652065                for (i = 0; i < node->keys; i++) {
    19662066                        as_area_t *area = node->value[i];
    1967 
     2067                       
    19682068                        ASSERT(area_idx < area_cnt);
    19692069                        mutex_lock(&area->lock);
    1970 
     2070                       
    19712071                        info[area_idx].start_addr = area->base;
    19722072                        info[area_idx].size = FRAMES2SIZE(area->pages);
    19732073                        info[area_idx].flags = area->flags;
    19742074                        ++area_idx;
    1975 
     2075                       
    19762076                        mutex_unlock(&area->lock);
    19772077                }
    19782078        }
    1979 
     2079       
    19802080        mutex_unlock(&as->lock);
    1981         interrupts_restore(ipl);
    1982 
     2081       
    19832082        *obuf = info;
    19842083        *osize = isize;
    19852084}
    19862085
    1987 
    19882086/** Print out information about address space.
    19892087 *
    1990  * @param as            Address space.
     2088 * @param as Address space.
     2089 *
    19912090 */
    19922091void as_print(as_t *as)
    19932092{
    1994         ipl_t ipl;
    1995        
    1996         ipl = interrupts_disable();
    19972093        mutex_lock(&as->lock);
    19982094       
     
    20012097        for (cur = as->as_area_btree.leaf_head.next;
    20022098            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2003                 btree_node_t *node;
    2004                
    2005                 node = list_get_instance(cur, btree_node_t, leaf_link);
    2006                
    2007                 unsigned int i;
     2099                btree_node_t *node
     2100                    = list_get_instance(cur, btree_node_t, leaf_link);
     2101                btree_key_t i;
     2102               
    20082103                for (i = 0; i < node->keys; i++) {
    20092104                        as_area_t *area = node->value[i];
    2010                
     2105                       
    20112106                        mutex_lock(&area->lock);
    2012                         printf("as_area: %p, base=%p, pages=%" PRIs
    2013                             " (%p - %p)\n", area, area->base, area->pages,
    2014                             area->base, area->base + FRAMES2SIZE(area->pages));
     2107                        printf("as_area: %p, base=%p, pages=%zu"
     2108                            " (%p - %p)\n", area, (void *) area->base,
     2109                            area->pages, (void *) area->base,
     2110                            (void *) (area->base + FRAMES2SIZE(area->pages)));
    20152111                        mutex_unlock(&area->lock);
    20162112                }
     
    20182114       
    20192115        mutex_unlock(&as->lock);
    2020         interrupts_restore(ipl);
    20212116}
    20222117
Note: See TracChangeset for help on using the changeset viewer.