Changeset 8b655705 in mainline for kernel/generic/src/mm/as.c


Ignore:
Timestamp:
2011-04-15T19:38:07Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9dd730d1
Parents:
6b9e85b (diff), b2fb47f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r6b9e85b r8b655705  
    7171#include <memstr.h>
    7272#include <macros.h>
     73#include <bitops.h>
    7374#include <arch.h>
    7475#include <errno.h>
     
    8283 * Each architecture decides what functions will be used to carry out
    8384 * address space operations such as creating or locking page tables.
    84  *
    8585 */
    8686as_operations_t *as_operations = NULL;
    8787
    88 /**
    89  * Slab for as_t objects.
     88/** Slab for as_t objects.
    9089 *
    9190 */
    9291static slab_cache_t *as_slab;
    9392
    94 /**
    95  * This lock serializes access to the ASID subsystem.
    96  * It protects:
     93/** ASID subsystem lock.
     94 *
     95 * This lock protects:
    9796 * - inactive_as_with_asid_head list
    9897 * - as->asid for each as of the as_t type
     
    103102
    104103/**
    105  * This list contains address spaces that are not active on any
    106  * processor and that have valid ASID.
    107  *
     104 * Inactive address spaces (on all processors)
     105 * that have valid ASID.
    108106 */
    109107LIST_INITIALIZE(inactive_as_with_asid_head);
     
    119117        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    120118       
    121         int rc = as_constructor_arch(as, flags);
    122        
    123         return rc;
     119        return as_constructor_arch(as, flags);
    124120}
    125121
    126122NO_TRACE static size_t as_destructor(void *obj)
    127123{
    128         as_t *as = (as_t *) obj;
    129         return as_destructor_arch(as);
     124        return as_destructor_arch((as_t *) obj);
    130125}
    131126
     
    142137                panic("Cannot create kernel address space.");
    143138       
    144         /* Make sure the kernel address space
     139        /*
     140         * Make sure the kernel address space
    145141         * reference count never drops to zero.
    146142         */
     
    191187{
    192188        DEADLOCK_PROBE_INIT(p_asidlock);
    193 
     189       
    194190        ASSERT(as != AS);
    195191        ASSERT(atomic_get(&as->refcount) == 0);
     
    199195         * lock its mutex.
    200196         */
    201 
     197       
    202198        /*
    203199         * We need to avoid deadlock between TLB shootdown and asidlock.
     
    206202         * disabled to prevent nested context switches. We also depend on the
    207203         * fact that so far no spinlocks are held.
    208          *
    209204         */
    210205        preemption_disable();
     
    231226        spinlock_unlock(&asidlock);
    232227        interrupts_restore(ipl);
    233 
     228       
    234229       
    235230        /*
     
    237232         * The B+tree must be walked carefully because it is
    238233         * also being destroyed.
    239          *
    240234         */
    241235        bool cond = true;
     
    264258/** Hold a reference to an address space.
    265259 *
    266  * Holding a reference to an address space prevents destruction of that address
    267  * space.
     260 * Holding a reference to an address space prevents destruction
     261 * of that address space.
    268262 *
    269263 * @param as Address space to be held.
     
    277271/** Release a reference to an address space.
    278272 *
    279  * The last one to release a reference to an address space destroys the address
    280  * space.
     273 * The last one to release a reference to an address space
     274 * destroys the address space.
    281275 *
    282276 * @param asAddress space to be released.
     
    291285/** Check area conflicts with other areas.
    292286 *
    293  * @param as         Address space.
    294  * @param va         Starting virtual address of the area being tested.
    295  * @param size       Size of the area being tested.
    296  * @param avoid_area Do not touch this area.
     287 * @param as    Address space.
     288 * @param addr  Starting virtual address of the area being tested.
     289 * @param count Number of pages in the area being tested.
     290 * @param avoid Do not touch this area.
    297291 *
    298292 * @return True if there is no conflict, false otherwise.
    299293 *
    300294 */
    301 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
    302     as_area_t *avoid_area)
    303 {
     295NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
     296    size_t count, as_area_t *avoid)
     297{
     298        ASSERT((addr % PAGE_SIZE) == 0);
    304299        ASSERT(mutex_locked(&as->lock));
    305300       
    306301        /*
    307302         * We don't want any area to have conflicts with NULL page.
    308          *
    309          */
    310         if (overlaps(va, size, (uintptr_t) NULL, PAGE_SIZE))
     303         */
     304        if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
    311305                return false;
    312306       
     
    317311         * record in the left neighbour, the leftmost record in the right
    318312         * neighbour and all records in the leaf node itself.
    319          *
    320313         */
    321314        btree_node_t *leaf;
    322315        as_area_t *area =
    323             (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     316            (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
    324317        if (area) {
    325                 if (area != avoid_area)
     318                if (area != avoid)
    326319                        return false;
    327320        }
     
    333326                area = (as_area_t *) node->value[node->keys - 1];
    334327               
    335                 mutex_lock(&area->lock);
    336                
    337                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     328                if (area != avoid) {
     329                        mutex_lock(&area->lock);
     330                       
     331                        if (overlaps(addr, count << PAGE_WIDTH,
     332                            area->base, area->pages << PAGE_WIDTH)) {
     333                                mutex_unlock(&area->lock);
     334                                return false;
     335                        }
     336                       
    338337                        mutex_unlock(&area->lock);
    339                         return false;
    340                 }
    341                
    342                 mutex_unlock(&area->lock);
     338                }
    343339        }
    344340       
     
    347343                area = (as_area_t *) node->value[0];
    348344               
    349                 mutex_lock(&area->lock);
    350                
    351                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     345                if (area != avoid) {
     346                        mutex_lock(&area->lock);
     347                       
     348                        if (overlaps(addr, count << PAGE_WIDTH,
     349                            area->base, area->pages << PAGE_WIDTH)) {
     350                                mutex_unlock(&area->lock);
     351                                return false;
     352                        }
     353                       
    352354                        mutex_unlock(&area->lock);
    353                         return false;
    354                 }
    355                
    356                 mutex_unlock(&area->lock);
     355                }
    357356        }
    358357       
     
    362361                area = (as_area_t *) leaf->value[i];
    363362               
    364                 if (area == avoid_area)
     363                if (area == avoid)
    365364                        continue;
    366365               
    367366                mutex_lock(&area->lock);
    368367               
    369                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     368                if (overlaps(addr, count << PAGE_WIDTH,
     369                    area->base, area->pages << PAGE_WIDTH)) {
    370370                        mutex_unlock(&area->lock);
    371371                        return false;
     
    378378         * So far, the area does not conflict with other areas.
    379379         * Check if it doesn't conflict with kernel address space.
    380          *
    381380         */
    382381        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    383                 return !overlaps(va, size,
     382                return !overlaps(addr, count << PAGE_WIDTH,
    384383                    KERNEL_ADDRESS_SPACE_START,
    385384                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     
    408407    mem_backend_data_t *backend_data)
    409408{
    410         if (base % PAGE_SIZE)
     409        if ((base % PAGE_SIZE) != 0)
    411410                return NULL;
    412411       
    413         if (!size)
     412        if (size == 0)
    414413                return NULL;
     414       
     415        size_t pages = SIZE2FRAMES(size);
    415416       
    416417        /* Writeable executable areas are not supported. */
     
    420421        mutex_lock(&as->lock);
    421422       
    422         if (!check_area_conflicts(as, base, size, NULL)) {
     423        if (!check_area_conflicts(as, base, pages, NULL)) {
    423424                mutex_unlock(&as->lock);
    424425                return NULL;
     
    432433        area->flags = flags;
    433434        area->attributes = attrs;
    434         area->pages = SIZE2FRAMES(size);
     435        area->pages = pages;
     436        area->resident = 0;
    435437        area->base = base;
    436438        area->sh_info = NULL;
     
    475477         * to find out whether this is a miss or va belongs to an address
    476478         * space area found there.
    477          *
    478479         */
    479480       
     
    486487                mutex_lock(&area->lock);
    487488               
    488                 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     489                if ((area->base <= va) &&
     490                    (va < area->base + (area->pages << PAGE_WIDTH)))
    489491                        return area;
    490492               
     
    495497         * Second, locate the left neighbour and test its last record.
    496498         * Because of its position in the B+tree, it must have base < va.
    497          *
    498499         */
    499500        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     
    503504                mutex_lock(&area->lock);
    504505               
    505                 if (va < area->base + area->pages * PAGE_SIZE)
     506                if (va < area->base + (area->pages << PAGE_WIDTH))
    506507                        return area;
    507508               
     
    530531        /*
    531532         * Locate the area.
    532          *
    533533         */
    534534        as_area_t *area = find_area_and_lock(as, address);
     
    542542                 * Remapping of address space areas associated
    543543                 * with memory mapped devices is not supported.
    544                  *
    545544                 */
    546545                mutex_unlock(&area->lock);
     
    553552                 * Remapping of shared address space areas
    554553                 * is not supported.
    555                  *
    556554                 */
    557555                mutex_unlock(&area->lock);
     
    564562                /*
    565563                 * Zero size address space areas are not allowed.
    566                  *
    567564                 */
    568565                mutex_unlock(&area->lock);
     
    572569       
    573570        if (pages < area->pages) {
    574                 uintptr_t start_free = area->base + pages * PAGE_SIZE;
     571                uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
    575572               
    576573                /*
    577574                 * Shrinking the area.
    578575                 * No need to check for overlaps.
    579                  *
    580576                 */
    581577               
     
    584580                /*
    585581                 * Start TLB shootdown sequence.
    586                  *
    587582                 */
    588583                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    589                     area->base + pages * PAGE_SIZE, area->pages - pages);
     584                    area->base + (pages << PAGE_WIDTH), area->pages - pages);
    590585               
    591586                /*
     
    595590                 * is also the right way to remove part of the used_space
    596591                 * B+tree leaf list.
    597                  *
    598592                 */
    599593                bool cond = true;
     
    611605                                size_t i = 0;
    612606                               
    613                                 if (overlaps(ptr, size * PAGE_SIZE, area->base,
    614                                     pages * PAGE_SIZE)) {
     607                                if (overlaps(ptr, size << PAGE_WIDTH, area->base,
     608                                    pages << PAGE_WIDTH)) {
    615609                                       
    616                                         if (ptr + size * PAGE_SIZE <= start_free) {
     610                                        if (ptr + (size << PAGE_WIDTH) <= start_free) {
    617611                                                /*
    618612                                                 * The whole interval fits
    619613                                                 * completely in the resized
    620614                                                 * address space area.
    621                                                  *
    622615                                                 */
    623616                                                break;
     
    628621                                         * to b and c overlaps with the resized
    629622                                         * address space area.
    630                                          *
    631623                                         */
    632624                                       
     
    648640                                for (; i < size; i++) {
    649641                                        pte_t *pte = page_mapping_find(as, ptr +
    650                                             i * PAGE_SIZE);
     642                                            (i << PAGE_WIDTH));
    651643                                       
    652644                                        ASSERT(pte);
     
    657649                                            (area->backend->frame_free)) {
    658650                                                area->backend->frame_free(area,
    659                                                     ptr + i * PAGE_SIZE,
     651                                                    ptr + (i << PAGE_WIDTH),
    660652                                                    PTE_GET_FRAME(pte));
    661653                                        }
    662654                                       
    663655                                        page_mapping_remove(as, ptr +
    664                                             i * PAGE_SIZE);
     656                                            (i << PAGE_WIDTH));
    665657                                }
    666658                        }
     
    669661                /*
    670662                 * Finish TLB shootdown sequence.
    671                  *
    672                  */
    673                
    674                 tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
     663                 */
     664               
     665                tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
    675666                    area->pages - pages);
    676667               
    677668                /*
    678669                 * Invalidate software translation caches (e.g. TSB on sparc64).
    679                  *
    680670                 */
    681671                as_invalidate_translation_cache(as, area->base +
    682                     pages * PAGE_SIZE, area->pages - pages);
     672                    (pages << PAGE_WIDTH), area->pages - pages);
    683673                tlb_shootdown_finalize(ipl);
    684674               
     
    688678                 * Growing the area.
    689679                 * Check for overlaps with other address space areas.
    690                  *
    691                  */
    692                 if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    693                     area)) {
     680                 */
     681                if (!check_area_conflicts(as, address, pages, area)) {
    694682                        mutex_unlock(&area->lock);
    695683                        mutex_unlock(&as->lock);
     
    790778                       
    791779                        for (size = 0; size < (size_t) node->value[i]; size++) {
    792                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     780                                pte_t *pte =
     781                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    793782                               
    794783                                ASSERT(pte);
     
    799788                                    (area->backend->frame_free)) {
    800789                                        area->backend->frame_free(area,
    801                                             ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
     790                                            ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
    802791                                }
    803792                               
    804                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     793                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    805794                        }
    806795                }
     
    809798        /*
    810799         * Finish TLB shootdown sequence.
    811          *
    812800         */
    813801       
     
    817805         * Invalidate potential software translation caches (e.g. TSB on
    818806         * sparc64).
    819          *
    820807         */
    821808        as_invalidate_translation_cache(as, area->base, area->pages);
     
    835822        /*
    836823         * Remove the empty area from address space.
    837          *
    838824         */
    839825        btree_remove(&as->as_area_btree, base, NULL);
     
    877863                /*
    878864                 * Could not find the source address space area.
    879                  *
    880865                 */
    881866                mutex_unlock(&src_as->lock);
     
    887872                 * There is no backend or the backend does not
    888873                 * know how to share the area.
    889                  *
    890874                 */
    891875                mutex_unlock(&src_area->lock);
     
    894878        }
    895879       
    896         size_t src_size = src_area->pages * PAGE_SIZE;
     880        size_t src_size = src_area->pages << PAGE_WIDTH;
    897881        unsigned int src_flags = src_area->flags;
    898882        mem_backend_t *src_backend = src_area->backend;
     
    914898         * First, prepare the area for sharing.
    915899         * Then it will be safe to unlock it.
    916          *
    917900         */
    918901        share_info_t *sh_info = src_area->sh_info;
     
    926909                /*
    927910                 * Call the backend to setup sharing.
    928                  *
    929911                 */
    930912                src_area->backend->share(src_area);
     
    945927         * The flags of the source area are masked against dst_flags_mask
    946928         * to support sharing in less privileged mode.
    947          *
    948929         */
    949930        as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
     
    962943         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    963944         * attribute and set the sh_info.
    964          *
    965945         */
    966946        mutex_lock(&dst_as->lock);
     
    985965NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
    986966{
     967        ASSERT(mutex_locked(&area->lock));
     968       
    987969        int flagmap[] = {
    988970                [PF_ACCESS_READ] = AS_AREA_READ,
     
    990972                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    991973        };
    992 
    993         ASSERT(mutex_locked(&area->lock));
    994974       
    995975        if (!(area->flags & flagmap[access]))
     
    10621042        /*
    10631043         * Compute total number of used pages in the used_space B+tree
    1064          *
    10651044         */
    10661045        size_t used_pages = 0;
     
    10841063        /*
    10851064         * Start TLB shootdown sequence.
    1086          *
    10871065         */
    10881066        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     
    10921070         * Remove used pages from page tables and remember their frame
    10931071         * numbers.
    1094          *
    10951072         */
    10961073        size_t frame_idx = 0;
     
    11071084                       
    11081085                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1109                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     1086                                pte_t *pte =
     1087                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    11101088                               
    11111089                                ASSERT(pte);
     
    11161094                               
    11171095                                /* Remove old mapping */
    1118                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     1096                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    11191097                        }
    11201098                }
     
    11231101        /*
    11241102         * Finish TLB shootdown sequence.
    1125          *
    11261103         */
    11271104       
     
    11311108         * Invalidate potential software translation caches (e.g. TSB on
    11321109         * sparc64).
    1133          *
    11341110         */
    11351111        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11641140                               
    11651141                                /* Insert the new mapping */
    1166                                 page_mapping_insert(as, ptr + size * PAGE_SIZE,
     1142                                page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
    11671143                                    old_frame[frame_idx++], page_flags);
    11681144                               
     
    12131189                 * No area contained mapping for 'page'.
    12141190                 * Signal page fault to low-level handler.
    1215                  *
    12161191                 */
    12171192                mutex_unlock(&AS->lock);
     
    12331208                 * The address space area is not backed by any backend
    12341209                 * or the backend cannot handle page faults.
    1235                  *
    12361210                 */
    12371211                mutex_unlock(&area->lock);
     
    12451219         * To avoid race condition between two page faults on the same address,
    12461220         * we need to make sure the mapping has not been already inserted.
    1247          *
    12481221         */
    12491222        pte_t *pte;
     
    12631236        /*
    12641237         * Resort to the backend page fault handler.
    1265          *
    12661238         */
    12671239        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    13181290                 * preemption is disabled. We should not be
    13191291                 * holding any other lock.
    1320                  *
    13211292                 */
    13221293                (void) interrupts_enable();
     
    13381309                         * list of inactive address spaces with assigned
    13391310                         * ASID.
    1340                          *
    13411311                         */
    13421312                        ASSERT(old_as->asid != ASID_INVALID);
     
    13491319                 * Perform architecture-specific tasks when the address space
    13501320                 * is being removed from the CPU.
    1351                  *
    13521321                 */
    13531322                as_deinstall_arch(old_as);
     
    13561325        /*
    13571326         * Second, prepare the new address space.
    1358          *
    13591327         */
    13601328        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    13721340         * Perform architecture-specific steps.
    13731341         * (e.g. write ASID to hardware register etc.)
    1374          *
    13751342         */
    13761343        as_install_arch(new_as);
     
    13911358{
    13921359        ASSERT(mutex_locked(&area->lock));
    1393 
     1360       
    13941361        return area_flags_to_page_flags(area->flags);
    13951362}
     
    14951462       
    14961463        if (src_area) {
    1497                 size = src_area->pages * PAGE_SIZE;
     1464                size = src_area->pages << PAGE_WIDTH;
    14981465                mutex_unlock(&src_area->lock);
    14991466        } else
     
    15121479 * @param count Number of page to be marked.
    15131480 *
    1514  * @return Zero on failure and non-zero on success.
    1515  *
    1516  */
    1517 int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
     1481 * @return False on failure or true on success.
     1482 *
     1483 */
     1484bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
    15181485{
    15191486        ASSERT(mutex_locked(&area->lock));
     
    15261493                /*
    15271494                 * We hit the beginning of some used space.
    1528                  *
    1529                  */
    1530                 return 0;
     1495                 */
     1496                return false;
    15311497        }
    15321498       
    15331499        if (!leaf->keys) {
    15341500                btree_insert(&area->used_space, page, (void *) count, leaf);
    1535                 return 1;
     1501                goto success;
    15361502        }
    15371503       
     
    15471513                 * somewhere between the rightmost interval of
    15481514                 * the left neigbour and the first interval of the leaf.
    1549                  *
    15501515                 */
    15511516               
    15521517                if (page >= right_pg) {
    15531518                        /* Do nothing. */
    1554                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1555                     left_cnt * PAGE_SIZE)) {
     1519                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1520                    left_cnt << PAGE_WIDTH)) {
    15561521                        /* The interval intersects with the left interval. */
    1557                         return 0;
    1558                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1559                     right_cnt * PAGE_SIZE)) {
     1522                        return false;
     1523                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1524                    right_cnt << PAGE_WIDTH)) {
    15601525                        /* The interval intersects with the right interval. */
    1561                         return 0;
    1562                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1563                     (page + count * PAGE_SIZE == right_pg)) {
     1526                        return false;
     1527                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1528                    (page + (count << PAGE_WIDTH) == right_pg)) {
    15641529                        /*
    15651530                         * The interval can be added by merging the two already
    15661531                         * present intervals.
    1567                          *
    15681532                         */
    15691533                        node->value[node->keys - 1] += count + right_cnt;
    15701534                        btree_remove(&area->used_space, right_pg, leaf);
    1571                         return 1;
    1572                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1535                        goto success;
     1536                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    15731537                        /*
    15741538                         * The interval can be added by simply growing the left
    15751539                         * interval.
    1576                          *
    15771540                         */
    15781541                        node->value[node->keys - 1] += count;
    1579                         return 1;
    1580                 } else if (page + count * PAGE_SIZE == right_pg) {
     1542                        goto success;
     1543                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    15811544                        /*
    15821545                         * The interval can be addded by simply moving base of
    15831546                         * the right interval down and increasing its size
    15841547                         * accordingly.
    1585                          *
    15861548                         */
    15871549                        leaf->value[0] += count;
    15881550                        leaf->key[0] = page;
    1589                         return 1;
     1551                        goto success;
    15901552                } else {
    15911553                        /*
    15921554                         * The interval is between both neigbouring intervals,
    15931555                         * but cannot be merged with any of them.
    1594                          *
    15951556                         */
    15961557                        btree_insert(&area->used_space, page, (void *) count,
    15971558                            leaf);
    1598                         return 1;
     1559                        goto success;
    15991560                }
    16001561        } else if (page < leaf->key[0]) {
     
    16051566                 * Investigate the border case in which the left neighbour does
    16061567                 * not exist but the interval fits from the left.
    1607                  *
    1608                  */
    1609                
    1610                 if (overlaps(page, count * PAGE_SIZE, right_pg,
    1611                     right_cnt * PAGE_SIZE)) {
     1568                 */
     1569               
     1570                if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1571                    right_cnt << PAGE_WIDTH)) {
    16121572                        /* The interval intersects with the right interval. */
    1613                         return 0;
    1614                 } else if (page + count * PAGE_SIZE == right_pg) {
     1573                        return false;
     1574                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    16151575                        /*
    16161576                         * The interval can be added by moving the base of the
    16171577                         * right interval down and increasing its size
    16181578                         * accordingly.
    1619                          *
    16201579                         */
    16211580                        leaf->key[0] = page;
    16221581                        leaf->value[0] += count;
    1623                         return 1;
     1582                        goto success;
    16241583                } else {
    16251584                        /*
    16261585                         * The interval doesn't adjoin with the right interval.
    16271586                         * It must be added individually.
    1628                          *
    16291587                         */
    16301588                        btree_insert(&area->used_space, page, (void *) count,
    16311589                            leaf);
    1632                         return 1;
     1590                        goto success;
    16331591                }
    16341592        }
     
    16451603                 * somewhere between the leftmost interval of
    16461604                 * the right neigbour and the last interval of the leaf.
    1647                  *
    16481605                 */
    16491606               
    16501607                if (page < left_pg) {
    16511608                        /* Do nothing. */
    1652                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1653                     left_cnt * PAGE_SIZE)) {
     1609                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1610                    left_cnt << PAGE_WIDTH)) {
    16541611                        /* The interval intersects with the left interval. */
    1655                         return 0;
    1656                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1657                     right_cnt * PAGE_SIZE)) {
     1612                        return false;
     1613                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1614                    right_cnt << PAGE_WIDTH)) {
    16581615                        /* The interval intersects with the right interval. */
    1659                         return 0;
    1660                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1661                     (page + count * PAGE_SIZE == right_pg)) {
     1616                        return false;
     1617                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1618                    (page + (count << PAGE_WIDTH) == right_pg)) {
    16621619                        /*
    16631620                         * The interval can be added by merging the two already
    16641621                         * present intervals.
    1665                          *
    16661622                         */
    16671623                        leaf->value[leaf->keys - 1] += count + right_cnt;
    16681624                        btree_remove(&area->used_space, right_pg, node);
    1669                         return 1;
    1670                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1625                        goto success;
     1626                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    16711627                        /*
    16721628                         * The interval can be added by simply growing the left
    16731629                         * interval.
    1674                          *
    16751630                         */
    1676                         leaf->value[leaf->keys - 1] +=  count;
    1677                         return 1;
    1678                 } else if (page + count * PAGE_SIZE == right_pg) {
     1631                        leaf->value[leaf->keys - 1] += count;
     1632                        goto success;
     1633                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    16791634                        /*
    16801635                         * The interval can be addded by simply moving base of
    16811636                         * the right interval down and increasing its size
    16821637                         * accordingly.
    1683                          *
    16841638                         */
    16851639                        node->value[0] += count;
    16861640                        node->key[0] = page;
    1687                         return 1;
     1641                        goto success;
    16881642                } else {
    16891643                        /*
    16901644                         * The interval is between both neigbouring intervals,
    16911645                         * but cannot be merged with any of them.
    1692                          *
    16931646                         */
    16941647                        btree_insert(&area->used_space, page, (void *) count,
    16951648                            leaf);
    1696                         return 1;
     1649                        goto success;
    16971650                }
    16981651        } else if (page >= leaf->key[leaf->keys - 1]) {
     
    17031656                 * Investigate the border case in which the right neighbour
    17041657                 * does not exist but the interval fits from the right.
    1705                  *
    1706                  */
    1707                
    1708                 if (overlaps(page, count * PAGE_SIZE, left_pg,
    1709                     left_cnt * PAGE_SIZE)) {
     1658                 */
     1659               
     1660                if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1661                    left_cnt << PAGE_WIDTH)) {
    17101662                        /* The interval intersects with the left interval. */
    1711                         return 0;
    1712                 } else if (left_pg + left_cnt * PAGE_SIZE == page) {
     1663                        return false;
     1664                } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
    17131665                        /*
    17141666                         * The interval can be added by growing the left
    17151667                         * interval.
    1716                          *
    17171668                         */
    17181669                        leaf->value[leaf->keys - 1] += count;
    1719                         return 1;
     1670                        goto success;
    17201671                } else {
    17211672                        /*
    17221673                         * The interval doesn't adjoin with the left interval.
    17231674                         * It must be added individually.
    1724                          *
    17251675                         */
    17261676                        btree_insert(&area->used_space, page, (void *) count,
    17271677                            leaf);
    1728                         return 1;
     1678                        goto success;
    17291679                }
    17301680        }
     
    17341684         * only between two other intervals of the leaf. The two border cases
    17351685         * were already resolved.
    1736          *
    17371686         */
    17381687        btree_key_t i;
     
    17461695                        /*
    17471696                         * The interval fits between left_pg and right_pg.
    1748                          *
    17491697                         */
    17501698                       
    1751                         if (overlaps(page, count * PAGE_SIZE, left_pg,
    1752                             left_cnt * PAGE_SIZE)) {
     1699                        if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1700                            left_cnt << PAGE_WIDTH)) {
    17531701                                /*
    17541702                                 * The interval intersects with the left
    17551703                                 * interval.
    1756                                  *
    17571704                                 */
    1758                                 return 0;
    1759                         } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1760                             right_cnt * PAGE_SIZE)) {
     1705                                return false;
     1706                        } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1707                            right_cnt << PAGE_WIDTH)) {
    17611708                                /*
    17621709                                 * The interval intersects with the right
    17631710                                 * interval.
    1764                                  *
    17651711                                 */
    1766                                 return 0;
    1767                         } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1768                             (page + count * PAGE_SIZE == right_pg)) {
     1712                                return false;
     1713                        } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1714                            (page + (count << PAGE_WIDTH) == right_pg)) {
    17691715                                /*
    17701716                                 * The interval can be added by merging the two
    17711717                                 * already present intervals.
    1772                                  *
    17731718                                 */
    17741719                                leaf->value[i - 1] += count + right_cnt;
    17751720                                btree_remove(&area->used_space, right_pg, leaf);
    1776                                 return 1;
    1777                         } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1721                                goto success;
     1722                        } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    17781723                                /*
    17791724                                 * The interval can be added by simply growing
    17801725                                 * the left interval.
    1781                                  *
    17821726                                 */
    17831727                                leaf->value[i - 1] += count;
    1784                                 return 1;
    1785                         } else if (page + count * PAGE_SIZE == right_pg) {
     1728                                goto success;
     1729                        } else if (page + (count << PAGE_WIDTH) == right_pg) {
    17861730                                /*
    17871731                                 * The interval can be addded by simply moving
    17881732                                 * base of the right interval down and
    17891733                                 * increasing its size accordingly.
    1790                                  *
    17911734                                 */
    17921735                                leaf->value[i] += count;
    17931736                                leaf->key[i] = page;
    1794                                 return 1;
     1737                                goto success;
    17951738                        } else {
    17961739                                /*
     
    17981741                                 * intervals, but cannot be merged with any of
    17991742                                 * them.
    1800                                  *
    18011743                                 */
    18021744                                btree_insert(&area->used_space, page,
    18031745                                    (void *) count, leaf);
    1804                                 return 1;
     1746                                goto success;
    18051747                        }
    18061748                }
     
    18091751        panic("Inconsistency detected while adding %zu pages of used "
    18101752            "space at %p.", count, (void *) page);
     1753       
     1754success:
     1755        area->resident += count;
     1756        return true;
    18111757}
    18121758
     
    18191765 * @param count Number of page to be marked.
    18201766 *
    1821  * @return Zero on failure and non-zero on success.
    1822  *
    1823  */
    1824 int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
     1767 * @return False on failure or true on success.
     1768 *
     1769 */
     1770bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
    18251771{
    18261772        ASSERT(mutex_locked(&area->lock));
     
    18331779                /*
    18341780                 * We are lucky, page is the beginning of some interval.
    1835                  *
    18361781                 */
    18371782                if (count > pages) {
    1838                         return 0;
     1783                        return false;
    18391784                } else if (count == pages) {
    18401785                        btree_remove(&area->used_space, page, leaf);
    1841                         return 1;
     1786                        goto success;
    18421787                } else {
    18431788                        /*
    18441789                         * Find the respective interval.
    18451790                         * Decrease its size and relocate its start address.
    1846                          *
    18471791                         */
    18481792                        btree_key_t i;
    18491793                        for (i = 0; i < leaf->keys; i++) {
    18501794                                if (leaf->key[i] == page) {
    1851                                         leaf->key[i] += count * PAGE_SIZE;
     1795                                        leaf->key[i] += count << PAGE_WIDTH;
    18521796                                        leaf->value[i] -= count;
    1853                                         return 1;
     1797                                        goto success;
    18541798                                }
    18551799                        }
     1800                       
    18561801                        goto error;
    18571802                }
     
    18631808                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18641809               
    1865                 if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1866                     count * PAGE_SIZE)) {
    1867                         if (page + count * PAGE_SIZE ==
    1868                             left_pg + left_cnt * PAGE_SIZE) {
     1810                if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1811                    count << PAGE_WIDTH)) {
     1812                        if (page + (count << PAGE_WIDTH) ==
     1813                            left_pg + (left_cnt << PAGE_WIDTH)) {
    18691814                                /*
    18701815                                 * The interval is contained in the rightmost
     
    18721817                                 * removed by updating the size of the bigger
    18731818                                 * interval.
    1874                                  *
    18751819                                 */
    18761820                                node->value[node->keys - 1] -= count;
    1877                                 return 1;
    1878                         } else if (page + count * PAGE_SIZE <
    1879                             left_pg + left_cnt*PAGE_SIZE) {
     1821                                goto success;
     1822                        } else if (page + (count << PAGE_WIDTH) <
     1823                            left_pg + (left_cnt << PAGE_WIDTH)) {
    18801824                                /*
    18811825                                 * The interval is contained in the rightmost
     
    18841828                                 * the original interval and also inserting a
    18851829                                 * new interval.
    1886                                  *
    18871830                                 */
    1888                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1889                                     (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
     1831                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1832                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    18901833                                node->value[node->keys - 1] -= count + new_cnt;
    18911834                                btree_insert(&area->used_space, page +
    1892                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
    1893                                 return 1;
     1835                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1836                                goto success;
    18941837                        }
    18951838                }
    1896                 return 0;
     1839               
     1840                return false;
    18971841        } else if (page < leaf->key[0])
    1898                 return 0;
     1842                return false;
    18991843       
    19001844        if (page > leaf->key[leaf->keys - 1]) {
     
    19021846                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    19031847               
    1904                 if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1905                     count * PAGE_SIZE)) {
    1906                         if (page + count * PAGE_SIZE ==
    1907                             left_pg + left_cnt * PAGE_SIZE) {
     1848                if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1849                    count << PAGE_WIDTH)) {
     1850                        if (page + (count << PAGE_WIDTH) ==
     1851                            left_pg + (left_cnt << PAGE_WIDTH)) {
    19081852                                /*
    19091853                                 * The interval is contained in the rightmost
    19101854                                 * interval of the leaf and can be removed by
    19111855                                 * updating the size of the bigger interval.
    1912                                  *
    19131856                                 */
    19141857                                leaf->value[leaf->keys - 1] -= count;
    1915                                 return 1;
    1916                         } else if (page + count * PAGE_SIZE < left_pg +
    1917                             left_cnt * PAGE_SIZE) {
     1858                                goto success;
     1859                        } else if (page + (count << PAGE_WIDTH) < left_pg +
     1860                            (left_cnt << PAGE_WIDTH)) {
    19181861                                /*
    19191862                                 * The interval is contained in the rightmost
     
    19221865                                 * original interval and also inserting a new
    19231866                                 * interval.
    1924                                  *
    19251867                                 */
    1926                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1927                                     (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
     1868                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1869                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    19281870                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    19291871                                btree_insert(&area->used_space, page +
    1930                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
    1931                                 return 1;
     1872                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1873                                goto success;
    19321874                        }
    19331875                }
    1934                 return 0;
     1876               
     1877                return false;
    19351878        }
    19361879       
    19371880        /*
    19381881         * The border cases have been already resolved.
    1939          * Now the interval can be only between intervals of the leaf. 
     1882         * Now the interval can be only between intervals of the leaf.
    19401883         */
    19411884        btree_key_t i;
     
    19491892                         * to (i - 1) and i.
    19501893                         */
    1951                         if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1952                             count * PAGE_SIZE)) {
    1953                                 if (page + count * PAGE_SIZE ==
    1954                                     left_pg + left_cnt*PAGE_SIZE) {
     1894                        if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1895                            count << PAGE_WIDTH)) {
     1896                                if (page + (count << PAGE_WIDTH) ==
     1897                                    left_pg + (left_cnt << PAGE_WIDTH)) {
    19551898                                        /*
    19561899                                         * The interval is contained in the
     
    19581901                                         * be removed by updating the size of
    19591902                                         * the bigger interval.
    1960                                          *
    19611903                                         */
    19621904                                        leaf->value[i - 1] -= count;
    1963                                         return 1;
    1964                                 } else if (page + count * PAGE_SIZE <
    1965                                     left_pg + left_cnt * PAGE_SIZE) {
     1905                                        goto success;
     1906                                } else if (page + (count << PAGE_WIDTH) <
     1907                                    left_pg + (left_cnt << PAGE_WIDTH)) {
    19661908                                        /*
    19671909                                         * The interval is contained in the
     
    19721914                                         */
    19731915                                        size_t new_cnt = ((left_pg +
    1974                                             left_cnt * PAGE_SIZE) -
    1975                                             (page + count * PAGE_SIZE)) >>
     1916                                            (left_cnt << PAGE_WIDTH)) -
     1917                                            (page + (count << PAGE_WIDTH))) >>
    19761918                                            PAGE_WIDTH;
    19771919                                        leaf->value[i - 1] -= count + new_cnt;
    19781920                                        btree_insert(&area->used_space, page +
    1979                                             count * PAGE_SIZE, (void *) new_cnt,
     1921                                            (count << PAGE_WIDTH), (void *) new_cnt,
    19801922                                            leaf);
    1981                                         return 1;
     1923                                        goto success;
    19821924                                }
    19831925                        }
    1984                         return 0;
     1926                       
     1927                        return false;
    19851928                }
    19861929        }
     
    19891932        panic("Inconsistency detected while removing %zu pages of used "
    19901933            "space from %p.", count, (void *) page);
     1934       
     1935success:
     1936        area->resident -= count;
     1937        return true;
    19911938}
    19921939
     
    20231970}
    20241971
     1972/** Return pointer to unmapped address space area
     1973 *
     1974 * @param base Lowest address bound.
     1975 * @param size Requested size of the allocation.
     1976 *
     1977 * @return Pointer to the beginning of unmapped address space area.
     1978 *
     1979 */
     1980sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
     1981{
     1982        if (size == 0)
     1983                return 0;
     1984       
     1985        /*
     1986         * Make sure we allocate from page-aligned
     1987         * address. Check for possible overflow in
     1988         * each step.
     1989         */
     1990       
     1991        size_t pages = SIZE2FRAMES(size);
     1992        uintptr_t ret = 0;
     1993       
     1994        /*
     1995         * Find the lowest unmapped address aligned on the sz
     1996         * boundary, not smaller than base and of the required size.
     1997         */
     1998       
     1999        mutex_lock(&AS->lock);
     2000       
     2001        /* First check the base address itself */
     2002        uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
     2003        if ((addr >= base) &&
     2004            (check_area_conflicts(AS, addr, pages, NULL)))
     2005                ret = addr;
     2006       
     2007        /* Eventually check the addresses behind each area */
     2008        link_t *cur;
     2009        for (cur = AS->as_area_btree.leaf_head.next;
     2010            (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
     2011            cur = cur->next) {
     2012                btree_node_t *node =
     2013                    list_get_instance(cur, btree_node_t, leaf_link);
     2014               
     2015                btree_key_t i;
     2016                for (i = 0; (ret == 0) && (i < node->keys); i++) {
     2017                        as_area_t *area = (as_area_t *) node->value[i];
     2018                       
     2019                        mutex_lock(&area->lock);
     2020                       
     2021                        uintptr_t addr =
     2022                            ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
     2023                            PAGE_SIZE);
     2024                       
     2025                        if ((addr >= base) && (addr >= area->base) &&
     2026                            (check_area_conflicts(AS, addr, pages, area)))
     2027                                ret = addr;
     2028                       
     2029                        mutex_unlock(&area->lock);
     2030                }
     2031        }
     2032       
     2033        mutex_unlock(&AS->lock);
     2034       
     2035        return (sysarg_t) ret;
     2036}
     2037
    20252038/** Get list of adress space areas.
    20262039 *
     
    20892102        mutex_lock(&as->lock);
    20902103       
    2091         /* print out info about address space areas */
     2104        /* Print out info about address space areas */
    20922105        link_t *cur;
    20932106        for (cur = as->as_area_btree.leaf_head.next;
Note: See TracChangeset for help on using the changeset viewer.