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


Ignore:
Timestamp:
2011-06-01T08:43:42Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8d6c1f1
Parents:
9e2e715 (diff), e51a514 (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:

Huuuuuge merge from development - all the work actually :)

File:
1 edited

Legend:

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

    r9e2e715 reb522e8  
    7171#include <memstr.h>
    7272#include <macros.h>
     73#include <bitops.h>
    7374#include <arch.h>
    7475#include <errno.h>
     
    7980#include <arch/interrupt.h>
    8081
    81 #ifdef CONFIG_VIRT_IDX_DCACHE
    82 #include <arch/mm/cache.h>
    83 #endif /* CONFIG_VIRT_IDX_DCACHE */
    84 
    8582/**
    8683 * Each architecture decides what functions will be used to carry out
    8784 * address space operations such as creating or locking page tables.
    88  *
    8985 */
    9086as_operations_t *as_operations = NULL;
    9187
    92 /**
    93  * Slab for as_t objects.
     88/** Slab for as_t objects.
    9489 *
    9590 */
    9691static slab_cache_t *as_slab;
    9792
    98 /**
    99  * This lock serializes access to the ASID subsystem.
    100  * It protects:
     93/** ASID subsystem lock.
     94 *
     95 * This lock protects:
    10196 * - inactive_as_with_asid_head list
    10297 * - as->asid for each as of the as_t type
     
    107102
    108103/**
    109  * This list contains address spaces that are not active on any
    110  * processor and that have valid ASID.
    111  *
     104 * Inactive address spaces (on all processors)
     105 * that have valid ASID.
    112106 */
    113107LIST_INITIALIZE(inactive_as_with_asid_head);
     
    123117        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    124118       
    125         int rc = as_constructor_arch(as, flags);
    126        
    127         return rc;
     119        return as_constructor_arch(as, flags);
    128120}
    129121
    130122NO_TRACE static size_t as_destructor(void *obj)
    131123{
    132         as_t *as = (as_t *) obj;
    133         return as_destructor_arch(as);
     124        return as_destructor_arch((as_t *) obj);
    134125}
    135126
     
    146137                panic("Cannot create kernel address space.");
    147138       
    148         /* Make sure the kernel address space
     139        /*
     140         * Make sure the kernel address space
    149141         * reference count never drops to zero.
    150142         */
     
    195187{
    196188        DEADLOCK_PROBE_INIT(p_asidlock);
    197 
     189       
    198190        ASSERT(as != AS);
    199191        ASSERT(atomic_get(&as->refcount) == 0);
     
    203195         * lock its mutex.
    204196         */
    205 
     197       
    206198        /*
    207199         * We need to avoid deadlock between TLB shootdown and asidlock.
     
    210202         * disabled to prevent nested context switches. We also depend on the
    211203         * fact that so far no spinlocks are held.
    212          *
    213204         */
    214205        preemption_disable();
     
    235226        spinlock_unlock(&asidlock);
    236227        interrupts_restore(ipl);
    237 
     228       
    238229       
    239230        /*
     
    241232         * The B+tree must be walked carefully because it is
    242233         * also being destroyed.
    243          *
    244234         */
    245235        bool cond = true;
     
    268258/** Hold a reference to an address space.
    269259 *
    270  * Holding a reference to an address space prevents destruction of that address
    271  * space.
     260 * Holding a reference to an address space prevents destruction
     261 * of that address space.
    272262 *
    273263 * @param as Address space to be held.
     
    281271/** Release a reference to an address space.
    282272 *
    283  * The last one to release a reference to an address space destroys the address
    284  * space.
     273 * The last one to release a reference to an address space
     274 * destroys the address space.
    285275 *
    286276 * @param asAddress space to be released.
     
    295285/** Check area conflicts with other areas.
    296286 *
    297  * @param as         Address space.
    298  * @param va         Starting virtual address of the area being tested.
    299  * @param size       Size of the area being tested.
    300  * @param avoid_area Do not touch this area.
     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.
    301291 *
    302292 * @return True if there is no conflict, false otherwise.
    303293 *
    304294 */
    305 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
    306     as_area_t *avoid_area)
    307 {
     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);
    308299        ASSERT(mutex_locked(&as->lock));
    309300       
    310301        /*
    311302         * We don't want any area to have conflicts with NULL page.
    312          *
    313          */
    314         if (overlaps(va, size, NULL, PAGE_SIZE))
     303         */
     304        if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
    315305                return false;
    316306       
     
    321311         * record in the left neighbour, the leftmost record in the right
    322312         * neighbour and all records in the leaf node itself.
    323          *
    324313         */
    325314        btree_node_t *leaf;
    326315        as_area_t *area =
    327             (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
     316            (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
    328317        if (area) {
    329                 if (area != avoid_area)
     318                if (area != avoid)
    330319                        return false;
    331320        }
     
    337326                area = (as_area_t *) node->value[node->keys - 1];
    338327               
    339                 mutex_lock(&area->lock);
    340                
    341                 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                       
    342337                        mutex_unlock(&area->lock);
    343                         return false;
    344                 }
    345                
    346                 mutex_unlock(&area->lock);
     338                }
    347339        }
    348340       
     
    351343                area = (as_area_t *) node->value[0];
    352344               
    353                 mutex_lock(&area->lock);
    354                
    355                 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                       
    356354                        mutex_unlock(&area->lock);
    357                         return false;
    358                 }
    359                
    360                 mutex_unlock(&area->lock);
     355                }
    361356        }
    362357       
     
    366361                area = (as_area_t *) leaf->value[i];
    367362               
    368                 if (area == avoid_area)
     363                if (area == avoid)
    369364                        continue;
    370365               
    371366                mutex_lock(&area->lock);
    372367               
    373                 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
     368                if (overlaps(addr, count << PAGE_WIDTH,
     369                    area->base, area->pages << PAGE_WIDTH)) {
    374370                        mutex_unlock(&area->lock);
    375371                        return false;
     
    382378         * So far, the area does not conflict with other areas.
    383379         * Check if it doesn't conflict with kernel address space.
    384          *
    385380         */
    386381        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    387                 return !overlaps(va, size,
     382                return !overlaps(addr, count << PAGE_WIDTH,
    388383                    KERNEL_ADDRESS_SPACE_START,
    389384                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     
    412407    mem_backend_data_t *backend_data)
    413408{
    414         if (base % PAGE_SIZE)
     409        if ((base % PAGE_SIZE) != 0)
    415410                return NULL;
    416411       
    417         if (!size)
     412        if (size == 0)
    418413                return NULL;
     414       
     415        size_t pages = SIZE2FRAMES(size);
    419416       
    420417        /* Writeable executable areas are not supported. */
     
    424421        mutex_lock(&as->lock);
    425422       
    426         if (!check_area_conflicts(as, base, size, NULL)) {
     423        if (!check_area_conflicts(as, base, pages, NULL)) {
    427424                mutex_unlock(&as->lock);
    428425                return NULL;
     
    436433        area->flags = flags;
    437434        area->attributes = attrs;
    438         area->pages = SIZE2FRAMES(size);
     435        area->pages = pages;
     436        area->resident = 0;
    439437        area->base = base;
    440438        area->sh_info = NULL;
     
    445443        else
    446444                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
     445       
     446        if (area->backend && area->backend->create) {
     447                if (!area->backend->create(area)) {
     448                        free(area);
     449                        mutex_unlock(&as->lock);
     450                        return NULL;
     451                }
     452        }
    447453       
    448454        btree_create(&area->used_space);
     
    479485         * to find out whether this is a miss or va belongs to an address
    480486         * space area found there.
    481          *
    482487         */
    483488       
     
    490495                mutex_lock(&area->lock);
    491496               
    492                 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
     497                if ((area->base <= va) &&
     498                    (va < area->base + (area->pages << PAGE_WIDTH)))
    493499                        return area;
    494500               
     
    499505         * Second, locate the left neighbour and test its last record.
    500506         * Because of its position in the B+tree, it must have base < va.
    501          *
    502507         */
    503508        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     
    507512                mutex_lock(&area->lock);
    508513               
    509                 if (va < area->base + area->pages * PAGE_SIZE)
     514                if (va < area->base + (area->pages << PAGE_WIDTH))
    510515                        return area;
    511516               
     
    534539        /*
    535540         * Locate the area.
    536          *
    537541         */
    538542        as_area_t *area = find_area_and_lock(as, address);
     
    546550                 * Remapping of address space areas associated
    547551                 * with memory mapped devices is not supported.
    548                  *
    549552                 */
    550553                mutex_unlock(&area->lock);
     
    557560                 * Remapping of shared address space areas
    558561                 * is not supported.
    559                  *
    560562                 */
    561563                mutex_unlock(&area->lock);
     
    568570                /*
    569571                 * Zero size address space areas are not allowed.
    570                  *
    571572                 */
    572573                mutex_unlock(&area->lock);
     
    576577       
    577578        if (pages < area->pages) {
    578                 uintptr_t start_free = area->base + pages * PAGE_SIZE;
     579                uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
    579580               
    580581                /*
    581582                 * Shrinking the area.
    582583                 * No need to check for overlaps.
    583                  *
    584584                 */
    585585               
     
    588588                /*
    589589                 * Start TLB shootdown sequence.
    590                  *
    591590                 */
    592591                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    593                     area->base + pages * PAGE_SIZE, area->pages - pages);
     592                    area->base + (pages << PAGE_WIDTH), area->pages - pages);
    594593               
    595594                /*
     
    599598                 * is also the right way to remove part of the used_space
    600599                 * B+tree leaf list.
    601                  *
    602600                 */
    603601                bool cond = true;
     
    615613                                size_t i = 0;
    616614                               
    617                                 if (overlaps(ptr, size * PAGE_SIZE, area->base,
    618                                     pages * PAGE_SIZE)) {
     615                                if (overlaps(ptr, size << PAGE_WIDTH, area->base,
     616                                    pages << PAGE_WIDTH)) {
    619617                                       
    620                                         if (ptr + size * PAGE_SIZE <= start_free) {
     618                                        if (ptr + (size << PAGE_WIDTH) <= start_free) {
    621619                                                /*
    622620                                                 * The whole interval fits
    623621                                                 * completely in the resized
    624622                                                 * address space area.
    625                                                  *
    626623                                                 */
    627624                                                break;
     
    632629                                         * to b and c overlaps with the resized
    633630                                         * address space area.
    634                                          *
    635631                                         */
    636632                                       
     
    652648                                for (; i < size; i++) {
    653649                                        pte_t *pte = page_mapping_find(as, ptr +
    654                                             i * PAGE_SIZE);
     650                                            (i << PAGE_WIDTH));
    655651                                       
    656652                                        ASSERT(pte);
     
    661657                                            (area->backend->frame_free)) {
    662658                                                area->backend->frame_free(area,
    663                                                     ptr + i * PAGE_SIZE,
     659                                                    ptr + (i << PAGE_WIDTH),
    664660                                                    PTE_GET_FRAME(pte));
    665661                                        }
    666662                                       
    667663                                        page_mapping_remove(as, ptr +
    668                                             i * PAGE_SIZE);
     664                                            (i << PAGE_WIDTH));
    669665                                }
    670666                        }
     
    673669                /*
    674670                 * Finish TLB shootdown sequence.
    675                  *
    676                  */
    677                
    678                 tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
     671                 */
     672               
     673                tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
    679674                    area->pages - pages);
    680675               
    681676                /*
    682677                 * Invalidate software translation caches (e.g. TSB on sparc64).
    683                  *
    684678                 */
    685679                as_invalidate_translation_cache(as, area->base +
    686                     pages * PAGE_SIZE, area->pages - pages);
     680                    (pages << PAGE_WIDTH), area->pages - pages);
    687681                tlb_shootdown_finalize(ipl);
    688682               
     
    692686                 * Growing the area.
    693687                 * Check for overlaps with other address space areas.
    694                  *
    695                  */
    696                 if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
    697                     area)) {
     688                 */
     689                if (!check_area_conflicts(as, address, pages, area)) {
    698690                        mutex_unlock(&area->lock);
    699691                        mutex_unlock(&as->lock);
    700692                        return EADDRNOTAVAIL;
     693                }
     694        }
     695       
     696        if (area->backend && area->backend->resize) {
     697                if (!area->backend->resize(area, pages)) {
     698                        mutex_unlock(&area->lock);
     699                        mutex_unlock(&as->lock);
     700                        return ENOMEM;
    701701                }
    702702        }
     
    768768                return ENOENT;
    769769        }
     770
     771        if (area->backend && area->backend->destroy)
     772                area->backend->destroy(area);
    770773       
    771774        uintptr_t base = area->base;
     
    794797                       
    795798                        for (size = 0; size < (size_t) node->value[i]; size++) {
    796                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     799                                pte_t *pte =
     800                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    797801                               
    798802                                ASSERT(pte);
     
    803807                                    (area->backend->frame_free)) {
    804808                                        area->backend->frame_free(area,
    805                                             ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
     809                                            ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
    806810                                }
    807811                               
    808                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     812                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    809813                        }
    810814                }
     
    813817        /*
    814818         * Finish TLB shootdown sequence.
    815          *
    816819         */
    817820       
     
    821824         * Invalidate potential software translation caches (e.g. TSB on
    822825         * sparc64).
    823          *
    824826         */
    825827        as_invalidate_translation_cache(as, area->base, area->pages);
     
    839841        /*
    840842         * Remove the empty area from address space.
    841          *
    842843         */
    843844        btree_remove(&as->as_area_btree, base, NULL);
     
    881882                /*
    882883                 * Could not find the source address space area.
    883                  *
    884884                 */
    885885                mutex_unlock(&src_as->lock);
     
    891891                 * There is no backend or the backend does not
    892892                 * know how to share the area.
    893                  *
    894893                 */
    895894                mutex_unlock(&src_area->lock);
     
    898897        }
    899898       
    900         size_t src_size = src_area->pages * PAGE_SIZE;
     899        size_t src_size = src_area->pages << PAGE_WIDTH;
    901900        unsigned int src_flags = src_area->flags;
    902901        mem_backend_t *src_backend = src_area->backend;
     
    918917         * First, prepare the area for sharing.
    919918         * Then it will be safe to unlock it.
    920          *
    921919         */
    922920        share_info_t *sh_info = src_area->sh_info;
     
    930928                /*
    931929                 * Call the backend to setup sharing.
    932                  *
    933930                 */
    934931                src_area->backend->share(src_area);
     
    949946         * The flags of the source area are masked against dst_flags_mask
    950947         * to support sharing in less privileged mode.
    951          *
    952948         */
    953949        as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
     
    966962         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    967963         * attribute and set the sh_info.
    968          *
    969964         */
    970965        mutex_lock(&dst_as->lock);
     
    989984NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
    990985{
     986        ASSERT(mutex_locked(&area->lock));
     987       
    991988        int flagmap[] = {
    992989                [PF_ACCESS_READ] = AS_AREA_READ,
     
    994991                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    995992        };
    996 
    997         ASSERT(mutex_locked(&area->lock));
    998993       
    999994        if (!(area->flags & flagmap[access]))
     
    10661061        /*
    10671062         * Compute total number of used pages in the used_space B+tree
    1068          *
    10691063         */
    10701064        size_t used_pages = 0;
     
    10881082        /*
    10891083         * Start TLB shootdown sequence.
    1090          *
    10911084         */
    10921085        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     
    10961089         * Remove used pages from page tables and remember their frame
    10971090         * numbers.
    1098          *
    10991091         */
    11001092        size_t frame_idx = 0;
     
    11111103                       
    11121104                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1113                                 pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
     1105                                pte_t *pte =
     1106                                    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
    11141107                               
    11151108                                ASSERT(pte);
     
    11201113                               
    11211114                                /* Remove old mapping */
    1122                                 page_mapping_remove(as, ptr + size * PAGE_SIZE);
     1115                                page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
    11231116                        }
    11241117                }
     
    11271120        /*
    11281121         * Finish TLB shootdown sequence.
    1129          *
    11301122         */
    11311123       
     
    11351127         * Invalidate potential software translation caches (e.g. TSB on
    11361128         * sparc64).
    1137          *
    11381129         */
    11391130        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11681159                               
    11691160                                /* Insert the new mapping */
    1170                                 page_mapping_insert(as, ptr + size * PAGE_SIZE,
     1161                                page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
    11711162                                    old_frame[frame_idx++], page_flags);
    11721163                               
     
    12171208                 * No area contained mapping for 'page'.
    12181209                 * Signal page fault to low-level handler.
    1219                  *
    12201210                 */
    12211211                mutex_unlock(&AS->lock);
     
    12371227                 * The address space area is not backed by any backend
    12381228                 * or the backend cannot handle page faults.
    1239                  *
    12401229                 */
    12411230                mutex_unlock(&area->lock);
     
    12491238         * To avoid race condition between two page faults on the same address,
    12501239         * we need to make sure the mapping has not been already inserted.
    1251          *
    12521240         */
    12531241        pte_t *pte;
     
    12671255        /*
    12681256         * Resort to the backend page fault handler.
    1269          *
    12701257         */
    12711258        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    13221309                 * preemption is disabled. We should not be
    13231310                 * holding any other lock.
    1324                  *
    13251311                 */
    13261312                (void) interrupts_enable();
     
    13421328                         * list of inactive address spaces with assigned
    13431329                         * ASID.
    1344                          *
    13451330                         */
    13461331                        ASSERT(old_as->asid != ASID_INVALID);
     
    13531338                 * Perform architecture-specific tasks when the address space
    13541339                 * is being removed from the CPU.
    1355                  *
    13561340                 */
    13571341                as_deinstall_arch(old_as);
     
    13601344        /*
    13611345         * Second, prepare the new address space.
    1362          *
    13631346         */
    13641347        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    13761359         * Perform architecture-specific steps.
    13771360         * (e.g. write ASID to hardware register etc.)
    1378          *
    13791361         */
    13801362        as_install_arch(new_as);
     
    13951377{
    13961378        ASSERT(mutex_locked(&area->lock));
    1397 
     1379       
    13981380        return area_flags_to_page_flags(area->flags);
    13991381}
     
    14991481       
    15001482        if (src_area) {
    1501                 size = src_area->pages * PAGE_SIZE;
     1483                size = src_area->pages << PAGE_WIDTH;
    15021484                mutex_unlock(&src_area->lock);
    15031485        } else
     
    15161498 * @param count Number of page to be marked.
    15171499 *
    1518  * @return Zero on failure and non-zero on success.
    1519  *
    1520  */
    1521 int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
     1500 * @return False on failure or true on success.
     1501 *
     1502 */
     1503bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
    15221504{
    15231505        ASSERT(mutex_locked(&area->lock));
     
    15301512                /*
    15311513                 * We hit the beginning of some used space.
    1532                  *
    1533                  */
    1534                 return 0;
     1514                 */
     1515                return false;
    15351516        }
    15361517       
    15371518        if (!leaf->keys) {
    15381519                btree_insert(&area->used_space, page, (void *) count, leaf);
    1539                 return 1;
     1520                goto success;
    15401521        }
    15411522       
     
    15511532                 * somewhere between the rightmost interval of
    15521533                 * the left neigbour and the first interval of the leaf.
    1553                  *
    15541534                 */
    15551535               
    15561536                if (page >= right_pg) {
    15571537                        /* Do nothing. */
    1558                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1559                     left_cnt * PAGE_SIZE)) {
     1538                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1539                    left_cnt << PAGE_WIDTH)) {
    15601540                        /* The interval intersects with the left interval. */
    1561                         return 0;
    1562                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1563                     right_cnt * PAGE_SIZE)) {
     1541                        return false;
     1542                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1543                    right_cnt << PAGE_WIDTH)) {
    15641544                        /* The interval intersects with the right interval. */
    1565                         return 0;
    1566                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1567                     (page + count * PAGE_SIZE == right_pg)) {
     1545                        return false;
     1546                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1547                    (page + (count << PAGE_WIDTH) == right_pg)) {
    15681548                        /*
    15691549                         * The interval can be added by merging the two already
    15701550                         * present intervals.
    1571                          *
    15721551                         */
    15731552                        node->value[node->keys - 1] += count + right_cnt;
    15741553                        btree_remove(&area->used_space, right_pg, leaf);
    1575                         return 1;
    1576                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1554                        goto success;
     1555                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    15771556                        /*
    15781557                         * The interval can be added by simply growing the left
    15791558                         * interval.
    1580                          *
    15811559                         */
    15821560                        node->value[node->keys - 1] += count;
    1583                         return 1;
    1584                 } else if (page + count * PAGE_SIZE == right_pg) {
     1561                        goto success;
     1562                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    15851563                        /*
    15861564                         * The interval can be addded by simply moving base of
    15871565                         * the right interval down and increasing its size
    15881566                         * accordingly.
    1589                          *
    15901567                         */
    15911568                        leaf->value[0] += count;
    15921569                        leaf->key[0] = page;
    1593                         return 1;
     1570                        goto success;
    15941571                } else {
    15951572                        /*
    15961573                         * The interval is between both neigbouring intervals,
    15971574                         * but cannot be merged with any of them.
    1598                          *
    15991575                         */
    16001576                        btree_insert(&area->used_space, page, (void *) count,
    16011577                            leaf);
    1602                         return 1;
     1578                        goto success;
    16031579                }
    16041580        } else if (page < leaf->key[0]) {
     
    16091585                 * Investigate the border case in which the left neighbour does
    16101586                 * not exist but the interval fits from the left.
    1611                  *
    1612                  */
    1613                
    1614                 if (overlaps(page, count * PAGE_SIZE, right_pg,
    1615                     right_cnt * PAGE_SIZE)) {
     1587                 */
     1588               
     1589                if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1590                    right_cnt << PAGE_WIDTH)) {
    16161591                        /* The interval intersects with the right interval. */
    1617                         return 0;
    1618                 } else if (page + count * PAGE_SIZE == right_pg) {
     1592                        return false;
     1593                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    16191594                        /*
    16201595                         * The interval can be added by moving the base of the
    16211596                         * right interval down and increasing its size
    16221597                         * accordingly.
    1623                          *
    16241598                         */
    16251599                        leaf->key[0] = page;
    16261600                        leaf->value[0] += count;
    1627                         return 1;
     1601                        goto success;
    16281602                } else {
    16291603                        /*
    16301604                         * The interval doesn't adjoin with the right interval.
    16311605                         * It must be added individually.
    1632                          *
    16331606                         */
    16341607                        btree_insert(&area->used_space, page, (void *) count,
    16351608                            leaf);
    1636                         return 1;
     1609                        goto success;
    16371610                }
    16381611        }
     
    16491622                 * somewhere between the leftmost interval of
    16501623                 * the right neigbour and the last interval of the leaf.
    1651                  *
    16521624                 */
    16531625               
    16541626                if (page < left_pg) {
    16551627                        /* Do nothing. */
    1656                 } else if (overlaps(page, count * PAGE_SIZE, left_pg,
    1657                     left_cnt * PAGE_SIZE)) {
     1628                } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1629                    left_cnt << PAGE_WIDTH)) {
    16581630                        /* The interval intersects with the left interval. */
    1659                         return 0;
    1660                 } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1661                     right_cnt * PAGE_SIZE)) {
     1631                        return false;
     1632                } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1633                    right_cnt << PAGE_WIDTH)) {
    16621634                        /* The interval intersects with the right interval. */
    1663                         return 0;
    1664                 } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1665                     (page + count * PAGE_SIZE == right_pg)) {
     1635                        return false;
     1636                } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1637                    (page + (count << PAGE_WIDTH) == right_pg)) {
    16661638                        /*
    16671639                         * The interval can be added by merging the two already
    16681640                         * present intervals.
    1669                          *
    16701641                         */
    16711642                        leaf->value[leaf->keys - 1] += count + right_cnt;
    16721643                        btree_remove(&area->used_space, right_pg, node);
    1673                         return 1;
    1674                 } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1644                        goto success;
     1645                } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    16751646                        /*
    16761647                         * The interval can be added by simply growing the left
    16771648                         * interval.
    1678                          *
    16791649                         */
    1680                         leaf->value[leaf->keys - 1] +=  count;
    1681                         return 1;
    1682                 } else if (page + count * PAGE_SIZE == right_pg) {
     1650                        leaf->value[leaf->keys - 1] += count;
     1651                        goto success;
     1652                } else if (page + (count << PAGE_WIDTH) == right_pg) {
    16831653                        /*
    16841654                         * The interval can be addded by simply moving base of
    16851655                         * the right interval down and increasing its size
    16861656                         * accordingly.
    1687                          *
    16881657                         */
    16891658                        node->value[0] += count;
    16901659                        node->key[0] = page;
    1691                         return 1;
     1660                        goto success;
    16921661                } else {
    16931662                        /*
    16941663                         * The interval is between both neigbouring intervals,
    16951664                         * but cannot be merged with any of them.
    1696                          *
    16971665                         */
    16981666                        btree_insert(&area->used_space, page, (void *) count,
    16991667                            leaf);
    1700                         return 1;
     1668                        goto success;
    17011669                }
    17021670        } else if (page >= leaf->key[leaf->keys - 1]) {
     
    17071675                 * Investigate the border case in which the right neighbour
    17081676                 * does not exist but the interval fits from the right.
    1709                  *
    1710                  */
    1711                
    1712                 if (overlaps(page, count * PAGE_SIZE, left_pg,
    1713                     left_cnt * PAGE_SIZE)) {
     1677                 */
     1678               
     1679                if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1680                    left_cnt << PAGE_WIDTH)) {
    17141681                        /* The interval intersects with the left interval. */
    1715                         return 0;
    1716                 } else if (left_pg + left_cnt * PAGE_SIZE == page) {
     1682                        return false;
     1683                } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
    17171684                        /*
    17181685                         * The interval can be added by growing the left
    17191686                         * interval.
    1720                          *
    17211687                         */
    17221688                        leaf->value[leaf->keys - 1] += count;
    1723                         return 1;
     1689                        goto success;
    17241690                } else {
    17251691                        /*
    17261692                         * The interval doesn't adjoin with the left interval.
    17271693                         * It must be added individually.
    1728                          *
    17291694                         */
    17301695                        btree_insert(&area->used_space, page, (void *) count,
    17311696                            leaf);
    1732                         return 1;
     1697                        goto success;
    17331698                }
    17341699        }
     
    17381703         * only between two other intervals of the leaf. The two border cases
    17391704         * were already resolved.
    1740          *
    17411705         */
    17421706        btree_key_t i;
     
    17501714                        /*
    17511715                         * The interval fits between left_pg and right_pg.
    1752                          *
    17531716                         */
    17541717                       
    1755                         if (overlaps(page, count * PAGE_SIZE, left_pg,
    1756                             left_cnt * PAGE_SIZE)) {
     1718                        if (overlaps(page, count << PAGE_WIDTH, left_pg,
     1719                            left_cnt << PAGE_WIDTH)) {
    17571720                                /*
    17581721                                 * The interval intersects with the left
    17591722                                 * interval.
    1760                                  *
    17611723                                 */
    1762                                 return 0;
    1763                         } else if (overlaps(page, count * PAGE_SIZE, right_pg,
    1764                             right_cnt * PAGE_SIZE)) {
     1724                                return false;
     1725                        } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
     1726                            right_cnt << PAGE_WIDTH)) {
    17651727                                /*
    17661728                                 * The interval intersects with the right
    17671729                                 * interval.
    1768                                  *
    17691730                                 */
    1770                                 return 0;
    1771                         } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
    1772                             (page + count * PAGE_SIZE == right_pg)) {
     1731                                return false;
     1732                        } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
     1733                            (page + (count << PAGE_WIDTH) == right_pg)) {
    17731734                                /*
    17741735                                 * The interval can be added by merging the two
    17751736                                 * already present intervals.
    1776                                  *
    17771737                                 */
    17781738                                leaf->value[i - 1] += count + right_cnt;
    17791739                                btree_remove(&area->used_space, right_pg, leaf);
    1780                                 return 1;
    1781                         } else if (page == left_pg + left_cnt * PAGE_SIZE) {
     1740                                goto success;
     1741                        } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
    17821742                                /*
    17831743                                 * The interval can be added by simply growing
    17841744                                 * the left interval.
    1785                                  *
    17861745                                 */
    17871746                                leaf->value[i - 1] += count;
    1788                                 return 1;
    1789                         } else if (page + count * PAGE_SIZE == right_pg) {
     1747                                goto success;
     1748                        } else if (page + (count << PAGE_WIDTH) == right_pg) {
    17901749                                /*
    17911750                                 * The interval can be addded by simply moving
    17921751                                 * base of the right interval down and
    17931752                                 * increasing its size accordingly.
    1794                                  *
    17951753                                 */
    17961754                                leaf->value[i] += count;
    17971755                                leaf->key[i] = page;
    1798                                 return 1;
     1756                                goto success;
    17991757                        } else {
    18001758                                /*
     
    18021760                                 * intervals, but cannot be merged with any of
    18031761                                 * them.
    1804                                  *
    18051762                                 */
    18061763                                btree_insert(&area->used_space, page,
    18071764                                    (void *) count, leaf);
    1808                                 return 1;
     1765                                goto success;
    18091766                        }
    18101767                }
    18111768        }
    18121769       
    1813         panic("Inconsistency detected while adding %" PRIs " pages of used "
    1814             "space at %p.", count, page);
     1770        panic("Inconsistency detected while adding %zu pages of used "
     1771            "space at %p.", count, (void *) page);
     1772       
     1773success:
     1774        area->resident += count;
     1775        return true;
    18151776}
    18161777
     
    18231784 * @param count Number of page to be marked.
    18241785 *
    1825  * @return Zero on failure and non-zero on success.
    1826  *
    1827  */
    1828 int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
     1786 * @return False on failure or true on success.
     1787 *
     1788 */
     1789bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
    18291790{
    18301791        ASSERT(mutex_locked(&area->lock));
     
    18371798                /*
    18381799                 * We are lucky, page is the beginning of some interval.
    1839                  *
    18401800                 */
    18411801                if (count > pages) {
    1842                         return 0;
     1802                        return false;
    18431803                } else if (count == pages) {
    18441804                        btree_remove(&area->used_space, page, leaf);
    1845                         return 1;
     1805                        goto success;
    18461806                } else {
    18471807                        /*
    18481808                         * Find the respective interval.
    18491809                         * Decrease its size and relocate its start address.
    1850                          *
    18511810                         */
    18521811                        btree_key_t i;
    18531812                        for (i = 0; i < leaf->keys; i++) {
    18541813                                if (leaf->key[i] == page) {
    1855                                         leaf->key[i] += count * PAGE_SIZE;
     1814                                        leaf->key[i] += count << PAGE_WIDTH;
    18561815                                        leaf->value[i] -= count;
    1857                                         return 1;
     1816                                        goto success;
    18581817                                }
    18591818                        }
     1819                       
    18601820                        goto error;
    18611821                }
     
    18671827                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18681828               
    1869                 if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1870                     count * PAGE_SIZE)) {
    1871                         if (page + count * PAGE_SIZE ==
    1872                             left_pg + left_cnt * PAGE_SIZE) {
     1829                if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1830                    count << PAGE_WIDTH)) {
     1831                        if (page + (count << PAGE_WIDTH) ==
     1832                            left_pg + (left_cnt << PAGE_WIDTH)) {
    18731833                                /*
    18741834                                 * The interval is contained in the rightmost
     
    18761836                                 * removed by updating the size of the bigger
    18771837                                 * interval.
    1878                                  *
    18791838                                 */
    18801839                                node->value[node->keys - 1] -= count;
    1881                                 return 1;
    1882                         } else if (page + count * PAGE_SIZE <
    1883                             left_pg + left_cnt*PAGE_SIZE) {
     1840                                goto success;
     1841                        } else if (page + (count << PAGE_WIDTH) <
     1842                            left_pg + (left_cnt << PAGE_WIDTH)) {
    18841843                                /*
    18851844                                 * The interval is contained in the rightmost
     
    18881847                                 * the original interval and also inserting a
    18891848                                 * new interval.
    1890                                  *
    18911849                                 */
    1892                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1893                                     (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
     1850                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1851                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    18941852                                node->value[node->keys - 1] -= count + new_cnt;
    18951853                                btree_insert(&area->used_space, page +
    1896                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
    1897                                 return 1;
     1854                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1855                                goto success;
    18981856                        }
    18991857                }
    1900                 return 0;
     1858               
     1859                return false;
    19011860        } else if (page < leaf->key[0])
    1902                 return 0;
     1861                return false;
    19031862       
    19041863        if (page > leaf->key[leaf->keys - 1]) {
     
    19061865                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    19071866               
    1908                 if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1909                     count * PAGE_SIZE)) {
    1910                         if (page + count * PAGE_SIZE ==
    1911                             left_pg + left_cnt * PAGE_SIZE) {
     1867                if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1868                    count << PAGE_WIDTH)) {
     1869                        if (page + (count << PAGE_WIDTH) ==
     1870                            left_pg + (left_cnt << PAGE_WIDTH)) {
    19121871                                /*
    19131872                                 * The interval is contained in the rightmost
    19141873                                 * interval of the leaf and can be removed by
    19151874                                 * updating the size of the bigger interval.
    1916                                  *
    19171875                                 */
    19181876                                leaf->value[leaf->keys - 1] -= count;
    1919                                 return 1;
    1920                         } else if (page + count * PAGE_SIZE < left_pg +
    1921                             left_cnt * PAGE_SIZE) {
     1877                                goto success;
     1878                        } else if (page + (count << PAGE_WIDTH) < left_pg +
     1879                            (left_cnt << PAGE_WIDTH)) {
    19221880                                /*
    19231881                                 * The interval is contained in the rightmost
     
    19261884                                 * original interval and also inserting a new
    19271885                                 * interval.
    1928                                  *
    19291886                                 */
    1930                                 size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
    1931                                     (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
     1887                                size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
     1888                                    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
    19321889                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    19331890                                btree_insert(&area->used_space, page +
    1934                                     count * PAGE_SIZE, (void *) new_cnt, leaf);
    1935                                 return 1;
     1891                                    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
     1892                                goto success;
    19361893                        }
    19371894                }
    1938                 return 0;
     1895               
     1896                return false;
    19391897        }
    19401898       
    19411899        /*
    19421900         * The border cases have been already resolved.
    1943          * Now the interval can be only between intervals of the leaf. 
     1901         * Now the interval can be only between intervals of the leaf.
    19441902         */
    19451903        btree_key_t i;
     
    19531911                         * to (i - 1) and i.
    19541912                         */
    1955                         if (overlaps(left_pg, left_cnt * PAGE_SIZE, page,
    1956                             count * PAGE_SIZE)) {
    1957                                 if (page + count * PAGE_SIZE ==
    1958                                     left_pg + left_cnt*PAGE_SIZE) {
     1913                        if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
     1914                            count << PAGE_WIDTH)) {
     1915                                if (page + (count << PAGE_WIDTH) ==
     1916                                    left_pg + (left_cnt << PAGE_WIDTH)) {
    19591917                                        /*
    19601918                                         * The interval is contained in the
     
    19621920                                         * be removed by updating the size of
    19631921                                         * the bigger interval.
    1964                                          *
    19651922                                         */
    19661923                                        leaf->value[i - 1] -= count;
    1967                                         return 1;
    1968                                 } else if (page + count * PAGE_SIZE <
    1969                                     left_pg + left_cnt * PAGE_SIZE) {
     1924                                        goto success;
     1925                                } else if (page + (count << PAGE_WIDTH) <
     1926                                    left_pg + (left_cnt << PAGE_WIDTH)) {
    19701927                                        /*
    19711928                                         * The interval is contained in the
     
    19761933                                         */
    19771934                                        size_t new_cnt = ((left_pg +
    1978                                             left_cnt * PAGE_SIZE) -
    1979                                             (page + count * PAGE_SIZE)) >>
     1935                                            (left_cnt << PAGE_WIDTH)) -
     1936                                            (page + (count << PAGE_WIDTH))) >>
    19801937                                            PAGE_WIDTH;
    19811938                                        leaf->value[i - 1] -= count + new_cnt;
    19821939                                        btree_insert(&area->used_space, page +
    1983                                             count * PAGE_SIZE, (void *) new_cnt,
     1940                                            (count << PAGE_WIDTH), (void *) new_cnt,
    19841941                                            leaf);
    1985                                         return 1;
     1942                                        goto success;
    19861943                                }
    19871944                        }
    1988                         return 0;
     1945                       
     1946                        return false;
    19891947                }
    19901948        }
    19911949       
    19921950error:
    1993         panic("Inconsistency detected while removing %" PRIs " pages of used "
    1994             "space from %p.", count, page);
     1951        panic("Inconsistency detected while removing %zu pages of used "
     1952            "space from %p.", count, (void *) page);
     1953       
     1954success:
     1955        area->resident -= count;
     1956        return true;
    19951957}
    19961958
     
    20001962
    20011963/** Wrapper for as_area_create(). */
    2002 unative_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
    2003 {
    2004         if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
     1964sysarg_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
     1965{
     1966        if (as_area_create(AS, flags, size, address,
    20051967            AS_AREA_ATTR_NONE, &anon_backend, NULL))
    2006                 return (unative_t) address;
     1968                return (sysarg_t) address;
    20071969        else
    2008                 return (unative_t) -1;
     1970                return (sysarg_t) -1;
    20091971}
    20101972
    20111973/** Wrapper for as_area_resize(). */
    2012 unative_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
    2013 {
    2014         return (unative_t) as_area_resize(AS, address, size, 0);
     1974sysarg_t sys_as_area_resize(uintptr_t address, size_t size, unsigned int flags)
     1975{
     1976        return (sysarg_t) as_area_resize(AS, address, size, 0);
    20151977}
    20161978
    20171979/** Wrapper for as_area_change_flags(). */
    2018 unative_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
    2019 {
    2020         return (unative_t) as_area_change_flags(AS, flags, address);
     1980sysarg_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
     1981{
     1982        return (sysarg_t) as_area_change_flags(AS, flags, address);
    20211983}
    20221984
    20231985/** Wrapper for as_area_destroy(). */
    2024 unative_t sys_as_area_destroy(uintptr_t address)
    2025 {
    2026         return (unative_t) as_area_destroy(AS, address);
     1986sysarg_t sys_as_area_destroy(uintptr_t address)
     1987{
     1988        return (sysarg_t) as_area_destroy(AS, address);
     1989}
     1990
     1991/** Return pointer to unmapped address space area
     1992 *
     1993 * @param base Lowest address bound.
     1994 * @param size Requested size of the allocation.
     1995 *
     1996 * @return Pointer to the beginning of unmapped address space area.
     1997 *
     1998 */
     1999sysarg_t sys_as_get_unmapped_area(uintptr_t base, size_t size)
     2000{
     2001        if (size == 0)
     2002                return 0;
     2003       
     2004        /*
     2005         * Make sure we allocate from page-aligned
     2006         * address. Check for possible overflow in
     2007         * each step.
     2008         */
     2009       
     2010        size_t pages = SIZE2FRAMES(size);
     2011        uintptr_t ret = 0;
     2012       
     2013        /*
     2014         * Find the lowest unmapped address aligned on the sz
     2015         * boundary, not smaller than base and of the required size.
     2016         */
     2017       
     2018        mutex_lock(&AS->lock);
     2019       
     2020        /* First check the base address itself */
     2021        uintptr_t addr = ALIGN_UP(base, PAGE_SIZE);
     2022        if ((addr >= base) &&
     2023            (check_area_conflicts(AS, addr, pages, NULL)))
     2024                ret = addr;
     2025       
     2026        /* Eventually check the addresses behind each area */
     2027        link_t *cur;
     2028        for (cur = AS->as_area_btree.leaf_head.next;
     2029            (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
     2030            cur = cur->next) {
     2031                btree_node_t *node =
     2032                    list_get_instance(cur, btree_node_t, leaf_link);
     2033               
     2034                btree_key_t i;
     2035                for (i = 0; (ret == 0) && (i < node->keys); i++) {
     2036                        as_area_t *area = (as_area_t *) node->value[i];
     2037                       
     2038                        mutex_lock(&area->lock);
     2039                       
     2040                        uintptr_t addr =
     2041                            ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
     2042                            PAGE_SIZE);
     2043                       
     2044                        if ((addr >= base) && (addr >= area->base) &&
     2045                            (check_area_conflicts(AS, addr, pages, area)))
     2046                                ret = addr;
     2047                       
     2048                        mutex_unlock(&area->lock);
     2049                }
     2050        }
     2051       
     2052        mutex_unlock(&AS->lock);
     2053       
     2054        return (sysarg_t) ret;
    20272055}
    20282056
     
    20932121        mutex_lock(&as->lock);
    20942122       
    2095         /* print out info about address space areas */
     2123        /* Print out info about address space areas */
    20962124        link_t *cur;
    20972125        for (cur = as->as_area_btree.leaf_head.next;
     
    21052133                       
    21062134                        mutex_lock(&area->lock);
    2107                         printf("as_area: %p, base=%p, pages=%" PRIs
    2108                             " (%p - %p)\n", area, area->base, area->pages,
    2109                             area->base, area->base + FRAMES2SIZE(area->pages));
     2135                        printf("as_area: %p, base=%p, pages=%zu"
     2136                            " (%p - %p)\n", area, (void *) area->base,
     2137                            area->pages, (void *) area->base,
     2138                            (void *) (area->base + FRAMES2SIZE(area->pages)));
    21102139                        mutex_unlock(&area->lock);
    21112140                }
Note: See TracChangeset for help on using the changeset viewer.