Ignore:
File:
1 edited

Legend:

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

    r7e752b2 r336db295  
    11/*
    2  * Copyright (c) 2010 Jakub Jermar
     2 * Copyright (c) 2001-2006 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 <typedefs.h>
     77#include <arch/types.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  *
    8988 */
    9089as_operations_t *as_operations = NULL;
     
    9291/**
    9392 * Slab for as_t objects.
    94  *
    9593 */
    9694static slab_cache_t *as_slab;
     
    102100 * - as->asid for each as of the as_t type
    103101 * - asids_allocated counter
    104  *
    105102 */
    106103SPINLOCK_INITIALIZE(asidlock);
     
    109106 * This list contains address spaces that are not active on any
    110107 * processor and that have valid ASID.
    111  *
    112108 */
    113109LIST_INITIALIZE(inactive_as_with_asid_head);
     
    116112as_t *AS_KERNEL = NULL;
    117113
    118 NO_TRACE static int as_constructor(void *obj, unsigned int flags)
     114static int area_flags_to_page_flags(int);
     115static as_area_t *find_area_and_lock(as_t *, uintptr_t);
     116static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
     117static void sh_info_remove_reference(share_info_t *);
     118
     119static int as_constructor(void *obj, int flags)
    119120{
    120121        as_t *as = (as_t *) obj;
    121        
     122        int rc;
     123
    122124        link_initialize(&as->inactive_as_with_asid_link);
    123125        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    124126       
    125         int rc = as_constructor_arch(as, flags);
     127        rc = as_constructor_arch(as, flags);
    126128       
    127129        return rc;
    128130}
    129131
    130 NO_TRACE static size_t as_destructor(void *obj)
     132static int as_destructor(void *obj)
    131133{
    132134        as_t *as = (as_t *) obj;
     135
    133136        return as_destructor_arch(as);
    134137}
     
    138141{
    139142        as_arch_init();
    140        
     143
    141144        as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
    142145            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
     
    149152         * reference count never drops to zero.
    150153         */
    151         as_hold(AS_KERNEL);
     154        atomic_set(&AS_KERNEL->refcount, 1);
    152155}
    153156
    154157/** Create address space.
    155158 *
    156  * @param flags Flags that influence the way in wich the address
    157  *              space is created.
    158  *
    159  */
    160 as_t *as_create(unsigned int flags)
    161 {
    162         as_t *as = (as_t *) slab_alloc(as_slab, 0);
     159 * @param flags         Flags that influence the way in wich the address space
     160 *                      is created.
     161 */
     162as_t *as_create(int flags)
     163{
     164        as_t *as;
     165
     166        as = (as_t *) slab_alloc(as_slab, 0);
    163167        (void) as_create_arch(as, 0);
    164168       
     
    172176        atomic_set(&as->refcount, 0);
    173177        as->cpu_refcount = 0;
    174        
    175178#ifdef AS_PAGE_TABLE
    176179        as->genarch.page_table = page_table_create(flags);
     
    189192 * We know that we don't hold any spinlock.
    190193 *
    191  * @param as Address space to be destroyed.
    192  *
     194 * @param as            Address space to be destroyed.
    193195 */
    194196void as_destroy(as_t *as)
    195197{
     198        ipl_t ipl;
     199        bool cond;
    196200        DEADLOCK_PROBE_INIT(p_asidlock);
    197201
    198         ASSERT(as != AS);
    199202        ASSERT(atomic_get(&as->refcount) == 0);
    200203       
    201204        /*
    202          * Since there is no reference to this address space, it is safe not to
    203          * lock its mutex.
     205         * Since there is no reference to this area,
     206         * it is safe not to lock its mutex.
    204207         */
    205208
     
    210213         * disabled to prevent nested context switches. We also depend on the
    211214         * fact that so far no spinlocks are held.
    212          *
    213215         */
    214216        preemption_disable();
    215         ipl_t ipl = interrupts_read();
    216        
     217        ipl = interrupts_read();
    217218retry:
    218219        interrupts_disable();
     
    222223                goto retry;
    223224        }
    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)
     225        preemption_enable();    /* Interrupts disabled, enable preemption */
     226        if (as->asid != ASID_INVALID && as != AS_KERNEL) {
     227                if (as != AS && as->cpu_refcount == 0)
    230228                        list_remove(&as->inactive_as_with_asid_link);
    231                
    232229                asid_put(as->asid);
    233230        }
    234        
    235231        spinlock_unlock(&asidlock);
    236         interrupts_restore(ipl);
    237 
    238        
     232
    239233        /*
    240234         * Destroy address space areas of the address space.
    241235         * The B+tree must be walked carefully because it is
    242236         * also being destroyed.
    243          *
    244          */
    245         bool cond = true;
    246         while (cond) {
     237         */     
     238        for (cond = true; cond; ) {
     239                btree_node_t *node;
     240
    247241                ASSERT(!list_empty(&as->as_area_btree.leaf_head));
    248                
    249                 btree_node_t *node =
    250                     list_get_instance(as->as_area_btree.leaf_head.next,
     242                node = list_get_instance(as->as_area_btree.leaf_head.next,
    251243                    btree_node_t, leaf_link);
    252                
    253                 if ((cond = node->keys))
     244
     245                if ((cond = node->keys)) {
    254246                        as_area_destroy(as, node->key[0]);
    255         }
    256        
     247                }
     248        }
     249
    257250        btree_destroy(&as->as_area_btree);
    258        
    259251#ifdef AS_PAGE_TABLE
    260252        page_table_destroy(as->genarch.page_table);
     
    262254        page_table_destroy(NULL);
    263255#endif
    264        
     256
     257        interrupts_restore(ipl);
     258
    265259        slab_free(as_slab, as);
    266260}
    267261
    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  */
    276 NO_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  */
    289 NO_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  */
    305 NO_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 
    395262/** Create address space area of common attributes.
    396263 *
    397264 * The created address space area is added to the target address space.
    398265 *
    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  */
    410 as_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 {
     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 */
     276as_area_t *
     277as_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       
    414283        if (base % PAGE_SIZE)
    415284                return NULL;
    416        
     285
    417286        if (!size)
    418287                return NULL;
    419        
     288
    420289        /* Writeable executable areas are not supported. */
    421290        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    422291                return NULL;
    423292       
     293        ipl = interrupts_disable();
    424294        mutex_lock(&as->lock);
    425295       
    426296        if (!check_area_conflicts(as, base, size, NULL)) {
    427297                mutex_unlock(&as->lock);
     298                interrupts_restore(ipl);
    428299                return NULL;
    429300        }
    430301       
    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        
     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;
    443313        if (backend_data)
    444                 area->backend_data = *backend_data;
     314                a->backend_data = *backend_data;
    445315        else
    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        
     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
    451322        mutex_unlock(&as->lock);
    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  */
    465 NO_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;
     323        interrupts_restore(ipl);
     324
     325        return a;
    516326}
    517327
    518328/** Find address space area and change it.
    519329 *
    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  */
    530 int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags)
    531 {
     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 */
     339int 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();
    532346        mutex_lock(&as->lock);
    533347       
    534348        /*
    535349         * Locate the area.
    536          *
    537          */
    538         as_area_t *area = find_area_and_lock(as, address);
     350         */
     351        area = find_area_and_lock(as, address);
    539352        if (!area) {
    540353                mutex_unlock(&as->lock);
     354                interrupts_restore(ipl);
    541355                return ENOENT;
    542356        }
    543        
     357
    544358        if (area->backend == &phys_backend) {
    545359                /*
    546360                 * Remapping of address space areas associated
    547361                 * with memory mapped devices is not supported.
    548                  *
    549362                 */
    550363                mutex_unlock(&area->lock);
    551364                mutex_unlock(&as->lock);
     365                interrupts_restore(ipl);
    552366                return ENOTSUP;
    553367        }
    554        
    555368        if (area->sh_info) {
    556369                /*
    557                  * Remapping of shared address space areas
     370                 * Remapping of shared address space areas 
    558371                 * is not supported.
    559                  *
    560372                 */
    561373                mutex_unlock(&area->lock);
    562374                mutex_unlock(&as->lock);
     375                interrupts_restore(ipl);
    563376                return ENOTSUP;
    564377        }
    565        
    566         size_t pages = SIZE2FRAMES((address - area->base) + size);
     378
     379        pages = SIZE2FRAMES((address - area->base) + size);
    567380        if (!pages) {
    568381                /*
    569382                 * Zero size address space areas are not allowed.
    570                  *
    571383                 */
    572384                mutex_unlock(&area->lock);
    573385                mutex_unlock(&as->lock);
     386                interrupts_restore(ipl);
    574387                return EPERM;
    575388        }
    576389       
    577390        if (pages < area->pages) {
     391                bool cond;
    578392                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    579                
     393
    580394                /*
    581395                 * Shrinking the area.
    582396                 * No need to check for overlaps.
    583                  *
    584                  */
    585                
    586                 page_table_lock(as, false);
    587                
     397                 */
     398
    588399                /*
    589400                 * Start TLB shootdown sequence.
    590                  *
    591                  */
    592                 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    593                     area->base + pages * PAGE_SIZE, area->pages - pages);
    594                
     401                 */
     402                tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
     403                    pages * PAGE_SIZE, area->pages - pages);
     404
    595405                /*
    596406                 * Remove frames belonging to used space starting from
     
    599409                 * is also the right way to remove part of the used_space
    600410                 * B+tree leaf list.
    601                  *
    602                  */
    603                 bool cond = true;
    604                 while (cond) {
     411                 */             
     412                for (cond = true; cond;) {
     413                        btree_node_t *node;
     414               
    605415                        ASSERT(!list_empty(&area->used_space.leaf_head));
    606                        
    607                         btree_node_t *node =
     416                        node =
    608417                            list_get_instance(area->used_space.leaf_head.prev,
    609418                            btree_node_t, leaf_link);
     419                        if ((cond = (bool) node->keys)) {
     420                                uintptr_t b = node->key[node->keys - 1];
     421                                size_t c =
     422                                    (size_t) node->value[node->keys - 1];
     423                                unsigned int i = 0;
    610424                       
    611                         if ((cond = (bool) node->keys)) {
    612                                 uintptr_t ptr = node->key[node->keys - 1];
    613                                 size_t size =
    614                                     (size_t) node->value[node->keys - 1];
    615                                 size_t i = 0;
    616                                
    617                                 if (overlaps(ptr, size * PAGE_SIZE, area->base,
     425                                if (overlaps(b, c * PAGE_SIZE, area->base,
    618426                                    pages * PAGE_SIZE)) {
    619427                                       
    620                                         if (ptr + size * PAGE_SIZE <= start_free) {
     428                                        if (b + c * PAGE_SIZE <= start_free) {
    621429                                                /*
    622430                                                 * The whole interval fits
    623431                                                 * completely in the resized
    624432                                                 * address space area.
    625                                                  *
    626433                                                 */
    627434                                                break;
    628435                                        }
    629                                        
     436               
    630437                                        /*
    631438                                         * Part of the interval corresponding
    632439                                         * to b and c overlaps with the resized
    633440                                         * address space area.
    634                                          *
    635441                                         */
    636                                        
    637                                         /* We are almost done */
    638                                         cond = false;
    639                                         i = (start_free - ptr) >> PAGE_WIDTH;
     442               
     443                                        cond = false;   /* we are almost done */
     444                                        i = (start_free - b) >> PAGE_WIDTH;
    640445                                        if (!used_space_remove(area, start_free,
    641                                             size - i))
    642                                                 panic("Cannot remove used space.");
     446                                            c - i))
     447                                                panic("Cannot remove used "
     448                                                    "space.");
    643449                                } else {
    644450                                        /*
     
    646452                                         * completely removed.
    647453                                         */
    648                                         if (!used_space_remove(area, ptr, size))
    649                                                 panic("Cannot remove used space.");
     454                                        if (!used_space_remove(area, b, c))
     455                                                panic("Cannot remove used "
     456                                                    "space.");
    650457                                }
    651                                
    652                                 for (; i < size; i++) {
    653                                         pte_t *pte = page_mapping_find(as, ptr +
     458                       
     459                                for (; i < c; i++) {
     460                                        pte_t *pte;
     461                       
     462                                        page_table_lock(as, false);
     463                                        pte = page_mapping_find(as, b +
    654464                                            i * PAGE_SIZE);
    655                                        
    656                                         ASSERT(pte);
    657                                         ASSERT(PTE_VALID(pte));
    658                                         ASSERT(PTE_PRESENT(pte));
    659                                        
    660                                         if ((area->backend) &&
    661                                             (area->backend->frame_free)) {
     465                                        ASSERT(pte && PTE_VALID(pte) &&
     466                                            PTE_PRESENT(pte));
     467                                        if (area->backend &&
     468                                            area->backend->frame_free) {
    662469                                                area->backend->frame_free(area,
    663                                                     ptr + i * PAGE_SIZE,
     470                                                    b + i * PAGE_SIZE,
    664471                                                    PTE_GET_FRAME(pte));
    665472                                        }
    666                                        
    667                                         page_mapping_remove(as, ptr +
     473                                        page_mapping_remove(as, b +
    668474                                            i * PAGE_SIZE);
     475                                        page_table_unlock(as, false);
    669476                                }
    670477                        }
    671478                }
    672                
     479
    673480                /*
    674481                 * Finish TLB shootdown sequence.
    675                  *
    676                  */
    677                
     482                 */
     483
    678484                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    679485                    area->pages - pages);
    680                
    681486                /*
    682487                 * Invalidate software translation caches (e.g. TSB on sparc64).
    683                  *
    684488                 */
    685489                as_invalidate_translation_cache(as, area->base +
    686490                    pages * PAGE_SIZE, area->pages - pages);
    687                 tlb_shootdown_finalize(ipl);
     491                tlb_shootdown_finalize();
    688492               
    689                 page_table_unlock(as, false);
    690493        } else {
    691494                /*
    692495                 * Growing the area.
    693496                 * Check for overlaps with other address space areas.
    694                  *
    695497                 */
    696498                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    697499                    area)) {
    698500                        mutex_unlock(&area->lock);
    699                         mutex_unlock(&as->lock);
     501                        mutex_unlock(&as->lock);               
     502                        interrupts_restore(ipl);
    700503                        return EADDRNOTAVAIL;
    701504                }
    702         }
    703        
     505        } 
     506
    704507        area->pages = pages;
    705508       
    706509        mutex_unlock(&area->lock);
    707510        mutex_unlock(&as->lock);
    708        
     511        interrupts_restore(ipl);
     512
    709513        return 0;
    710514}
    711515
    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  */
    719 NO_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 
    753516/** Destroy address space area.
    754517 *
    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  *
     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.
    760522 */
    761523int as_area_destroy(as_t *as, uintptr_t address)
    762524{
     525        as_area_t *area;
     526        uintptr_t base;
     527        link_t *cur;
     528        ipl_t ipl;
     529
     530        ipl = interrupts_disable();
    763531        mutex_lock(&as->lock);
    764        
    765         as_area_t *area = find_area_and_lock(as, address);
     532
     533        area = find_area_and_lock(as, address);
    766534        if (!area) {
    767535                mutex_unlock(&as->lock);
     536                interrupts_restore(ipl);
    768537                return ENOENT;
    769538        }
    770        
    771         uintptr_t base = area->base;
    772        
    773         page_table_lock(as, false);
    774        
     539
     540        base = area->base;
     541
    775542        /*
    776543         * Start TLB shootdown sequence.
    777544         */
    778         ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    779             area->pages);
    780        
     545        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
     546
    781547        /*
    782548         * Visit only the pages mapped by used_space B+tree.
    783549         */
    784         link_t *cur;
    785550        for (cur = area->used_space.leaf_head.next;
    786551            cur != &area->used_space.leaf_head; cur = cur->next) {
    787552                btree_node_t *node;
    788                 btree_key_t i;
     553                unsigned int i;
    789554               
    790555                node = list_get_instance(cur, btree_node_t, leaf_link);
    791556                for (i = 0; i < node->keys; i++) {
    792                         uintptr_t ptr = node->key[i];
    793                         size_t size;
     557                        uintptr_t b = node->key[i];
     558                        size_t j;
     559                        pte_t *pte;
    794560                       
    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));
     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));
    806570                                }
    807                                
    808                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     571                                page_mapping_remove(as, b + j * PAGE_SIZE);                             
     572                                page_table_unlock(as, false);
    809573                        }
    810574                }
    811575        }
    812        
     576
    813577        /*
    814578         * Finish TLB shootdown sequence.
    815          *
    816          */
    817        
     579         */
     580
    818581        tlb_invalidate_pages(as->asid, area->base, area->pages);
    819        
    820582        /*
    821583         * Invalidate potential software translation caches (e.g. TSB on
    822584         * sparc64).
    823          *
    824585         */
    825586        as_invalidate_translation_cache(as, area->base, area->pages);
    826         tlb_shootdown_finalize(ipl);
    827        
    828         page_table_unlock(as, false);
     587        tlb_shootdown_finalize();
    829588       
    830589        btree_destroy(&area->used_space);
    831        
     590
    832591        area->attributes |= AS_AREA_ATTR_PARTIAL;
    833592       
    834593        if (area->sh_info)
    835594                sh_info_remove_reference(area->sh_info);
    836        
     595               
    837596        mutex_unlock(&area->lock);
    838        
     597
    839598        /*
    840599         * Remove the empty area from address space.
    841          *
    842600         */
    843601        btree_remove(&as->as_area_btree, base, NULL);
     
    846604       
    847605        mutex_unlock(&as->lock);
     606        interrupts_restore(ipl);
    848607        return 0;
    849608}
     
    856615 * sh_info of the source area. The process of duplicating the
    857616 * mapping is done through the backend share function.
    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.
     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.
    864623 * @param dst_flags_mask Destination address space area flags mask.
    865624 *
    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  *
     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.
    874631 */
    875632int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
    876     as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
    877 {
     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();
    878644        mutex_lock(&src_as->lock);
    879         as_area_t *src_area = find_area_and_lock(src_as, src_base);
     645        src_area = find_area_and_lock(src_as, src_base);
    880646        if (!src_area) {
    881647                /*
    882648                 * Could not find the source address space area.
    883                  *
    884649                 */
    885650                mutex_unlock(&src_as->lock);
     651                interrupts_restore(ipl);
    886652                return ENOENT;
    887653        }
    888        
    889         if ((!src_area->backend) || (!src_area->backend->share)) {
     654
     655        if (!src_area->backend || !src_area->backend->share) {
    890656                /*
    891657                 * There is no backend or the backend does not
    892658                 * know how to share the area.
    893                  *
    894659                 */
    895660                mutex_unlock(&src_area->lock);
    896661                mutex_unlock(&src_as->lock);
     662                interrupts_restore(ipl);
    897663                return ENOTSUP;
    898664        }
    899665       
    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        
     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
    905671        /* Share the cacheable flag from the original mapping */
    906672        if (src_flags & AS_AREA_CACHEABLE)
    907673                dst_flags_mask |= AS_AREA_CACHEABLE;
    908        
    909         if ((src_size != acc_size) ||
    910             ((src_flags & dst_flags_mask) != dst_flags_mask)) {
     674
     675        if (src_size != acc_size ||
     676            (src_flags & dst_flags_mask) != dst_flags_mask) {
    911677                mutex_unlock(&src_area->lock);
    912678                mutex_unlock(&src_as->lock);
     679                interrupts_restore(ipl);
    913680                return EPERM;
    914681        }
    915        
     682
    916683        /*
    917684         * Now we are committed to sharing the area.
    918685         * First, prepare the area for sharing.
    919686         * Then it will be safe to unlock it.
    920          *
    921          */
    922         share_info_t *sh_info = src_area->sh_info;
     687         */
     688        sh_info = src_area->sh_info;
    923689        if (!sh_info) {
    924690                sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
     
    927693                btree_create(&sh_info->pagemap);
    928694                src_area->sh_info = sh_info;
    929                
    930695                /*
    931696                 * Call the backend to setup sharing.
    932                  *
    933697                 */
    934698                src_area->backend->share(src_area);
     
    938702                mutex_unlock(&sh_info->lock);
    939703        }
    940        
     704
    941705        mutex_unlock(&src_area->lock);
    942706        mutex_unlock(&src_as->lock);
    943        
     707
    944708        /*
    945709         * Create copy of the source address space area.
     
    949713         * The flags of the source area are masked against dst_flags_mask
    950714         * to support sharing in less privileged mode.
    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);
     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);
    955718        if (!dst_area) {
    956719                /*
     
    959722                sh_info_remove_reference(sh_info);
    960723               
     724                interrupts_restore(ipl);
    961725                return ENOMEM;
    962726        }
    963        
     727
    964728        /*
    965729         * Now the destination address space area has been
    966730         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    967731         * attribute and set the sh_info.
    968          *
    969          */
    970         mutex_lock(&dst_as->lock);
     732         */     
     733        mutex_lock(&dst_as->lock);     
    971734        mutex_lock(&dst_area->lock);
    972735        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
    973736        dst_area->sh_info = sh_info;
    974737        mutex_unlock(&dst_area->lock);
    975         mutex_unlock(&dst_as->lock);
     738        mutex_unlock(&dst_as->lock);   
     739
     740        interrupts_restore(ipl);
    976741       
    977742        return 0;
     
    980745/** Check access mode for address space area.
    981746 *
    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  */
    989 NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
     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 */
     755bool as_area_check_access(as_area_t *area, pf_access_t access)
    990756{
    991757        int flagmap[] = {
     
    995761        };
    996762
    997         ASSERT(mutex_locked(&area->lock));
    998        
    999763        if (!(area->flags & flagmap[access]))
    1000764                return false;
    1001765       
    1002766        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  */
    1012 NO_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;
    1029767}
    1030768
     
    1043781 *
    1044782 */
    1045 int as_area_change_flags(as_t *as, unsigned int flags, uintptr_t address)
    1046 {
     783int 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       
    1047794        /* Flags for the new memory mapping */
    1048         unsigned int page_flags = area_flags_to_page_flags(flags);
    1049        
     795        page_flags = area_flags_to_page_flags(flags);
     796
     797        ipl = interrupts_disable();
    1050798        mutex_lock(&as->lock);
    1051        
    1052         as_area_t *area = find_area_and_lock(as, address);
     799
     800        area = find_area_and_lock(as, address);
    1053801        if (!area) {
    1054802                mutex_unlock(&as->lock);
     803                interrupts_restore(ipl);
    1055804                return ENOENT;
    1056805        }
    1057        
     806
    1058807        if ((area->sh_info) || (area->backend != &anon_backend)) {
    1059808                /* Copying shared areas not supported yet */
     
    1061810                mutex_unlock(&area->lock);
    1062811                mutex_unlock(&as->lock);
     812                interrupts_restore(ipl);
    1063813                return ENOTSUP;
    1064814        }
    1065        
     815
     816        base = area->base;
     817
    1066818        /*
    1067819         * Compute total number of used pages in the used_space B+tree
    1068          *
    1069          */
    1070         size_t used_pages = 0;
    1071         link_t *cur;
    1072        
     820         */
     821        used_pages = 0;
     822
    1073823        for (cur = area->used_space.leaf_head.next;
    1074824            cur != &area->used_space.leaf_head; cur = cur->next) {
    1075                 btree_node_t *node
    1076                     = list_get_instance(cur, btree_node_t, leaf_link);
    1077                 btree_key_t i;
     825                btree_node_t *node;
     826                unsigned int i;
    1078827               
    1079                 for (i = 0; i < node->keys; i++)
     828                node = list_get_instance(cur, btree_node_t, leaf_link);
     829                for (i = 0; i < node->keys; i++) {
    1080830                        used_pages += (size_t) node->value[i];
    1081         }
    1082        
     831                }
     832        }
     833
    1083834        /* An array for storing frame numbers */
    1084         uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    1085        
    1086         page_table_lock(as, false);
    1087        
     835        old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     836
    1088837        /*
    1089838         * Start TLB shootdown sequence.
    1090          *
    1091          */
    1092         ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    1093             area->pages);
    1094        
     839         */
     840        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
     841
    1095842        /*
    1096843         * Remove used pages from page tables and remember their frame
    1097844         * numbers.
    1098          *
    1099          */
    1100         size_t frame_idx = 0;
    1101        
     845         */
     846        frame_idx = 0;
     847
    1102848        for (cur = area->used_space.leaf_head.next;
    1103849            cur != &area->used_space.leaf_head; cur = cur->next) {
    1104                 btree_node_t *node
    1105                     = list_get_instance(cur, btree_node_t, leaf_link);
    1106                 btree_key_t i;
     850                btree_node_t *node;
     851                unsigned int i;
    1107852               
     853                node = list_get_instance(cur, btree_node_t, leaf_link);
    1108854                for (i = 0; i < node->keys; i++) {
    1109                         uintptr_t ptr = node->key[i];
    1110                         size_t size;
     855                        uintptr_t b = node->key[i];
     856                        size_t j;
     857                        pte_t *pte;
    1111858                       
    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                                
     859                        for (j = 0; j < (size_t) node->value[i]; j++) {
     860                                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));
    1119864                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
    1120                                
     865
    1121866                                /* Remove old mapping */
    1122                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     867                                page_mapping_remove(as, b + j * PAGE_SIZE);
     868                                page_table_unlock(as, false);
    1123869                        }
    1124870                }
    1125871        }
    1126        
     872
    1127873        /*
    1128874         * Finish TLB shootdown sequence.
    1129          *
    1130          */
    1131        
     875         */
     876
    1132877        tlb_invalidate_pages(as->asid, area->base, area->pages);
    1133878       
     
    1135880         * Invalidate potential software translation caches (e.g. TSB on
    1136881         * sparc64).
    1137          *
    1138882         */
    1139883        as_invalidate_translation_cache(as, area->base, area->pages);
    1140         tlb_shootdown_finalize(ipl);
    1141        
    1142         page_table_unlock(as, false);
    1143        
     884        tlb_shootdown_finalize();
     885
    1144886        /*
    1145887         * Set the new flags.
    1146888         */
    1147889        area->flags = flags;
    1148        
     890
    1149891        /*
    1150892         * Map pages back in with new flags. This step is kept separate
     
    1153895         */
    1154896        frame_idx = 0;
    1155        
     897
    1156898        for (cur = area->used_space.leaf_head.next;
    1157899            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;
     900                btree_node_t *node;
     901                unsigned int i;
    1161902               
     903                node = list_get_instance(cur, btree_node_t, leaf_link);
    1162904                for (i = 0; i < node->keys; i++) {
    1163                         uintptr_t ptr = node->key[i];
    1164                         size_t size;
     905                        uintptr_t b = node->key[i];
     906                        size_t j;
    1165907                       
    1166                         for (size = 0; size < (size_t) node->value[i]; size++) {
     908                        for (j = 0; j < (size_t) node->value[i]; j++) {
    1167909                                page_table_lock(as, false);
    1168                                
     910
    1169911                                /* Insert the new mapping */
    1170                                 page_mapping_insert(as, ptr + size * PAGE_SIZE,
     912                                page_mapping_insert(as, b + j * PAGE_SIZE,
    1171913                                    old_frame[frame_idx++], page_flags);
    1172                                
     914
    1173915                                page_table_unlock(as, false);
    1174916                        }
    1175917                }
    1176918        }
    1177        
     919
    1178920        free(old_frame);
    1179        
     921
    1180922        mutex_unlock(&area->lock);
    1181923        mutex_unlock(&as->lock);
    1182        
     924        interrupts_restore(ipl);
     925
    1183926        return 0;
    1184927}
     928
    1185929
    1186930/** Handle page fault within the current address space.
     
    1192936 * Interrupts are assumed disabled.
    1193937 *
    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  *
     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().
    1204946 */
    1205947int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    1206948{
     949        pte_t *pte;
     950        as_area_t *area;
     951       
    1207952        if (!THREAD)
    1208953                return AS_PF_FAULT;
    1209        
    1210         if (!AS)
    1211                 return AS_PF_FAULT;
    1212        
     954               
     955        ASSERT(AS);
     956
    1213957        mutex_lock(&AS->lock);
    1214         as_area_t *area = find_area_and_lock(AS, page);
     958        area = find_area_and_lock(AS, page);   
    1215959        if (!area) {
    1216960                /*
    1217961                 * No area contained mapping for 'page'.
    1218962                 * Signal page fault to low-level handler.
    1219                  *
    1220963                 */
    1221964                mutex_unlock(&AS->lock);
    1222965                goto page_fault;
    1223966        }
    1224        
     967
    1225968        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    1226969                /*
     
    1230973                mutex_unlock(&area->lock);
    1231974                mutex_unlock(&AS->lock);
    1232                 goto page_fault;
    1233         }
    1234        
    1235         if ((!area->backend) || (!area->backend->page_fault)) {
     975                goto page_fault;               
     976        }
     977
     978        if (!area->backend || !area->backend->page_fault) {
    1236979                /*
    1237980                 * The address space area is not backed by any backend
    1238981                 * or the backend cannot handle page faults.
    1239                  *
    1240982                 */
    1241983                mutex_unlock(&area->lock);
    1242984                mutex_unlock(&AS->lock);
    1243                 goto page_fault;
    1244         }
    1245        
     985                goto page_fault;               
     986        }
     987
    1246988        page_table_lock(AS, false);
    1247989       
     
    1249991         * To avoid race condition between two page faults on the same address,
    1250992         * we need to make sure the mapping has not been already inserted.
    1251          *
    1252          */
    1253         pte_t *pte;
     993         */
    1254994        if ((pte = page_mapping_find(AS, page))) {
    1255995                if (PTE_PRESENT(pte)) {
     
    12671007        /*
    12681008         * Resort to the backend page fault handler.
    1269          *
    12701009         */
    12711010        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    12801019        mutex_unlock(&AS->lock);
    12811020        return AS_PF_OK;
    1282        
     1021
    12831022page_fault:
    12841023        if (THREAD->in_copy_from_uspace) {
     
    12931032                return AS_PF_FAULT;
    12941033        }
    1295        
     1034
    12961035        return AS_PF_DEFER;
    12971036}
     
    13051044 * When this function is enetered, no spinlocks may be held.
    13061045 *
    1307  * @param old Old address space or NULL.
    1308  * @param new New address space.
    1309  *
     1046 * @param old           Old address space or NULL.
     1047 * @param new           New address space.
    13101048 */
    13111049void as_switch(as_t *old_as, as_t *new_as)
     
    13131051        DEADLOCK_PROBE_INIT(p_asidlock);
    13141052        preemption_disable();
    1315        
    13161053retry:
    13171054        (void) interrupts_disable();
    13181055        if (!spinlock_trylock(&asidlock)) {
    1319                 /*
     1056                /* 
    13201057                 * Avoid deadlock with TLB shootdown.
    13211058                 * We can enable interrupts here because
    13221059                 * preemption is disabled. We should not be
    13231060                 * holding any other lock.
    1324                  *
    13251061                 */
    13261062                (void) interrupts_enable();
     
    13291065        }
    13301066        preemption_enable();
    1331        
     1067
    13321068        /*
    13331069         * First, take care of the old address space.
    1334          */
     1070         */     
    13351071        if (old_as) {
    13361072                ASSERT(old_as->cpu_refcount);
    1337                
    1338                 if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
     1073                if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    13391074                        /*
    13401075                         * The old address space is no longer active on
     
    13421077                         * list of inactive address spaces with assigned
    13431078                         * ASID.
    1344                          *
    13451079                         */
    13461080                        ASSERT(old_as->asid != ASID_INVALID);
    1347                        
    13481081                        list_append(&old_as->inactive_as_with_asid_link,
    13491082                            &inactive_as_with_asid_head);
    13501083                }
    1351                
     1084
    13521085                /*
    13531086                 * Perform architecture-specific tasks when the address space
    13541087                 * is being removed from the CPU.
    1355                  *
    13561088                 */
    13571089                as_deinstall_arch(old_as);
    13581090        }
    1359        
     1091
    13601092        /*
    13611093         * Second, prepare the new address space.
    1362          *
    13631094         */
    13641095        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    13681099                        new_as->asid = asid_get();
    13691100        }
    1370        
    13711101#ifdef AS_PAGE_TABLE
    13721102        SET_PTL0_ADDRESS(new_as->genarch.page_table);
     
    13761106         * Perform architecture-specific steps.
    13771107         * (e.g. write ASID to hardware register etc.)
    1378          *
    13791108         */
    13801109        as_install_arch(new_as);
    1381        
     1110
    13821111        spinlock_unlock(&asidlock);
    13831112       
     
    13851114}
    13861115
     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 */
     1122int 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
    13871143/** Compute flags for virtual address translation subsytem.
    13881144 *
    1389  * @param area Address space area.
    1390  *
    1391  * @return Flags to be used in page_mapping_insert().
    1392  *
    1393  */
    1394 NO_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);
     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 */
     1152int as_area_get_flags(as_area_t *a)
     1153{
     1154        return area_flags_to_page_flags(a->flags);
    13991155}
    14001156
     
    14041160 * table.
    14051161 *
    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  */
    1412 NO_TRACE pte_t *page_table_create(unsigned int flags)
     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 */
     1167pte_t *page_table_create(int flags)
    14131168{
    14141169        ASSERT(as_operations);
     
    14221177 * Destroy page table in architecture specific way.
    14231178 *
    1424  * @param page_table Physical address of PTL0.
    1425  *
    1426  */
    1427 NO_TRACE void page_table_destroy(pte_t *page_table)
     1179 * @param page_table    Physical address of PTL0.
     1180 */
     1181void page_table_destroy(pte_t *page_table)
    14281182{
    14291183        ASSERT(as_operations);
     
    14371191 * This function should be called before any page_mapping_insert(),
    14381192 * page_mapping_remove() and page_mapping_find().
    1439  *
     1193 * 
    14401194 * Locking order is such that address space areas must be locked
    14411195 * prior to this call. Address space can be locked prior to this
    14421196 * call in which case the lock argument is false.
    14431197 *
    1444  * @param as   Address space.
    1445  * @param lock If false, do not attempt to lock as->lock.
    1446  *
    1447  */
    1448 NO_TRACE void page_table_lock(as_t *as, bool lock)
     1198 * @param as            Address space.
     1199 * @param lock          If false, do not attempt to lock as->lock.
     1200 */
     1201void page_table_lock(as_t *as, bool lock)
    14491202{
    14501203        ASSERT(as_operations);
     
    14561209/** Unlock page table.
    14571210 *
    1458  * @param as     Address space.
    1459  * @param unlock If false, do not attempt to unlock as->lock.
    1460  *
    1461  */
    1462 NO_TRACE void page_table_unlock(as_t *as, bool unlock)
     1211 * @param as            Address space.
     1212 * @param unlock        If false, do not attempt to unlock as->lock.
     1213 */
     1214void page_table_unlock(as_t *as, bool unlock)
    14631215{
    14641216        ASSERT(as_operations);
     
    14681220}
    14691221
    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  */
    1477 NO_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);
     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 */
     1233as_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 */
     1290bool
     1291check_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;
    14831363}
    14841364
    14851365/** Return size of the address space area with given base.
    14861366 *
    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  *
     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.
    14921371 */
    14931372size_t as_area_get_size(uintptr_t base)
    14941373{
     1374        ipl_t ipl;
     1375        as_area_t *src_area;
    14951376        size_t size;
    1496        
    1497         page_table_lock(AS, true);
    1498         as_area_t *src_area = find_area_and_lock(AS, base);
    1499        
     1377
     1378        ipl = interrupts_disable();
     1379        src_area = find_area_and_lock(AS, base);
    15001380        if (src_area) {
    15011381                size = src_area->pages * PAGE_SIZE;
    15021382                mutex_unlock(&src_area->lock);
    1503         } else
     1383        } else {
    15041384                size = 0;
    1505        
    1506         page_table_unlock(AS, true);
     1385        }
     1386        interrupts_restore(ipl);
    15071387        return size;
    15081388}
     
    15121392 * The address space area must be already locked.
    15131393 *
    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  */
    1521 int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
    1522 {
    1523         ASSERT(mutex_locked(&area->lock));
     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 */
     1400int 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
    15241406        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    15251407        ASSERT(count);
    1526        
    1527         btree_node_t *leaf;
    1528         size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     1408
     1409        pages = (size_t) btree_search(&a->used_space, page, &leaf);
    15291410        if (pages) {
    15301411                /*
    15311412                 * We hit the beginning of some used space.
    1532                  *
    15331413                 */
    15341414                return 0;
    15351415        }
    1536        
     1416
    15371417        if (!leaf->keys) {
    1538                 btree_insert(&area->used_space, page, (void *) count, leaf);
     1418                btree_insert(&a->used_space, page, (void *) count, leaf);
    15391419                return 1;
    15401420        }
    1541        
    1542         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1421
     1422        node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
    15431423        if (node) {
    15441424                uintptr_t left_pg = node->key[node->keys - 1];
     
    15511431                 * somewhere between the rightmost interval of
    15521432                 * the left neigbour and the first interval of the leaf.
    1553                  *
    1554                  */
    1555                
     1433                 */
     1434                 
    15561435                if (page >= right_pg) {
    15571436                        /* Do nothing. */
     
    15631442                    right_cnt * PAGE_SIZE)) {
    15641443                        /* The interval intersects with the right interval. */
    1565                         return 0;
     1444                        return 0;                       
    15661445                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    15671446                    (page + count * PAGE_SIZE == right_pg)) {
     
    15691448                         * The interval can be added by merging the two already
    15701449                         * present intervals.
    1571                          *
    15721450                         */
    15731451                        node->value[node->keys - 1] += count + right_cnt;
    1574                         btree_remove(&area->used_space, right_pg, leaf);
    1575                         return 1;
     1452                        btree_remove(&a->used_space, right_pg, leaf);
     1453                        return 1; 
    15761454                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    1577                         /*
     1455                        /* 
    15781456                         * The interval can be added by simply growing the left
    15791457                         * interval.
    1580                          *
    15811458                         */
    15821459                        node->value[node->keys - 1] += count;
     
    15871464                         * the right interval down and increasing its size
    15881465                         * accordingly.
    1589                          *
    15901466                         */
    15911467                        leaf->value[0] += count;
     
    15961472                         * The interval is between both neigbouring intervals,
    15971473                         * but cannot be merged with any of them.
    1598                          *
    15991474                         */
    1600                         btree_insert(&area->used_space, page, (void *) count,
     1475                        btree_insert(&a->used_space, page, (void *) count,
    16011476                            leaf);
    16021477                        return 1;
     
    16051480                uintptr_t right_pg = leaf->key[0];
    16061481                size_t right_cnt = (size_t) leaf->value[0];
    1607                
     1482       
    16081483                /*
    16091484                 * Investigate the border case in which the left neighbour does
    16101485                 * not exist but the interval fits from the left.
    1611                  *
    1612                  */
    1613                
     1486                 */
     1487                 
    16141488                if (overlaps(page, count * PAGE_SIZE, right_pg,
    16151489                    right_cnt * PAGE_SIZE)) {
     
    16211495                         * right interval down and increasing its size
    16221496                         * accordingly.
    1623                          *
    16241497                         */
    16251498                        leaf->key[0] = page;
     
    16301503                         * The interval doesn't adjoin with the right interval.
    16311504                         * It must be added individually.
    1632                          *
    16331505                         */
    1634                         btree_insert(&area->used_space, page, (void *) count,
     1506                        btree_insert(&a->used_space, page, (void *) count,
    16351507                            leaf);
    16361508                        return 1;
    16371509                }
    16381510        }
    1639        
    1640         node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
     1511
     1512        node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
    16411513        if (node) {
    16421514                uintptr_t left_pg = leaf->key[leaf->keys - 1];
     
    16491521                 * somewhere between the leftmost interval of
    16501522                 * the right neigbour and the last interval of the leaf.
    1651                  *
    1652                  */
    1653                
     1523                 */
     1524
    16541525                if (page < left_pg) {
    16551526                        /* Do nothing. */
     
    16611532                    right_cnt * PAGE_SIZE)) {
    16621533                        /* The interval intersects with the right interval. */
    1663                         return 0;
     1534                        return 0;                       
    16641535                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    16651536                    (page + count * PAGE_SIZE == right_pg)) {
     
    16671538                         * The interval can be added by merging the two already
    16681539                         * present intervals.
    1669                          *
    1670                          */
     1540                         * */
    16711541                        leaf->value[leaf->keys - 1] += count + right_cnt;
    1672                         btree_remove(&area->used_space, right_pg, node);
    1673                         return 1;
     1542                        btree_remove(&a->used_space, right_pg, node);
     1543                        return 1; 
    16741544                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16751545                        /*
    16761546                         * The interval can be added by simply growing the left
    16771547                         * interval.
    1678                          *
    1679                          */
     1548                         * */
    16801549                        leaf->value[leaf->keys - 1] +=  count;
    16811550                        return 1;
     
    16851554                         * the right interval down and increasing its size
    16861555                         * accordingly.
    1687                          *
    16881556                         */
    16891557                        node->value[0] += count;
     
    16941562                         * The interval is between both neigbouring intervals,
    16951563                         * but cannot be merged with any of them.
    1696                          *
    16971564                         */
    1698                         btree_insert(&area->used_space, page, (void *) count,
     1565                        btree_insert(&a->used_space, page, (void *) count,
    16991566                            leaf);
    17001567                        return 1;
     
    17031570                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    17041571                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1705                
     1572       
    17061573                /*
    17071574                 * Investigate the border case in which the right neighbour
    17081575                 * does not exist but the interval fits from the right.
    1709                  *
    1710                  */
    1711                
     1576                 */
     1577                 
    17121578                if (overlaps(page, count * PAGE_SIZE, left_pg,
    17131579                    left_cnt * PAGE_SIZE)) {
     
    17181584                         * The interval can be added by growing the left
    17191585                         * interval.
    1720                          *
    17211586                         */
    17221587                        leaf->value[leaf->keys - 1] += count;
     
    17261591                         * The interval doesn't adjoin with the left interval.
    17271592                         * It must be added individually.
    1728                          *
    17291593                         */
    1730                         btree_insert(&area->used_space, page, (void *) count,
     1594                        btree_insert(&a->used_space, page, (void *) count,
    17311595                            leaf);
    17321596                        return 1;
     
    17381602         * only between two other intervals of the leaf. The two border cases
    17391603         * were already resolved.
    1740          *
    1741          */
    1742         btree_key_t i;
     1604         */
    17431605        for (i = 1; i < leaf->keys; i++) {
    17441606                if (page < leaf->key[i]) {
     
    17471609                        size_t left_cnt = (size_t) leaf->value[i - 1];
    17481610                        size_t right_cnt = (size_t) leaf->value[i];
    1749                        
     1611
    17501612                        /*
    17511613                         * The interval fits between left_pg and right_pg.
    1752                          *
    17531614                         */
    1754                        
     1615
    17551616                        if (overlaps(page, count * PAGE_SIZE, left_pg,
    17561617                            left_cnt * PAGE_SIZE)) {
     
    17581619                                 * The interval intersects with the left
    17591620                                 * interval.
    1760                                  *
    17611621                                 */
    17621622                                return 0;
     
    17661626                                 * The interval intersects with the right
    17671627                                 * interval.
    1768                                  *
    17691628                                 */
    1770                                 return 0;
     1629                                return 0;                       
    17711630                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    17721631                            (page + count * PAGE_SIZE == right_pg)) {
     
    17741633                                 * The interval can be added by merging the two
    17751634                                 * already present intervals.
    1776                                  *
    17771635                                 */
    17781636                                leaf->value[i - 1] += count + right_cnt;
    1779                                 btree_remove(&area->used_space, right_pg, leaf);
    1780                                 return 1;
     1637                                btree_remove(&a->used_space, right_pg, leaf);
     1638                                return 1; 
    17811639                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    17821640                                /*
    17831641                                 * The interval can be added by simply growing
    17841642                                 * the left interval.
    1785                                  *
    17861643                                 */
    17871644                                leaf->value[i - 1] += count;
     
    17891646                        } else if (page + count * PAGE_SIZE == right_pg) {
    17901647                                /*
    1791                                 * The interval can be addded by simply moving
     1648                                * The interval can be addded by simply moving
    17921649                                 * base of the right interval down and
    17931650                                 * increasing its size accordingly.
    1794                                  *
    1795                                  */
     1651                                 */
    17961652                                leaf->value[i] += count;
    17971653                                leaf->key[i] = page;
     
    18021658                                 * intervals, but cannot be merged with any of
    18031659                                 * them.
    1804                                  *
    18051660                                 */
    1806                                 btree_insert(&area->used_space, page,
     1661                                btree_insert(&a->used_space, page,
    18071662                                    (void *) count, leaf);
    18081663                                return 1;
     
    18101665                }
    18111666        }
    1812        
    1813         panic("Inconsistency detected while adding %zu pages of used "
    1814             "space at %p.", count, (void *) page);
     1667
     1668        panic("Inconsistency detected while adding %" PRIs " pages of used "
     1669            "space at %p.", count, page);
    18151670}
    18161671
     
    18191674 * The address space area must be already locked.
    18201675 *
    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  */
    1828 int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
    1829 {
    1830         ASSERT(mutex_locked(&area->lock));
     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 */
     1682int 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
    18311688        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    18321689        ASSERT(count);
    1833        
    1834         btree_node_t *leaf;
    1835         size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     1690
     1691        pages = (size_t) btree_search(&a->used_space, page, &leaf);
    18361692        if (pages) {
    18371693                /*
    18381694                 * We are lucky, page is the beginning of some interval.
    1839                  *
    18401695                 */
    18411696                if (count > pages) {
    18421697                        return 0;
    18431698                } else if (count == pages) {
    1844                         btree_remove(&area->used_space, page, leaf);
     1699                        btree_remove(&a->used_space, page, leaf);
    18451700                        return 1;
    18461701                } else {
     
    18481703                         * Find the respective interval.
    18491704                         * Decrease its size and relocate its start address.
    1850                          *
    18511705                         */
    1852                         btree_key_t i;
    18531706                        for (i = 0; i < leaf->keys; i++) {
    18541707                                if (leaf->key[i] == page) {
     
    18611714                }
    18621715        }
    1863        
    1864         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    1865         if ((node) && (page < leaf->key[0])) {
     1716
     1717        node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
     1718        if (node && page < leaf->key[0]) {
    18661719                uintptr_t left_pg = node->key[node->keys - 1];
    18671720                size_t left_cnt = (size_t) node->value[node->keys - 1];
    1868                
     1721
    18691722                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    18701723                    count * PAGE_SIZE)) {
     
    18761729                                 * removed by updating the size of the bigger
    18771730                                 * interval.
    1878                                  *
    18791731                                 */
    18801732                                node->value[node->keys - 1] -= count;
     
    18821734                        } else if (page + count * PAGE_SIZE <
    18831735                            left_pg + left_cnt*PAGE_SIZE) {
     1736                                size_t new_cnt;
     1737                               
    18841738                                /*
    18851739                                 * The interval is contained in the rightmost
     
    18881742                                 * the original interval and also inserting a
    18891743                                 * new interval.
    1890                                  *
    18911744                                 */
    1892                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1745                                new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    18931746                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    18941747                                node->value[node->keys - 1] -= count + new_cnt;
    1895                                 btree_insert(&area->used_space, page +
     1748                                btree_insert(&a->used_space, page +
    18961749                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    18971750                                return 1;
     
    18991752                }
    19001753                return 0;
    1901         } else if (page < leaf->key[0])
     1754        } else if (page < leaf->key[0]) {
    19021755                return 0;
     1756        }
    19031757       
    19041758        if (page > leaf->key[leaf->keys - 1]) {
    19051759                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    19061760                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1907                
     1761
    19081762                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    19091763                    count * PAGE_SIZE)) {
    1910                         if (page + count * PAGE_SIZE ==
     1764                        if (page + count * PAGE_SIZE == 
    19111765                            left_pg + left_cnt * PAGE_SIZE) {
    19121766                                /*
     
    19141768                                 * interval of the leaf and can be removed by
    19151769                                 * updating the size of the bigger interval.
    1916                                  *
    19171770                                 */
    19181771                                leaf->value[leaf->keys - 1] -= count;
     
    19201773                        } else if (page + count * PAGE_SIZE < left_pg +
    19211774                            left_cnt * PAGE_SIZE) {
     1775                                size_t new_cnt;
     1776                               
    19221777                                /*
    19231778                                 * The interval is contained in the rightmost
     
    19261781                                 * original interval and also inserting a new
    19271782                                 * interval.
    1928                                  *
    19291783                                 */
    1930                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1784                                new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    19311785                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    19321786                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    1933                                 btree_insert(&area->used_space, page +
     1787                                btree_insert(&a->used_space, page +
    19341788                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    19351789                                return 1;
     
    19371791                }
    19381792                return 0;
    1939         }
     1793        }       
    19401794       
    19411795        /*
     
    19431797         * Now the interval can be only between intervals of the leaf.
    19441798         */
    1945         btree_key_t i;
    19461799        for (i = 1; i < leaf->keys - 1; i++) {
    19471800                if (page < leaf->key[i]) {
    19481801                        uintptr_t left_pg = leaf->key[i - 1];
    19491802                        size_t left_cnt = (size_t) leaf->value[i - 1];
    1950                        
     1803
    19511804                        /*
    19521805                         * Now the interval is between intervals corresponding
     
    19621815                                         * be removed by updating the size of
    19631816                                         * the bigger interval.
    1964                                          *
    19651817                                         */
    19661818                                        leaf->value[i - 1] -= count;
     
    19681820                                } else if (page + count * PAGE_SIZE <
    19691821                                    left_pg + left_cnt * PAGE_SIZE) {
     1822                                        size_t new_cnt;
     1823                               
    19701824                                        /*
    19711825                                         * The interval is contained in the
     
    19751829                                         * also inserting a new interval.
    19761830                                         */
    1977                                         size_t new_cnt = ((left_pg +
     1831                                        new_cnt = ((left_pg +
    19781832                                            left_cnt * PAGE_SIZE) -
    19791833                                            (page + count * PAGE_SIZE)) >>
    19801834                                            PAGE_WIDTH;
    19811835                                        leaf->value[i - 1] -= count + new_cnt;
    1982                                         btree_insert(&area->used_space, page +
     1836                                        btree_insert(&a->used_space, page +
    19831837                                            count * PAGE_SIZE, (void *) new_cnt,
    19841838                                            leaf);
     
    19891843                }
    19901844        }
    1991        
     1845
    19921846error:
    1993         panic("Inconsistency detected while removing %zu pages of used "
    1994             "space from %p.", count, (void *) page);
     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 */
     1857void 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        }
    19951888}
    19961889
     
    20001893
    20011894/** Wrapper for as_area_create(). */
    2002 unative_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
     1895unative_t sys_as_area_create(uintptr_t address, size_t size, int flags)
    20031896{
    20041897        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
     
    20101903
    20111904/** Wrapper for as_area_resize(). */
    2012 unative_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
     1905unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
    20131906{
    20141907        return (unative_t) as_area_resize(AS, address, size, 0);
     
    20161909
    20171910/** Wrapper for as_area_change_flags(). */
    2018 unative_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
     1911unative_t sys_as_area_change_flags(uintptr_t address, int flags)
    20191912{
    20201913        return (unative_t) as_area_change_flags(AS, flags, address);
     
    20291922/** Get list of adress space areas.
    20301923 *
    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  *
     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.
    20351927 */
    20361928void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
    20371929{
     1930        ipl_t ipl;
     1931        size_t area_cnt, area_idx, i;
     1932        link_t *cur;
     1933
     1934        as_area_info_t *info;
     1935        size_t isize;
     1936
     1937        ipl = interrupts_disable();
    20381938        mutex_lock(&as->lock);
    2039        
     1939
    20401940        /* First pass, count number of areas. */
    2041        
    2042         size_t area_cnt = 0;
    2043         link_t *cur;
    2044        
     1941
     1942        area_cnt = 0;
     1943
    20451944        for (cur = as->as_area_btree.leaf_head.next;
    20461945            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2047                 btree_node_t *node =
    2048                     list_get_instance(cur, btree_node_t, leaf_link);
     1946                btree_node_t *node;
     1947
     1948                node = list_get_instance(cur, btree_node_t, leaf_link);
    20491949                area_cnt += node->keys;
    20501950        }
    2051        
    2052         size_t isize = area_cnt * sizeof(as_area_info_t);
    2053         as_area_info_t *info = malloc(isize, 0);
    2054        
     1951
     1952        isize = area_cnt * sizeof(as_area_info_t);
     1953        info = malloc(isize, 0);
     1954
    20551955        /* Second pass, record data. */
    2056        
    2057         size_t area_idx = 0;
    2058        
     1956
     1957        area_idx = 0;
     1958
    20591959        for (cur = as->as_area_btree.leaf_head.next;
    20601960            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2061                 btree_node_t *node =
    2062                     list_get_instance(cur, btree_node_t, leaf_link);
    2063                 btree_key_t i;
    2064                
     1961                btree_node_t *node;
     1962
     1963                node = list_get_instance(cur, btree_node_t, leaf_link);
     1964
    20651965                for (i = 0; i < node->keys; i++) {
    20661966                        as_area_t *area = node->value[i];
    2067                        
     1967
    20681968                        ASSERT(area_idx < area_cnt);
    20691969                        mutex_lock(&area->lock);
    2070                        
     1970
    20711971                        info[area_idx].start_addr = area->base;
    20721972                        info[area_idx].size = FRAMES2SIZE(area->pages);
    20731973                        info[area_idx].flags = area->flags;
    20741974                        ++area_idx;
    2075                        
     1975
    20761976                        mutex_unlock(&area->lock);
    20771977                }
    20781978        }
    2079        
     1979
    20801980        mutex_unlock(&as->lock);
    2081        
     1981        interrupts_restore(ipl);
     1982
    20821983        *obuf = info;
    20831984        *osize = isize;
    20841985}
    20851986
     1987
    20861988/** Print out information about address space.
    20871989 *
    2088  * @param as Address space.
    2089  *
     1990 * @param as            Address space.
    20901991 */
    20911992void as_print(as_t *as)
    20921993{
     1994        ipl_t ipl;
     1995       
     1996        ipl = interrupts_disable();
    20931997        mutex_lock(&as->lock);
    20941998       
     
    20972001        for (cur = as->as_area_btree.leaf_head.next;
    20982002            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2099                 btree_node_t *node
    2100                     = list_get_instance(cur, btree_node_t, leaf_link);
    2101                 btree_key_t i;
     2003                btree_node_t *node;
    21022004               
     2005                node = list_get_instance(cur, btree_node_t, leaf_link);
     2006               
     2007                unsigned int i;
    21032008                for (i = 0; i < node->keys; i++) {
    21042009                        as_area_t *area = node->value[i];
    2105                        
     2010               
    21062011                        mutex_lock(&area->lock);
    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)));
     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));
    21112015                        mutex_unlock(&area->lock);
    21122016                }
     
    21142018       
    21152019        mutex_unlock(&as->lock);
     2020        interrupts_restore(ipl);
    21162021}
    21172022
Note: See TracChangeset for help on using the changeset viewer.