Ignore:
File:
1 edited

Legend:

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

    rfc47885 r98000fb  
    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>
     
    8989as_operations_t *as_operations = NULL;
    9090
    91 /** Slab for as_t objects.
    92  *
     91/**
     92 * Slab for as_t objects.
    9393 */
    9494static slab_cache_t *as_slab;
    9595
    96 /** ASID subsystem lock.
    97  *
    98  * This lock protects:
     96/**
     97 * This lock serializes access to the ASID subsystem.
     98 * It protects:
    9999 * - inactive_as_with_asid_head list
    100100 * - as->asid for each as of the as_t type
    101101 * - asids_allocated counter
    102  *
    103102 */
    104103SPINLOCK_INITIALIZE(asidlock);
    105104
    106105/**
    107  * Inactive address spaces (on all processors)
    108  * that have valid ASID.
     106 * This list contains address spaces that are not active on any
     107 * processor and that have valid ASID.
    109108 */
    110109LIST_INITIALIZE(inactive_as_with_asid_head);
     
    113112as_t *AS_KERNEL = NULL;
    114113
    115 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)
    116120{
    117121        as_t *as = (as_t *) obj;
    118        
     122        int rc;
     123
    119124        link_initialize(&as->inactive_as_with_asid_link);
    120125        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    121126       
    122         return as_constructor_arch(as, flags);
    123 }
    124 
    125 NO_TRACE static size_t as_destructor(void *obj)
    126 {
    127         return as_destructor_arch((as_t *) obj);
     127        rc = as_constructor_arch(as, flags);
     128       
     129        return rc;
     130}
     131
     132static int as_destructor(void *obj)
     133{
     134        as_t *as = (as_t *) obj;
     135
     136        return as_destructor_arch(as);
    128137}
    129138
     
    132141{
    133142        as_arch_init();
    134        
     143
    135144        as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
    136145            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
     
    140149                panic("Cannot create kernel address space.");
    141150       
    142         /*
    143          * Make sure the kernel address space
     151        /* Make sure the kernel address space
    144152         * reference count never drops to zero.
    145153         */
    146         as_hold(AS_KERNEL);
     154        atomic_set(&AS_KERNEL->refcount, 1);
    147155}
    148156
    149157/** Create address space.
    150158 *
    151  * @param flags Flags that influence the way in wich the address
    152  *              space is created.
    153  *
    154  */
    155 as_t *as_create(unsigned int flags)
    156 {
    157         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);
    158167        (void) as_create_arch(as, 0);
    159168       
     
    167176        atomic_set(&as->refcount, 0);
    168177        as->cpu_refcount = 0;
    169        
    170178#ifdef AS_PAGE_TABLE
    171179        as->genarch.page_table = page_table_create(flags);
     
    184192 * We know that we don't hold any spinlock.
    185193 *
    186  * @param as Address space to be destroyed.
    187  *
     194 * @param as            Address space to be destroyed.
    188195 */
    189196void as_destroy(as_t *as)
    190197{
     198        ipl_t ipl;
     199        bool cond;
    191200        DEADLOCK_PROBE_INIT(p_asidlock);
    192        
    193         ASSERT(as != AS);
     201
    194202        ASSERT(atomic_get(&as->refcount) == 0);
    195203       
    196204        /*
    197          * Since there is no reference to this address space, it is safe not to
    198          * lock its mutex.
    199          */
    200        
     205         * Since there is no reference to this area,
     206         * it is safe not to lock its mutex.
     207         */
     208
    201209        /*
    202210         * We need to avoid deadlock between TLB shootdown and asidlock.
     
    207215         */
    208216        preemption_disable();
    209         ipl_t ipl = interrupts_read();
    210        
     217        ipl = interrupts_read();
    211218retry:
    212219        interrupts_disable();
     
    216223                goto retry;
    217224        }
    218        
    219         /* Interrupts disabled, enable preemption */
    220         preemption_enable();
    221        
    222         if ((as->asid != ASID_INVALID) && (as != AS_KERNEL)) {
    223                 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)
    224228                        list_remove(&as->inactive_as_with_asid_link);
    225                
    226229                asid_put(as->asid);
    227230        }
    228        
    229231        spinlock_unlock(&asidlock);
    230         interrupts_restore(ipl);
    231        
    232        
     232
    233233        /*
    234234         * Destroy address space areas of the address space.
    235235         * The B+tree must be walked carefully because it is
    236236         * also being destroyed.
    237          */
    238         bool cond = true;
    239         while (cond) {
     237         */     
     238        for (cond = true; cond; ) {
     239                btree_node_t *node;
     240
    240241                ASSERT(!list_empty(&as->as_area_btree.leaf_head));
    241                
    242                 btree_node_t *node =
    243                     list_get_instance(as->as_area_btree.leaf_head.next,
     242                node = list_get_instance(as->as_area_btree.leaf_head.next,
    244243                    btree_node_t, leaf_link);
    245                
    246                 if ((cond = node->keys))
     244
     245                if ((cond = node->keys)) {
    247246                        as_area_destroy(as, node->key[0]);
    248         }
    249        
     247                }
     248        }
     249
    250250        btree_destroy(&as->as_area_btree);
    251        
    252251#ifdef AS_PAGE_TABLE
    253252        page_table_destroy(as->genarch.page_table);
     
    255254        page_table_destroy(NULL);
    256255#endif
    257        
     256
     257        interrupts_restore(ipl);
     258
    258259        slab_free(as_slab, as);
    259260}
    260261
    261 /** Hold a reference to an address space.
    262  *
    263  * Holding a reference to an address space prevents destruction
    264  * of that address space.
    265  *
    266  * @param as Address space to be held.
    267  *
    268  */
    269 NO_TRACE void as_hold(as_t *as)
    270 {
    271         atomic_inc(&as->refcount);
    272 }
    273 
    274 /** Release a reference to an address space.
    275  *
    276  * The last one to release a reference to an address space
    277  * destroys the address space.
    278  *
    279  * @param asAddress space to be released.
    280  *
    281  */
    282 NO_TRACE void as_release(as_t *as)
    283 {
    284         if (atomic_predec(&as->refcount) == 0)
    285                 as_destroy(as);
    286 }
    287 
    288 /** Check area conflicts with other areas.
    289  *
    290  * @param as         Address space.
    291  * @param va         Starting virtual address of the area being tested.
    292  * @param size       Size of the area being tested.
    293  * @param avoid_area Do not touch this area.
    294  *
    295  * @return True if there is no conflict, false otherwise.
    296  *
    297  */
    298 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
    299     as_area_t *avoid_area)
    300 {
    301         ASSERT(mutex_locked(&as->lock));
    302        
    303         /*
    304          * We don't want any area to have conflicts with NULL page.
    305          */
    306         if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
    307                 return false;
    308        
    309         /*
    310          * The leaf node is found in O(log n), where n is proportional to
    311          * the number of address space areas belonging to as.
    312          * The check for conflicts is then attempted on the rightmost
    313          * record in the left neighbour, the leftmost record in the right
    314          * neighbour and all records in the leaf node itself.
    315          */
    316         btree_node_t *leaf;
    317         as_area_t *area =
    318             (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    319         if (area) {
    320                 if (area != avoid_area)
    321                         return false;
    322         }
    323        
    324         /* First, check the two border cases. */
    325         btree_node_t *node =
    326             btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    327         if (node) {
    328                 area = (as_area_t *) node->value[node->keys - 1];
    329                
    330                 mutex_lock(&area->lock);
    331                
    332                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    333                         mutex_unlock(&area->lock);
    334                         return false;
    335                 }
    336                
    337                 mutex_unlock(&area->lock);
    338         }
    339        
    340         node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    341         if (node) {
    342                 area = (as_area_t *) node->value[0];
    343                
    344                 mutex_lock(&area->lock);
    345                
    346                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    347                         mutex_unlock(&area->lock);
    348                         return false;
    349                 }
    350                
    351                 mutex_unlock(&area->lock);
    352         }
    353        
    354         /* Second, check the leaf node. */
    355         btree_key_t i;
    356         for (i = 0; i < leaf->keys; i++) {
    357                 area = (as_area_t *) leaf->value[i];
    358                
    359                 if (area == avoid_area)
    360                         continue;
    361                
    362                 mutex_lock(&area->lock);
    363                
    364                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    365                         mutex_unlock(&area->lock);
    366                         return false;
    367                 }
    368                
    369                 mutex_unlock(&area->lock);
    370         }
    371        
    372         /*
    373          * So far, the area does not conflict with other areas.
    374          * Check if it doesn't conflict with kernel address space.
    375          */
    376         if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    377                 return !overlaps(va, size,
    378                     KERNEL_ADDRESS_SPACE_START,
    379                     KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
    380         }
    381        
    382         return true;
    383 }
    384 
    385262/** Create address space area of common attributes.
    386263 *
    387264 * The created address space area is added to the target address space.
    388265 *
    389  * @param as           Target address space.
    390  * @param flags        Flags of the area memory.
    391  * @param size         Size of area.
    392  * @param base         Base address of area.
    393  * @param attrs        Attributes of the area.
    394  * @param backend      Address space area backend. NULL if no backend is used.
    395  * @param backend_data NULL or a pointer to an array holding two void *.
    396  *
    397  * @return Address space area on success or NULL on failure.
    398  *
    399  */
    400 as_area_t *as_area_create(as_t *as, unsigned int flags, size_t size,
    401     uintptr_t base, unsigned int attrs, mem_backend_t *backend,
    402     mem_backend_data_t *backend_data)
    403 {
     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       
    404283        if (base % PAGE_SIZE)
    405284                return NULL;
    406        
     285
    407286        if (!size)
    408287                return NULL;
    409        
     288
    410289        /* Writeable executable areas are not supported. */
    411290        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
    412291                return NULL;
    413292       
     293        ipl = interrupts_disable();
    414294        mutex_lock(&as->lock);
    415295       
    416296        if (!check_area_conflicts(as, base, size, NULL)) {
    417297                mutex_unlock(&as->lock);
     298                interrupts_restore(ipl);
    418299                return NULL;
    419300        }
    420301       
    421         as_area_t *area = (as_area_t *) malloc(sizeof(as_area_t), 0);
    422        
    423         mutex_initialize(&area->lock, MUTEX_PASSIVE);
    424        
    425         area->as = as;
    426         area->flags = flags;
    427         area->attributes = attrs;
    428         area->pages = SIZE2FRAMES(size);
    429         area->resident = 0;
    430         area->base = base;
    431         area->sh_info = NULL;
    432         area->backend = backend;
    433        
     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;
    434313        if (backend_data)
    435                 area->backend_data = *backend_data;
     314                a->backend_data = *backend_data;
    436315        else
    437                 memsetb(&area->backend_data, sizeof(area->backend_data), 0);
    438        
    439         btree_create(&area->used_space);
    440         btree_insert(&as->as_area_btree, base, (void *) area, NULL);
    441        
     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
    442322        mutex_unlock(&as->lock);
    443        
    444         return area;
    445 }
    446 
    447 /** Find address space area and lock it.
    448  *
    449  * @param as Address space.
    450  * @param va Virtual address.
    451  *
    452  * @return Locked address space area containing va on success or
    453  *         NULL on failure.
    454  *
    455  */
    456 NO_TRACE static as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
    457 {
    458         ASSERT(mutex_locked(&as->lock));
    459        
    460         btree_node_t *leaf;
    461         as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    462         if (area) {
    463                 /* va is the base address of an address space area */
    464                 mutex_lock(&area->lock);
    465                 return area;
    466         }
    467        
    468         /*
    469          * Search the leaf node and the righmost record of its left neighbour
    470          * to find out whether this is a miss or va belongs to an address
    471          * space area found there.
    472          */
    473        
    474         /* First, search the leaf node itself. */
    475         btree_key_t i;
    476        
    477         for (i = 0; i < leaf->keys; i++) {
    478                 area = (as_area_t *) leaf->value[i];
    479                
    480                 mutex_lock(&area->lock);
    481                
    482                 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
    483                         return area;
    484                
    485                 mutex_unlock(&area->lock);
    486         }
    487        
    488         /*
    489          * Second, locate the left neighbour and test its last record.
    490          * Because of its position in the B+tree, it must have base < va.
    491          */
    492         btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
    493         if (lnode) {
    494                 area = (as_area_t *) lnode->value[lnode->keys - 1];
    495                
    496                 mutex_lock(&area->lock);
    497                
    498                 if (va < area->base + area->pages * PAGE_SIZE)
    499                         return area;
    500                
    501                 mutex_unlock(&area->lock);
    502         }
    503        
    504         return NULL;
     323        interrupts_restore(ipl);
     324
     325        return a;
    505326}
    506327
    507328/** Find address space area and change it.
    508329 *
    509  * @param as      Address space.
    510  * @param address Virtual address belonging to the area to be changed.
    511  *                Must be page-aligned.
    512  * @param size    New size of the virtual memory block starting at
    513  *                address.
    514  * @param flags   Flags influencing the remap operation. Currently unused.
    515  *
    516  * @return Zero on success or a value from @ref errno.h otherwise.
    517  *
    518  */
    519 int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags)
    520 {
     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();
    521346        mutex_lock(&as->lock);
    522347       
     
    524349         * Locate the area.
    525350         */
    526         as_area_t *area = find_area_and_lock(as, address);
     351        area = find_area_and_lock(as, address);
    527352        if (!area) {
    528353                mutex_unlock(&as->lock);
     354                interrupts_restore(ipl);
    529355                return ENOENT;
    530356        }
    531        
     357
    532358        if (area->backend == &phys_backend) {
    533359                /*
     
    537363                mutex_unlock(&area->lock);
    538364                mutex_unlock(&as->lock);
     365                interrupts_restore(ipl);
    539366                return ENOTSUP;
    540367        }
    541        
    542368        if (area->sh_info) {
    543369                /*
    544                  * Remapping of shared address space areas
     370                 * Remapping of shared address space areas 
    545371                 * is not supported.
    546372                 */
    547373                mutex_unlock(&area->lock);
    548374                mutex_unlock(&as->lock);
     375                interrupts_restore(ipl);
    549376                return ENOTSUP;
    550377        }
    551        
    552         size_t pages = SIZE2FRAMES((address - area->base) + size);
     378
     379        pages = SIZE2FRAMES((address - area->base) + size);
    553380        if (!pages) {
    554381                /*
     
    557384                mutex_unlock(&area->lock);
    558385                mutex_unlock(&as->lock);
     386                interrupts_restore(ipl);
    559387                return EPERM;
    560388        }
    561389       
    562390        if (pages < area->pages) {
     391                bool cond;
    563392                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    564                
     393
    565394                /*
    566395                 * Shrinking the area.
    567396                 * No need to check for overlaps.
    568397                 */
    569                
    570                 page_table_lock(as, false);
    571                
     398
    572399                /*
    573400                 * Start TLB shootdown sequence.
    574401                 */
    575                 ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    576                     area->base + pages * PAGE_SIZE, area->pages - pages);
    577                
     402                tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
     403                    pages * PAGE_SIZE, area->pages - pages);
     404
    578405                /*
    579406                 * Remove frames belonging to used space starting from
     
    582409                 * is also the right way to remove part of the used_space
    583410                 * B+tree leaf list.
    584                  */
    585                 bool cond = true;
    586                 while (cond) {
     411                 */             
     412                for (cond = true; cond;) {
     413                        btree_node_t *node;
     414               
    587415                        ASSERT(!list_empty(&area->used_space.leaf_head));
    588                        
    589                         btree_node_t *node =
     416                        node =
    590417                            list_get_instance(area->used_space.leaf_head.prev,
    591418                            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;
    592424                       
    593                         if ((cond = (bool) node->keys)) {
    594                                 uintptr_t ptr = node->key[node->keys - 1];
    595                                 size_t size =
    596                                     (size_t) node->value[node->keys - 1];
    597                                 size_t i = 0;
    598                                
    599                                 if (overlaps(ptr, size * PAGE_SIZE, area->base,
     425                                if (overlaps(b, c * PAGE_SIZE, area->base,
    600426                                    pages * PAGE_SIZE)) {
    601427                                       
    602                                         if (ptr + size * PAGE_SIZE <= start_free) {
     428                                        if (b + c * PAGE_SIZE <= start_free) {
    603429                                                /*
    604430                                                 * The whole interval fits
     
    608434                                                break;
    609435                                        }
    610                                        
     436               
    611437                                        /*
    612438                                         * Part of the interval corresponding
     
    614440                                         * address space area.
    615441                                         */
    616                                        
    617                                         /* We are almost done */
    618                                         cond = false;
    619                                         i = (start_free - ptr) >> PAGE_WIDTH;
     442               
     443                                        cond = false;   /* we are almost done */
     444                                        i = (start_free - b) >> PAGE_WIDTH;
    620445                                        if (!used_space_remove(area, start_free,
    621                                             size - i))
    622                                                 panic("Cannot remove used space.");
     446                                            c - i))
     447                                                panic("Cannot remove used "
     448                                                    "space.");
    623449                                } else {
    624450                                        /*
     
    626452                                         * completely removed.
    627453                                         */
    628                                         if (!used_space_remove(area, ptr, size))
    629                                                 panic("Cannot remove used space.");
     454                                        if (!used_space_remove(area, b, c))
     455                                                panic("Cannot remove used "
     456                                                    "space.");
    630457                                }
    631                                
    632                                 for (; i < size; i++) {
    633                                         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 +
    634464                                            i * PAGE_SIZE);
    635                                        
    636                                         ASSERT(pte);
    637                                         ASSERT(PTE_VALID(pte));
    638                                         ASSERT(PTE_PRESENT(pte));
    639                                        
    640                                         if ((area->backend) &&
    641                                             (area->backend->frame_free)) {
     465                                        ASSERT(pte && PTE_VALID(pte) &&
     466                                            PTE_PRESENT(pte));
     467                                        if (area->backend &&
     468                                            area->backend->frame_free) {
    642469                                                area->backend->frame_free(area,
    643                                                     ptr + i * PAGE_SIZE,
     470                                                    b + i * PAGE_SIZE,
    644471                                                    PTE_GET_FRAME(pte));
    645472                                        }
    646                                        
    647                                         page_mapping_remove(as, ptr +
     473                                        page_mapping_remove(as, b +
    648474                                            i * PAGE_SIZE);
     475                                        page_table_unlock(as, false);
    649476                                }
    650477                        }
    651478                }
    652                
     479
    653480                /*
    654481                 * Finish TLB shootdown sequence.
    655482                 */
    656                
     483
    657484                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    658485                    area->pages - pages);
    659                
    660486                /*
    661487                 * Invalidate software translation caches (e.g. TSB on sparc64).
     
    663489                as_invalidate_translation_cache(as, area->base +
    664490                    pages * PAGE_SIZE, area->pages - pages);
    665                 tlb_shootdown_finalize(ipl);
     491                tlb_shootdown_finalize();
    666492               
    667                 page_table_unlock(as, false);
    668493        } else {
    669494                /*
     
    674499                    area)) {
    675500                        mutex_unlock(&area->lock);
    676                         mutex_unlock(&as->lock);
     501                        mutex_unlock(&as->lock);               
     502                        interrupts_restore(ipl);
    677503                        return EADDRNOTAVAIL;
    678504                }
    679         }
    680        
     505        } 
     506
    681507        area->pages = pages;
    682508       
    683509        mutex_unlock(&area->lock);
    684510        mutex_unlock(&as->lock);
    685        
     511        interrupts_restore(ipl);
     512
    686513        return 0;
    687514}
    688515
    689 /** Remove reference to address space area share info.
    690  *
    691  * If the reference count drops to 0, the sh_info is deallocated.
    692  *
    693  * @param sh_info Pointer to address space area share info.
    694  *
    695  */
    696 NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)
    697 {
    698         bool dealloc = false;
    699        
    700         mutex_lock(&sh_info->lock);
    701         ASSERT(sh_info->refcount);
    702        
    703         if (--sh_info->refcount == 0) {
    704                 dealloc = true;
    705                 link_t *cur;
    706                
    707                 /*
    708                  * Now walk carefully the pagemap B+tree and free/remove
    709                  * reference from all frames found there.
    710                  */
    711                 for (cur = sh_info->pagemap.leaf_head.next;
    712                     cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
    713                         btree_node_t *node
    714                             = list_get_instance(cur, btree_node_t, leaf_link);
    715                         btree_key_t i;
    716                        
    717                         for (i = 0; i < node->keys; i++)
    718                                 frame_free((uintptr_t) node->value[i]);
    719                 }
    720                
    721         }
    722         mutex_unlock(&sh_info->lock);
    723        
    724         if (dealloc) {
    725                 btree_destroy(&sh_info->pagemap);
    726                 free(sh_info);
    727         }
    728 }
    729 
    730516/** Destroy address space area.
    731517 *
    732  * @param as      Address space.
    733  * @param address Address within the area to be deleted.
    734  *
    735  * @return Zero on success or a value from @ref errno.h on failure.
    736  *
     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.
    737522 */
    738523int as_area_destroy(as_t *as, uintptr_t address)
    739524{
     525        as_area_t *area;
     526        uintptr_t base;
     527        link_t *cur;
     528        ipl_t ipl;
     529
     530        ipl = interrupts_disable();
    740531        mutex_lock(&as->lock);
    741        
    742         as_area_t *area = find_area_and_lock(as, address);
     532
     533        area = find_area_and_lock(as, address);
    743534        if (!area) {
    744535                mutex_unlock(&as->lock);
     536                interrupts_restore(ipl);
    745537                return ENOENT;
    746538        }
    747        
    748         uintptr_t base = area->base;
    749        
    750         page_table_lock(as, false);
    751        
     539
     540        base = area->base;
     541
    752542        /*
    753543         * Start TLB shootdown sequence.
    754544         */
    755         ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    756             area->pages);
    757        
     545        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
     546
    758547        /*
    759548         * Visit only the pages mapped by used_space B+tree.
    760549         */
    761         link_t *cur;
    762550        for (cur = area->used_space.leaf_head.next;
    763551            cur != &area->used_space.leaf_head; cur = cur->next) {
    764552                btree_node_t *node;
    765                 btree_key_t i;
     553                unsigned int i;
    766554               
    767555                node = list_get_instance(cur, btree_node_t, leaf_link);
    768556                for (i = 0; i < node->keys; i++) {
    769                         uintptr_t ptr = node->key[i];
    770                         size_t size;
     557                        uintptr_t b = node->key[i];
     558                        size_t j;
     559                        pte_t *pte;
    771560                       
    772                         for (size = 0; size < (size_t) node->value[i]; size++) {
    773                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    774                                
    775                                 ASSERT(pte);
    776                                 ASSERT(PTE_VALID(pte));
    777                                 ASSERT(PTE_PRESENT(pte));
    778                                
    779                                 if ((area->backend) &&
    780                                     (area->backend->frame_free)) {
    781                                         area->backend->frame_free(area,
    782                                             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));
    783570                                }
    784                                
    785                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     571                                page_mapping_remove(as, b + j * PAGE_SIZE);                             
     572                                page_table_unlock(as, false);
    786573                        }
    787574                }
    788575        }
    789        
     576
    790577        /*
    791578         * Finish TLB shootdown sequence.
    792579         */
    793        
     580
    794581        tlb_invalidate_pages(as->asid, area->base, area->pages);
    795        
    796582        /*
    797583         * Invalidate potential software translation caches (e.g. TSB on
     
    799585         */
    800586        as_invalidate_translation_cache(as, area->base, area->pages);
    801         tlb_shootdown_finalize(ipl);
    802        
    803         page_table_unlock(as, false);
     587        tlb_shootdown_finalize();
    804588       
    805589        btree_destroy(&area->used_space);
    806        
     590
    807591        area->attributes |= AS_AREA_ATTR_PARTIAL;
    808592       
    809593        if (area->sh_info)
    810594                sh_info_remove_reference(area->sh_info);
    811        
     595               
    812596        mutex_unlock(&area->lock);
    813        
     597
    814598        /*
    815599         * Remove the empty area from address space.
     
    820604       
    821605        mutex_unlock(&as->lock);
     606        interrupts_restore(ipl);
    822607        return 0;
    823608}
     
    830615 * sh_info of the source area. The process of duplicating the
    831616 * mapping is done through the backend share function.
    832  *
    833  * @param src_as         Pointer to source address space.
    834  * @param src_base       Base address of the source address space area.
    835  * @param acc_size       Expected size of the source area.
    836  * @param dst_as         Pointer to destination address space.
    837  * @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.
    838623 * @param dst_flags_mask Destination address space area flags mask.
    839624 *
    840  * @return Zero on success.
    841  * @return ENOENT if there is no such task or such address space.
    842  * @return EPERM if there was a problem in accepting the area.
    843  * @return ENOMEM if there was a problem in allocating destination
    844  *         address space area.
    845  * @return ENOTSUP if the address space area backend does not support
    846  *         sharing.
    847  *
     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.
    848631 */
    849632int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
    850     as_t *dst_as, uintptr_t dst_base, unsigned int dst_flags_mask)
    851 {
     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();
    852644        mutex_lock(&src_as->lock);
    853         as_area_t *src_area = find_area_and_lock(src_as, src_base);
     645        src_area = find_area_and_lock(src_as, src_base);
    854646        if (!src_area) {
    855647                /*
     
    857649                 */
    858650                mutex_unlock(&src_as->lock);
     651                interrupts_restore(ipl);
    859652                return ENOENT;
    860653        }
    861        
    862         if ((!src_area->backend) || (!src_area->backend->share)) {
     654
     655        if (!src_area->backend || !src_area->backend->share) {
    863656                /*
    864657                 * There is no backend or the backend does not
     
    867660                mutex_unlock(&src_area->lock);
    868661                mutex_unlock(&src_as->lock);
     662                interrupts_restore(ipl);
    869663                return ENOTSUP;
    870664        }
    871665       
    872         size_t src_size = src_area->pages * PAGE_SIZE;
    873         unsigned int src_flags = src_area->flags;
    874         mem_backend_t *src_backend = src_area->backend;
    875         mem_backend_data_t src_backend_data = src_area->backend_data;
    876        
     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
    877671        /* Share the cacheable flag from the original mapping */
    878672        if (src_flags & AS_AREA_CACHEABLE)
    879673                dst_flags_mask |= AS_AREA_CACHEABLE;
    880        
    881         if ((src_size != acc_size) ||
    882             ((src_flags & dst_flags_mask) != dst_flags_mask)) {
     674
     675        if (src_size != acc_size ||
     676            (src_flags & dst_flags_mask) != dst_flags_mask) {
    883677                mutex_unlock(&src_area->lock);
    884678                mutex_unlock(&src_as->lock);
     679                interrupts_restore(ipl);
    885680                return EPERM;
    886681        }
    887        
     682
    888683        /*
    889684         * Now we are committed to sharing the area.
     
    891686         * Then it will be safe to unlock it.
    892687         */
    893         share_info_t *sh_info = src_area->sh_info;
     688        sh_info = src_area->sh_info;
    894689        if (!sh_info) {
    895690                sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
     
    898693                btree_create(&sh_info->pagemap);
    899694                src_area->sh_info = sh_info;
    900                
    901695                /*
    902696                 * Call the backend to setup sharing.
     
    908702                mutex_unlock(&sh_info->lock);
    909703        }
    910        
     704
    911705        mutex_unlock(&src_area->lock);
    912706        mutex_unlock(&src_as->lock);
    913        
     707
    914708        /*
    915709         * Create copy of the source address space area.
     
    920714         * to support sharing in less privileged mode.
    921715         */
    922         as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
    923             dst_base, AS_AREA_ATTR_PARTIAL, src_backend, &src_backend_data);
     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);
    924718        if (!dst_area) {
    925719                /*
     
    928722                sh_info_remove_reference(sh_info);
    929723               
     724                interrupts_restore(ipl);
    930725                return ENOMEM;
    931726        }
    932        
     727
    933728        /*
    934729         * Now the destination address space area has been
    935730         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    936731         * attribute and set the sh_info.
    937          */
    938         mutex_lock(&dst_as->lock);
     732         */     
     733        mutex_lock(&dst_as->lock);     
    939734        mutex_lock(&dst_area->lock);
    940735        dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
    941736        dst_area->sh_info = sh_info;
    942737        mutex_unlock(&dst_area->lock);
    943         mutex_unlock(&dst_as->lock);
     738        mutex_unlock(&dst_as->lock);   
     739
     740        interrupts_restore(ipl);
    944741       
    945742        return 0;
     
    948745/** Check access mode for address space area.
    949746 *
    950  * @param area   Address space area.
    951  * @param access Access mode.
    952  *
    953  * @return False if access violates area's permissions, true
    954  *         otherwise.
    955  *
    956  */
    957 NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
    958 {
    959         ASSERT(mutex_locked(&area->lock));
    960        
     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)
     756{
    961757        int flagmap[] = {
    962758                [PF_ACCESS_READ] = AS_AREA_READ,
     
    964760                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    965761        };
    966        
     762
    967763        if (!(area->flags & flagmap[access]))
    968764                return false;
    969765       
    970766        return true;
    971 }
    972 
    973 /** Convert address space area flags to page flags.
    974  *
    975  * @param aflags Flags of some address space area.
    976  *
    977  * @return Flags to be passed to page_mapping_insert().
    978  *
    979  */
    980 NO_TRACE static unsigned int area_flags_to_page_flags(unsigned int aflags)
    981 {
    982         unsigned int flags = PAGE_USER | PAGE_PRESENT;
    983        
    984         if (aflags & AS_AREA_READ)
    985                 flags |= PAGE_READ;
    986                
    987         if (aflags & AS_AREA_WRITE)
    988                 flags |= PAGE_WRITE;
    989        
    990         if (aflags & AS_AREA_EXEC)
    991                 flags |= PAGE_EXEC;
    992        
    993         if (aflags & AS_AREA_CACHEABLE)
    994                 flags |= PAGE_CACHEABLE;
    995        
    996         return flags;
    997767}
    998768
     
    1011781 *
    1012782 */
    1013 int as_area_change_flags(as_t *as, unsigned int flags, uintptr_t address)
    1014 {
     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       
    1015794        /* Flags for the new memory mapping */
    1016         unsigned int page_flags = area_flags_to_page_flags(flags);
    1017        
     795        page_flags = area_flags_to_page_flags(flags);
     796
     797        ipl = interrupts_disable();
    1018798        mutex_lock(&as->lock);
    1019        
    1020         as_area_t *area = find_area_and_lock(as, address);
     799
     800        area = find_area_and_lock(as, address);
    1021801        if (!area) {
    1022802                mutex_unlock(&as->lock);
     803                interrupts_restore(ipl);
    1023804                return ENOENT;
    1024805        }
    1025        
     806
    1026807        if ((area->sh_info) || (area->backend != &anon_backend)) {
    1027808                /* Copying shared areas not supported yet */
     
    1029810                mutex_unlock(&area->lock);
    1030811                mutex_unlock(&as->lock);
     812                interrupts_restore(ipl);
    1031813                return ENOTSUP;
    1032814        }
    1033        
     815
     816        base = area->base;
     817
    1034818        /*
    1035819         * Compute total number of used pages in the used_space B+tree
    1036820         */
    1037         size_t used_pages = 0;
    1038         link_t *cur;
    1039        
     821        used_pages = 0;
     822
    1040823        for (cur = area->used_space.leaf_head.next;
    1041824            cur != &area->used_space.leaf_head; cur = cur->next) {
    1042                 btree_node_t *node
    1043                     = list_get_instance(cur, btree_node_t, leaf_link);
    1044                 btree_key_t i;
     825                btree_node_t *node;
     826                unsigned int i;
    1045827               
    1046                 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++) {
    1047830                        used_pages += (size_t) node->value[i];
    1048         }
    1049        
     831                }
     832        }
     833
    1050834        /* An array for storing frame numbers */
    1051         uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    1052        
    1053         page_table_lock(as, false);
    1054        
     835        old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
     836
    1055837        /*
    1056838         * Start TLB shootdown sequence.
    1057839         */
    1058         ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    1059             area->pages);
    1060        
     840        tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
     841
    1061842        /*
    1062843         * Remove used pages from page tables and remember their frame
    1063844         * numbers.
    1064845         */
    1065         size_t frame_idx = 0;
    1066        
     846        frame_idx = 0;
     847
    1067848        for (cur = area->used_space.leaf_head.next;
    1068849            cur != &area->used_space.leaf_head; cur = cur->next) {
    1069                 btree_node_t *node
    1070                     = list_get_instance(cur, btree_node_t, leaf_link);
    1071                 btree_key_t i;
     850                btree_node_t *node;
     851                unsigned int i;
    1072852               
     853                node = list_get_instance(cur, btree_node_t, leaf_link);
    1073854                for (i = 0; i < node->keys; i++) {
    1074                         uintptr_t ptr = node->key[i];
    1075                         size_t size;
     855                        uintptr_t b = node->key[i];
     856                        size_t j;
     857                        pte_t *pte;
    1076858                       
    1077                         for (size = 0; size < (size_t) node->value[i]; size++) {
    1078                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    1079                                
    1080                                 ASSERT(pte);
    1081                                 ASSERT(PTE_VALID(pte));
    1082                                 ASSERT(PTE_PRESENT(pte));
    1083                                
     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));
    1084864                                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
    1085                                
     865
    1086866                                /* Remove old mapping */
    1087                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     867                                page_mapping_remove(as, b + j * PAGE_SIZE);
     868                                page_table_unlock(as, false);
    1088869                        }
    1089870                }
    1090871        }
    1091        
     872
    1092873        /*
    1093874         * Finish TLB shootdown sequence.
    1094875         */
    1095        
     876
    1096877        tlb_invalidate_pages(as->asid, area->base, area->pages);
    1097878       
     
    1101882         */
    1102883        as_invalidate_translation_cache(as, area->base, area->pages);
    1103         tlb_shootdown_finalize(ipl);
    1104        
    1105         page_table_unlock(as, false);
    1106        
     884        tlb_shootdown_finalize();
     885
    1107886        /*
    1108887         * Set the new flags.
    1109888         */
    1110889        area->flags = flags;
    1111        
     890
    1112891        /*
    1113892         * Map pages back in with new flags. This step is kept separate
     
    1116895         */
    1117896        frame_idx = 0;
    1118        
     897
    1119898        for (cur = area->used_space.leaf_head.next;
    1120899            cur != &area->used_space.leaf_head; cur = cur->next) {
    1121                 btree_node_t *node
    1122                     = list_get_instance(cur, btree_node_t, leaf_link);
    1123                 btree_key_t i;
     900                btree_node_t *node;
     901                unsigned int i;
    1124902               
     903                node = list_get_instance(cur, btree_node_t, leaf_link);
    1125904                for (i = 0; i < node->keys; i++) {
    1126                         uintptr_t ptr = node->key[i];
    1127                         size_t size;
     905                        uintptr_t b = node->key[i];
     906                        size_t j;
    1128907                       
    1129                         for (size = 0; size < (size_t) node->value[i]; size++) {
     908                        for (j = 0; j < (size_t) node->value[i]; j++) {
    1130909                                page_table_lock(as, false);
    1131                                
     910
    1132911                                /* Insert the new mapping */
    1133                                 page_mapping_insert(as, ptr + size * PAGE_SIZE,
     912                                page_mapping_insert(as, b + j * PAGE_SIZE,
    1134913                                    old_frame[frame_idx++], page_flags);
    1135                                
     914
    1136915                                page_table_unlock(as, false);
    1137916                        }
    1138917                }
    1139918        }
    1140        
     919
    1141920        free(old_frame);
    1142        
     921
    1143922        mutex_unlock(&area->lock);
    1144923        mutex_unlock(&as->lock);
    1145        
     924        interrupts_restore(ipl);
     925
    1146926        return 0;
    1147927}
     928
    1148929
    1149930/** Handle page fault within the current address space.
     
    1155936 * Interrupts are assumed disabled.
    1156937 *
    1157  * @param page   Faulting page.
    1158  * @param access Access mode that caused the page fault (i.e.
    1159  *               read/write/exec).
    1160  * @param istate Pointer to the interrupted state.
    1161  *
    1162  * @return AS_PF_FAULT on page fault.
    1163  * @return AS_PF_OK on success.
    1164  * @return AS_PF_DEFER if the fault was caused by copy_to_uspace()
    1165  *         or copy_from_uspace().
    1166  *
     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().
    1167946 */
    1168947int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    1169948{
     949        pte_t *pte;
     950        as_area_t *area;
     951       
    1170952        if (!THREAD)
    1171953                return AS_PF_FAULT;
    1172        
    1173         if (!AS)
    1174                 return AS_PF_FAULT;
    1175        
     954               
     955        ASSERT(AS);
     956
    1176957        mutex_lock(&AS->lock);
    1177         as_area_t *area = find_area_and_lock(AS, page);
     958        area = find_area_and_lock(AS, page);   
    1178959        if (!area) {
    1179960                /*
     
    1184965                goto page_fault;
    1185966        }
    1186        
     967
    1187968        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    1188969                /*
     
    1192973                mutex_unlock(&area->lock);
    1193974                mutex_unlock(&AS->lock);
    1194                 goto page_fault;
    1195         }
    1196        
    1197         if ((!area->backend) || (!area->backend->page_fault)) {
     975                goto page_fault;               
     976        }
     977
     978        if (!area->backend || !area->backend->page_fault) {
    1198979                /*
    1199980                 * The address space area is not backed by any backend
     
    1202983                mutex_unlock(&area->lock);
    1203984                mutex_unlock(&AS->lock);
    1204                 goto page_fault;
    1205         }
    1206        
     985                goto page_fault;               
     986        }
     987
    1207988        page_table_lock(AS, false);
    1208989       
     
    1211992         * we need to make sure the mapping has not been already inserted.
    1212993         */
    1213         pte_t *pte;
    1214994        if ((pte = page_mapping_find(AS, page))) {
    1215995                if (PTE_PRESENT(pte)) {
     
    12391019        mutex_unlock(&AS->lock);
    12401020        return AS_PF_OK;
    1241        
     1021
    12421022page_fault:
    12431023        if (THREAD->in_copy_from_uspace) {
     
    12521032                return AS_PF_FAULT;
    12531033        }
    1254        
     1034
    12551035        return AS_PF_DEFER;
    12561036}
     
    12641044 * When this function is enetered, no spinlocks may be held.
    12651045 *
    1266  * @param old Old address space or NULL.
    1267  * @param new New address space.
    1268  *
     1046 * @param old           Old address space or NULL.
     1047 * @param new           New address space.
    12691048 */
    12701049void as_switch(as_t *old_as, as_t *new_as)
     
    12721051        DEADLOCK_PROBE_INIT(p_asidlock);
    12731052        preemption_disable();
    1274        
    12751053retry:
    12761054        (void) interrupts_disable();
    12771055        if (!spinlock_trylock(&asidlock)) {
    1278                 /*
     1056                /* 
    12791057                 * Avoid deadlock with TLB shootdown.
    12801058                 * We can enable interrupts here because
     
    12871065        }
    12881066        preemption_enable();
    1289        
     1067
    12901068        /*
    12911069         * First, take care of the old address space.
    1292          */
     1070         */     
    12931071        if (old_as) {
    12941072                ASSERT(old_as->cpu_refcount);
    1295                
    1296                 if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
     1073                if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    12971074                        /*
    12981075                         * The old address space is no longer active on
     
    13021079                         */
    13031080                        ASSERT(old_as->asid != ASID_INVALID);
    1304                        
    13051081                        list_append(&old_as->inactive_as_with_asid_link,
    13061082                            &inactive_as_with_asid_head);
    13071083                }
    1308                
     1084
    13091085                /*
    13101086                 * Perform architecture-specific tasks when the address space
     
    13131089                as_deinstall_arch(old_as);
    13141090        }
    1315        
     1091
    13161092        /*
    13171093         * Second, prepare the new address space.
     
    13231099                        new_as->asid = asid_get();
    13241100        }
    1325        
    13261101#ifdef AS_PAGE_TABLE
    13271102        SET_PTL0_ADDRESS(new_as->genarch.page_table);
     
    13331108         */
    13341109        as_install_arch(new_as);
    1335        
     1110
    13361111        spinlock_unlock(&asidlock);
    13371112       
     
    13391114}
    13401115
     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
    13411143/** Compute flags for virtual address translation subsytem.
    13421144 *
    1343  * @param area Address space area.
    1344  *
    1345  * @return Flags to be used in page_mapping_insert().
    1346  *
    1347  */
    1348 NO_TRACE unsigned int as_area_get_flags(as_area_t *area)
    1349 {
    1350         ASSERT(mutex_locked(&area->lock));
    1351        
    1352         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);
    13531155}
    13541156
     
    13581160 * table.
    13591161 *
    1360  * @param flags Flags saying whether the page table is for the kernel
    1361  *              address space.
    1362  *
    1363  * @return First entry of the page table.
    1364  *
    1365  */
    1366 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)
    13671168{
    13681169        ASSERT(as_operations);
     
    13761177 * Destroy page table in architecture specific way.
    13771178 *
    1378  * @param page_table Physical address of PTL0.
    1379  *
    1380  */
    1381 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)
    13821182{
    13831183        ASSERT(as_operations);
     
    13911191 * This function should be called before any page_mapping_insert(),
    13921192 * page_mapping_remove() and page_mapping_find().
    1393  *
     1193 * 
    13941194 * Locking order is such that address space areas must be locked
    13951195 * prior to this call. Address space can be locked prior to this
    13961196 * call in which case the lock argument is false.
    13971197 *
    1398  * @param as   Address space.
    1399  * @param lock If false, do not attempt to lock as->lock.
    1400  *
    1401  */
    1402 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)
    14031202{
    14041203        ASSERT(as_operations);
     
    14101209/** Unlock page table.
    14111210 *
    1412  * @param as     Address space.
    1413  * @param unlock If false, do not attempt to unlock as->lock.
    1414  *
    1415  */
    1416 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)
    14171215{
    14181216        ASSERT(as_operations);
     
    14221220}
    14231221
    1424 /** Test whether page tables are locked.
    1425  *
    1426  * @param as Address space where the page tables belong.
    1427  *
    1428  * @return True if the page tables belonging to the address soace
    1429  *         are locked, otherwise false.
    1430  */
    1431 NO_TRACE bool page_table_locked(as_t *as)
    1432 {
    1433         ASSERT(as_operations);
    1434         ASSERT(as_operations->page_table_locked);
    1435 
    1436         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;
    14371363}
    14381364
    14391365/** Return size of the address space area with given base.
    14401366 *
    1441  * @param base Arbitrary address inside the address space area.
    1442  *
    1443  * @return Size of the address space area in bytes or zero if it
    1444  *         does not exist.
    1445  *
     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.
    14461371 */
    14471372size_t as_area_get_size(uintptr_t base)
    14481373{
     1374        ipl_t ipl;
     1375        as_area_t *src_area;
    14491376        size_t size;
    1450        
    1451         page_table_lock(AS, true);
    1452         as_area_t *src_area = find_area_and_lock(AS, base);
    1453        
     1377
     1378        ipl = interrupts_disable();
     1379        src_area = find_area_and_lock(AS, base);
    14541380        if (src_area) {
    14551381                size = src_area->pages * PAGE_SIZE;
    14561382                mutex_unlock(&src_area->lock);
    1457         } else
     1383        } else {
    14581384                size = 0;
    1459        
    1460         page_table_unlock(AS, true);
     1385        }
     1386        interrupts_restore(ipl);
    14611387        return size;
    14621388}
     
    14661392 * The address space area must be already locked.
    14671393 *
    1468  * @param area  Address space area.
    1469  * @param page  First page to be marked.
    1470  * @param count Number of page to be marked.
    1471  *
    1472  * @return False on failure or true on success.
    1473  *
    1474  */
    1475 bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
    1476 {
    1477         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
    14781406        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    14791407        ASSERT(count);
    1480        
    1481         btree_node_t *leaf;
    1482         size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     1408
     1409        pages = (size_t) btree_search(&a->used_space, page, &leaf);
    14831410        if (pages) {
    14841411                /*
    14851412                 * We hit the beginning of some used space.
    14861413                 */
    1487                 return false;
    1488         }
    1489        
     1414                return 0;
     1415        }
     1416
    14901417        if (!leaf->keys) {
    1491                 btree_insert(&area->used_space, page, (void *) count, leaf);
    1492                 goto success;
    1493         }
    1494        
    1495         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
     1418                btree_insert(&a->used_space, page, (void *) count, leaf);
     1419                return 1;
     1420        }
     1421
     1422        node = btree_leaf_node_left_neighbour(&a->used_space, leaf);
    14961423        if (node) {
    14971424                uintptr_t left_pg = node->key[node->keys - 1];
     
    15051432                 * the left neigbour and the first interval of the leaf.
    15061433                 */
    1507                
     1434                 
    15081435                if (page >= right_pg) {
    15091436                        /* Do nothing. */
     
    15111438                    left_cnt * PAGE_SIZE)) {
    15121439                        /* The interval intersects with the left interval. */
    1513                         return false;
     1440                        return 0;
    15141441                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    15151442                    right_cnt * PAGE_SIZE)) {
    15161443                        /* The interval intersects with the right interval. */
    1517                         return false;
     1444                        return 0;                       
    15181445                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    15191446                    (page + count * PAGE_SIZE == right_pg)) {
     
    15231450                         */
    15241451                        node->value[node->keys - 1] += count + right_cnt;
    1525                         btree_remove(&area->used_space, right_pg, leaf);
    1526                         goto success;
     1452                        btree_remove(&a->used_space, right_pg, leaf);
     1453                        return 1;
    15271454                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    1528                         /*
     1455                        /* 
    15291456                         * The interval can be added by simply growing the left
    15301457                         * interval.
    15311458                         */
    15321459                        node->value[node->keys - 1] += count;
    1533                         goto success;
     1460                        return 1;
    15341461                } else if (page + count * PAGE_SIZE == right_pg) {
    15351462                        /*
     
    15401467                        leaf->value[0] += count;
    15411468                        leaf->key[0] = page;
    1542                         goto success;
     1469                        return 1;
    15431470                } else {
    15441471                        /*
     
    15461473                         * but cannot be merged with any of them.
    15471474                         */
    1548                         btree_insert(&area->used_space, page, (void *) count,
     1475                        btree_insert(&a->used_space, page, (void *) count,
    15491476                            leaf);
    1550                         goto success;
     1477                        return 1;
    15511478                }
    15521479        } else if (page < leaf->key[0]) {
    15531480                uintptr_t right_pg = leaf->key[0];
    15541481                size_t right_cnt = (size_t) leaf->value[0];
    1555                
     1482       
    15561483                /*
    15571484                 * Investigate the border case in which the left neighbour does
    15581485                 * not exist but the interval fits from the left.
    15591486                 */
    1560                
     1487                 
    15611488                if (overlaps(page, count * PAGE_SIZE, right_pg,
    15621489                    right_cnt * PAGE_SIZE)) {
    15631490                        /* The interval intersects with the right interval. */
    1564                         return false;
     1491                        return 0;
    15651492                } else if (page + count * PAGE_SIZE == right_pg) {
    15661493                        /*
     
    15711498                        leaf->key[0] = page;
    15721499                        leaf->value[0] += count;
    1573                         goto success;
     1500                        return 1;
    15741501                } else {
    15751502                        /*
     
    15771504                         * It must be added individually.
    15781505                         */
    1579                         btree_insert(&area->used_space, page, (void *) count,
     1506                        btree_insert(&a->used_space, page, (void *) count,
    15801507                            leaf);
    1581                         goto success;
    1582                 }
    1583         }
    1584        
    1585         node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
     1508                        return 1;
     1509                }
     1510        }
     1511
     1512        node = btree_leaf_node_right_neighbour(&a->used_space, leaf);
    15861513        if (node) {
    15871514                uintptr_t left_pg = leaf->key[leaf->keys - 1];
     
    15951522                 * the right neigbour and the last interval of the leaf.
    15961523                 */
    1597                
     1524
    15981525                if (page < left_pg) {
    15991526                        /* Do nothing. */
     
    16011528                    left_cnt * PAGE_SIZE)) {
    16021529                        /* The interval intersects with the left interval. */
    1603                         return false;
     1530                        return 0;
    16041531                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    16051532                    right_cnt * PAGE_SIZE)) {
    16061533                        /* The interval intersects with the right interval. */
    1607                         return false;
     1534                        return 0;                       
    16081535                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    16091536                    (page + count * PAGE_SIZE == right_pg)) {
     
    16111538                         * The interval can be added by merging the two already
    16121539                         * present intervals.
    1613                          */
     1540                         * */
    16141541                        leaf->value[leaf->keys - 1] += count + right_cnt;
    1615                         btree_remove(&area->used_space, right_pg, node);
    1616                         goto success;
     1542                        btree_remove(&a->used_space, right_pg, node);
     1543                        return 1;
    16171544                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16181545                        /*
    16191546                         * The interval can be added by simply growing the left
    16201547                         * interval.
    1621                          */
    1622                         leaf->value[leaf->keys - 1] += count;
    1623                         goto success;
     1548                         * */
     1549                        leaf->value[leaf->keys - 1] +=  count;
     1550                        return 1;
    16241551                } else if (page + count * PAGE_SIZE == right_pg) {
    16251552                        /*
     
    16301557                        node->value[0] += count;
    16311558                        node->key[0] = page;
    1632                         goto success;
     1559                        return 1;
    16331560                } else {
    16341561                        /*
     
    16361563                         * but cannot be merged with any of them.
    16371564                         */
    1638                         btree_insert(&area->used_space, page, (void *) count,
     1565                        btree_insert(&a->used_space, page, (void *) count,
    16391566                            leaf);
    1640                         goto success;
     1567                        return 1;
    16411568                }
    16421569        } else if (page >= leaf->key[leaf->keys - 1]) {
    16431570                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    16441571                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1645                
     1572       
    16461573                /*
    16471574                 * Investigate the border case in which the right neighbour
    16481575                 * does not exist but the interval fits from the right.
    16491576                 */
    1650                
     1577                 
    16511578                if (overlaps(page, count * PAGE_SIZE, left_pg,
    16521579                    left_cnt * PAGE_SIZE)) {
    16531580                        /* The interval intersects with the left interval. */
    1654                         return false;
     1581                        return 0;
    16551582                } else if (left_pg + left_cnt * PAGE_SIZE == page) {
    16561583                        /*
     
    16591586                         */
    16601587                        leaf->value[leaf->keys - 1] += count;
    1661                         goto success;
     1588                        return 1;
    16621589                } else {
    16631590                        /*
     
    16651592                         * It must be added individually.
    16661593                         */
    1667                         btree_insert(&area->used_space, page, (void *) count,
     1594                        btree_insert(&a->used_space, page, (void *) count,
    16681595                            leaf);
    1669                         goto success;
     1596                        return 1;
    16701597                }
    16711598        }
     
    16761603         * were already resolved.
    16771604         */
    1678         btree_key_t i;
    16791605        for (i = 1; i < leaf->keys; i++) {
    16801606                if (page < leaf->key[i]) {
     
    16831609                        size_t left_cnt = (size_t) leaf->value[i - 1];
    16841610                        size_t right_cnt = (size_t) leaf->value[i];
    1685                        
     1611
    16861612                        /*
    16871613                         * The interval fits between left_pg and right_pg.
    16881614                         */
    1689                        
     1615
    16901616                        if (overlaps(page, count * PAGE_SIZE, left_pg,
    16911617                            left_cnt * PAGE_SIZE)) {
     
    16941620                                 * interval.
    16951621                                 */
    1696                                 return false;
     1622                                return 0;
    16971623                        } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    16981624                            right_cnt * PAGE_SIZE)) {
     
    17011627                                 * interval.
    17021628                                 */
    1703                                 return false;
     1629                                return 0;                       
    17041630                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    17051631                            (page + count * PAGE_SIZE == right_pg)) {
     
    17091635                                 */
    17101636                                leaf->value[i - 1] += count + right_cnt;
    1711                                 btree_remove(&area->used_space, right_pg, leaf);
    1712                                 goto success;
     1637                                btree_remove(&a->used_space, right_pg, leaf);
     1638                                return 1;
    17131639                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    17141640                                /*
     
    17171643                                 */
    17181644                                leaf->value[i - 1] += count;
    1719                                 goto success;
     1645                                return 1;
    17201646                        } else if (page + count * PAGE_SIZE == right_pg) {
    17211647                                /*
    1722                                 * The interval can be addded by simply moving
     1648                                * The interval can be addded by simply moving
    17231649                                 * base of the right interval down and
    17241650                                 * increasing its size accordingly.
    1725                                  */
     1651                                 */
    17261652                                leaf->value[i] += count;
    17271653                                leaf->key[i] = page;
    1728                                 goto success;
     1654                                return 1;
    17291655                        } else {
    17301656                                /*
     
    17331659                                 * them.
    17341660                                 */
    1735                                 btree_insert(&area->used_space, page,
     1661                                btree_insert(&a->used_space, page,
    17361662                                    (void *) count, leaf);
    1737                                 goto success;
     1663                                return 1;
    17381664                        }
    17391665                }
    17401666        }
    1741        
    1742         panic("Inconsistency detected while adding %zu pages of used "
    1743             "space at %p.", count, (void *) page);
    1744        
    1745 success:
    1746         area->resident += count;
    1747         return true;
     1667
     1668        panic("Inconsistency detected while adding %" PRIs " pages of used "
     1669            "space at %p.", count, page);
    17481670}
    17491671
     
    17521674 * The address space area must be already locked.
    17531675 *
    1754  * @param area  Address space area.
    1755  * @param page  First page to be marked.
    1756  * @param count Number of page to be marked.
    1757  *
    1758  * @return False on failure or true on success.
    1759  *
    1760  */
    1761 bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
    1762 {
    1763         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
    17641688        ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
    17651689        ASSERT(count);
    1766        
    1767         btree_node_t *leaf;
    1768         size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     1690
     1691        pages = (size_t) btree_search(&a->used_space, page, &leaf);
    17691692        if (pages) {
    17701693                /*
     
    17721695                 */
    17731696                if (count > pages) {
    1774                         return false;
     1697                        return 0;
    17751698                } else if (count == pages) {
    1776                         btree_remove(&area->used_space, page, leaf);
    1777                         goto success;
     1699                        btree_remove(&a->used_space, page, leaf);
     1700                        return 1;
    17781701                } else {
    17791702                        /*
     
    17811704                         * Decrease its size and relocate its start address.
    17821705                         */
    1783                         btree_key_t i;
    17841706                        for (i = 0; i < leaf->keys; i++) {
    17851707                                if (leaf->key[i] == page) {
    17861708                                        leaf->key[i] += count * PAGE_SIZE;
    17871709                                        leaf->value[i] -= count;
    1788                                         goto success;
     1710                                        return 1;
    17891711                                }
    17901712                        }
    1791                        
    17921713                        goto error;
    17931714                }
    17941715        }
    1795        
    1796         btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    1797         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]) {
    17981719                uintptr_t left_pg = node->key[node->keys - 1];
    17991720                size_t left_cnt = (size_t) node->value[node->keys - 1];
    1800                
     1721
    18011722                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    18021723                    count * PAGE_SIZE)) {
     
    18101731                                 */
    18111732                                node->value[node->keys - 1] -= count;
    1812                                 goto success;
     1733                                return 1;
    18131734                        } else if (page + count * PAGE_SIZE <
    18141735                            left_pg + left_cnt*PAGE_SIZE) {
     1736                                size_t new_cnt;
     1737                               
    18151738                                /*
    18161739                                 * The interval is contained in the rightmost
     
    18201743                                 * new interval.
    18211744                                 */
    1822                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1745                                new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    18231746                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    18241747                                node->value[node->keys - 1] -= count + new_cnt;
    1825                                 btree_insert(&area->used_space, page +
     1748                                btree_insert(&a->used_space, page +
    18261749                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    1827                                 goto success;
     1750                                return 1;
    18281751                        }
    18291752                }
    1830                
    1831                 return false;
    1832         } else if (page < leaf->key[0])
    1833                 return false;
     1753                return 0;
     1754        } else if (page < leaf->key[0]) {
     1755                return 0;
     1756        }
    18341757       
    18351758        if (page > leaf->key[leaf->keys - 1]) {
    18361759                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    18371760                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1838                
     1761
    18391762                if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    18401763                    count * PAGE_SIZE)) {
    1841                         if (page + count * PAGE_SIZE ==
     1764                        if (page + count * PAGE_SIZE == 
    18421765                            left_pg + left_cnt * PAGE_SIZE) {
    18431766                                /*
     
    18471770                                 */
    18481771                                leaf->value[leaf->keys - 1] -= count;
    1849                                 goto success;
     1772                                return 1;
    18501773                        } else if (page + count * PAGE_SIZE < left_pg +
    18511774                            left_cnt * PAGE_SIZE) {
     1775                                size_t new_cnt;
     1776                               
    18521777                                /*
    18531778                                 * The interval is contained in the rightmost
     
    18571782                                 * interval.
    18581783                                 */
    1859                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1784                                new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    18601785                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    18611786                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    1862                                 btree_insert(&area->used_space, page +
     1787                                btree_insert(&a->used_space, page +
    18631788                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
    1864                                 goto success;
     1789                                return 1;
    18651790                        }
    18661791                }
    1867                
    1868                 return false;
    1869         }
     1792                return 0;
     1793        }       
    18701794       
    18711795        /*
    18721796         * The border cases have been already resolved.
    1873          * Now the interval can be only between intervals of the leaf.
    1874          */
    1875         btree_key_t i;
     1797         * Now the interval can be only between intervals of the leaf.
     1798         */
    18761799        for (i = 1; i < leaf->keys - 1; i++) {
    18771800                if (page < leaf->key[i]) {
    18781801                        uintptr_t left_pg = leaf->key[i - 1];
    18791802                        size_t left_cnt = (size_t) leaf->value[i - 1];
    1880                        
     1803
    18811804                        /*
    18821805                         * Now the interval is between intervals corresponding
     
    18941817                                         */
    18951818                                        leaf->value[i - 1] -= count;
    1896                                         goto success;
     1819                                        return 1;
    18971820                                } else if (page + count * PAGE_SIZE <
    18981821                                    left_pg + left_cnt * PAGE_SIZE) {
     1822                                        size_t new_cnt;
     1823                               
    18991824                                        /*
    19001825                                         * The interval is contained in the
     
    19041829                                         * also inserting a new interval.
    19051830                                         */
    1906                                         size_t new_cnt = ((left_pg +
     1831                                        new_cnt = ((left_pg +
    19071832                                            left_cnt * PAGE_SIZE) -
    19081833                                            (page + count * PAGE_SIZE)) >>
    19091834                                            PAGE_WIDTH;
    19101835                                        leaf->value[i - 1] -= count + new_cnt;
    1911                                         btree_insert(&area->used_space, page +
     1836                                        btree_insert(&a->used_space, page +
    19121837                                            count * PAGE_SIZE, (void *) new_cnt,
    19131838                                            leaf);
    1914                                         goto success;
     1839                                        return 1;
    19151840                                }
    19161841                        }
     1842                        return 0;
     1843                }
     1844        }
     1845
     1846error:
     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;
    19171875                       
    1918                         return false;
    1919                 }
    1920         }
    1921        
    1922 error:
    1923         panic("Inconsistency detected while removing %zu pages of used "
    1924             "space from %p.", count, (void *) page);
    1925        
    1926 success:
    1927         area->resident -= count;
    1928         return true;
     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        }
    19291888}
    19301889
     
    19341893
    19351894/** Wrapper for as_area_create(). */
    1936 sysarg_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)
    19371896{
    19381897        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
    19391898            AS_AREA_ATTR_NONE, &anon_backend, NULL))
    1940                 return (sysarg_t) address;
     1899                return (unative_t) address;
    19411900        else
    1942                 return (sysarg_t) -1;
     1901                return (unative_t) -1;
    19431902}
    19441903
    19451904/** Wrapper for as_area_resize(). */
    1946 sysarg_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
    1947 {
    1948         return (sysarg_t) as_area_resize(AS, address, size, 0);
     1905unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
     1906{
     1907        return (unative_t) as_area_resize(AS, address, size, 0);
    19491908}
    19501909
    19511910/** Wrapper for as_area_change_flags(). */
    1952 sysarg_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
    1953 {
    1954         return (sysarg_t) as_area_change_flags(AS, flags, address);
     1911unative_t sys_as_area_change_flags(uintptr_t address, int flags)
     1912{
     1913        return (unative_t) as_area_change_flags(AS, flags, address);
    19551914}
    19561915
    19571916/** Wrapper for as_area_destroy(). */
    1958 sysarg_t sys_as_area_destroy(uintptr_t address)
    1959 {
    1960         return (sysarg_t) as_area_destroy(AS, address);
    1961 }
    1962 
    1963 /** Get list of adress space areas.
    1964  *
    1965  * @param as    Address space.
    1966  * @param obuf  Place to save pointer to returned buffer.
    1967  * @param osize Place to save size of returned buffer.
    1968  *
    1969  */
    1970 void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
    1971 {
    1972         mutex_lock(&as->lock);
    1973        
    1974         /* First pass, count number of areas. */
    1975        
    1976         size_t area_cnt = 0;
    1977         link_t *cur;
    1978        
    1979         for (cur = as->as_area_btree.leaf_head.next;
    1980             cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1981                 btree_node_t *node =
    1982                     list_get_instance(cur, btree_node_t, leaf_link);
    1983                 area_cnt += node->keys;
    1984         }
    1985        
    1986         size_t isize = area_cnt * sizeof(as_area_info_t);
    1987         as_area_info_t *info = malloc(isize, 0);
    1988        
    1989         /* Second pass, record data. */
    1990        
    1991         size_t area_idx = 0;
    1992        
    1993         for (cur = as->as_area_btree.leaf_head.next;
    1994             cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    1995                 btree_node_t *node =
    1996                     list_get_instance(cur, btree_node_t, leaf_link);
    1997                 btree_key_t i;
    1998                
    1999                 for (i = 0; i < node->keys; i++) {
    2000                         as_area_t *area = node->value[i];
    2001                        
    2002                         ASSERT(area_idx < area_cnt);
    2003                         mutex_lock(&area->lock);
    2004                        
    2005                         info[area_idx].start_addr = area->base;
    2006                         info[area_idx].size = FRAMES2SIZE(area->pages);
    2007                         info[area_idx].flags = area->flags;
    2008                         ++area_idx;
    2009                        
    2010                         mutex_unlock(&area->lock);
    2011                 }
    2012         }
    2013        
    2014         mutex_unlock(&as->lock);
    2015        
    2016         *obuf = info;
    2017         *osize = isize;
     1917unative_t sys_as_area_destroy(uintptr_t address)
     1918{
     1919        return (unative_t) as_area_destroy(AS, address);
    20181920}
    20191921
    20201922/** Print out information about address space.
    20211923 *
    2022  * @param as Address space.
    2023  *
     1924 * @param as            Address space.
    20241925 */
    20251926void as_print(as_t *as)
    20261927{
     1928        ipl_t ipl;
     1929       
     1930        ipl = interrupts_disable();
    20271931        mutex_lock(&as->lock);
    20281932       
     
    20311935        for (cur = as->as_area_btree.leaf_head.next;
    20321936            cur != &as->as_area_btree.leaf_head; cur = cur->next) {
    2033                 btree_node_t *node
    2034                     = list_get_instance(cur, btree_node_t, leaf_link);
    2035                 btree_key_t i;
     1937                btree_node_t *node;
    20361938               
     1939                node = list_get_instance(cur, btree_node_t, leaf_link);
     1940               
     1941                unsigned int i;
    20371942                for (i = 0; i < node->keys; i++) {
    20381943                        as_area_t *area = node->value[i];
    2039                        
     1944               
    20401945                        mutex_lock(&area->lock);
    2041                         printf("as_area: %p, base=%p, pages=%zu"
    2042                             " (%p - %p)\n", area, (void *) area->base,
    2043                             area->pages, (void *) area->base,
    2044                             (void *) (area->base + FRAMES2SIZE(area->pages)));
     1946                        printf("as_area: %p, base=%p, pages=%" PRIs
     1947                            " (%p - %p)\n", area, area->base, area->pages,
     1948                            area->base, area->base + FRAMES2SIZE(area->pages));
    20451949                        mutex_unlock(&area->lock);
    20461950                }
     
    20481952       
    20491953        mutex_unlock(&as->lock);
     1954        interrupts_restore(ipl);
    20501955}
    20511956
Note: See TracChangeset for help on using the changeset viewer.