Ignore:
File:
1 edited

Legend:

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

    re394b736 r97bdb4a  
    7171#include <memstr.h>
    7272#include <macros.h>
    73 #include <bitops.h>
    7473#include <arch.h>
    7574#include <errno.h>
     
    8079#include <arch/interrupt.h>
    8180
     81#ifdef CONFIG_VIRT_IDX_DCACHE
     82#include <arch/mm/cache.h>
     83#endif /* CONFIG_VIRT_IDX_DCACHE */
     84
    8285/**
    8386 * Each architecture decides what functions will be used to carry out
    8487 * address space operations such as creating or locking page tables.
     88 *
    8589 */
    8690as_operations_t *as_operations = NULL;
    8791
    88 /** Slab for as_t objects.
     92/**
     93 * Slab for as_t objects.
    8994 *
    9095 */
    9196static slab_cache_t *as_slab;
    9297
    93 /** ASID subsystem lock.
    94  *
    95  * This lock protects:
     98/**
     99 * This lock serializes access to the ASID subsystem.
     100 * It protects:
    96101 * - inactive_as_with_asid_head list
    97102 * - as->asid for each as of the as_t type
     
    102107
    103108/**
    104  * Inactive address spaces (on all processors)
    105  * that have valid ASID.
     109 * This list contains address spaces that are not active on any
     110 * processor and that have valid ASID.
     111 *
    106112 */
    107113LIST_INITIALIZE(inactive_as_with_asid_head);
     
    117123        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    118124       
    119         return as_constructor_arch(as, flags);
     125        int rc = as_constructor_arch(as, flags);
     126       
     127        return rc;
    120128}
    121129
    122130NO_TRACE static size_t as_destructor(void *obj)
    123131{
    124         return as_destructor_arch((as_t *) obj);
     132        as_t *as = (as_t *) obj;
     133        return as_destructor_arch(as);
    125134}
    126135
     
    137146                panic("Cannot create kernel address space.");
    138147       
    139         /*
    140          * Make sure the kernel address space
     148        /* Make sure the kernel address space
    141149         * reference count never drops to zero.
    142150         */
     
    187195{
    188196        DEADLOCK_PROBE_INIT(p_asidlock);
    189        
     197
    190198        ASSERT(as != AS);
    191199        ASSERT(atomic_get(&as->refcount) == 0);
     
    195203         * lock its mutex.
    196204         */
    197        
     205
    198206        /*
    199207         * We need to avoid deadlock between TLB shootdown and asidlock.
     
    202210         * disabled to prevent nested context switches. We also depend on the
    203211         * fact that so far no spinlocks are held.
     212         *
    204213         */
    205214        preemption_disable();
     
    226235        spinlock_unlock(&asidlock);
    227236        interrupts_restore(ipl);
    228        
     237
    229238       
    230239        /*
     
    232241         * The B+tree must be walked carefully because it is
    233242         * also being destroyed.
     243         *
    234244         */
    235245        bool cond = true;
     
    258268/** Hold a reference to an address space.
    259269 *
    260  * Holding a reference to an address space prevents destruction
    261  * of that address space.
     270 * Holding a reference to an address space prevents destruction of that address
     271 * space.
    262272 *
    263273 * @param as Address space to be held.
     
    271281/** Release a reference to an address space.
    272282 *
    273  * The last one to release a reference to an address space
    274  * destroys the address space.
     283 * The last one to release a reference to an address space destroys the address
     284 * space.
    275285 *
    276286 * @param asAddress space to be released.
     
    285295/** Check area conflicts with other areas.
    286296 *
    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.
     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.
    291301 *
    292302 * @return True if there is no conflict, false otherwise.
    293303 *
    294304 */
    295 NO_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);
     305NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
     306    as_area_t *avoid_area)
     307{
    299308        ASSERT(mutex_locked(&as->lock));
    300309       
    301310        /*
    302311         * We don't want any area to have conflicts with NULL page.
    303          */
    304         if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
     312         *
     313         */
     314        if (overlaps(va, size, NULL, PAGE_SIZE))
    305315                return false;
    306316       
     
    311321         * record in the left neighbour, the leftmost record in the right
    312322         * neighbour and all records in the leaf node itself.
     323         *
    313324         */
    314325        btree_node_t *leaf;
    315326        as_area_t *area =
    316             (as_area_t *) btree_search(&as->as_area_btree, addr, &leaf);
     327            (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
    317328        if (area) {
    318                 if (area != avoid)
     329                if (area != avoid_area)
    319330                        return false;
    320331        }
     
    326337                area = (as_area_t *) node->value[node->keys - 1];
    327338               
    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                        
     339                mutex_lock(&area->lock);
     340               
     341                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    337342                        mutex_unlock(&area->lock);
     343                        return false;
    338344                }
     345               
     346                mutex_unlock(&area->lock);
    339347        }
    340348       
     
    343351                area = (as_area_t *) node->value[0];
    344352               
    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                        
     353                mutex_lock(&area->lock);
     354               
     355                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    354356                        mutex_unlock(&area->lock);
     357                        return false;
    355358                }
     359               
     360                mutex_unlock(&area->lock);
    356361        }
    357362       
     
    361366                area = (as_area_t *) leaf->value[i];
    362367               
    363                 if (area == avoid)
     368                if (area == avoid_area)
    364369                        continue;
    365370               
    366371                mutex_lock(&area->lock);
    367372               
    368                 if (overlaps(addr, count << PAGE_WIDTH,
    369                     area->base, area->pages << PAGE_WIDTH)) {
     373                if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {
    370374                        mutex_unlock(&area->lock);
    371375                        return false;
     
    378382         * So far, the area does not conflict with other areas.
    379383         * Check if it doesn't conflict with kernel address space.
     384         *
    380385         */
    381386        if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
    382                 return !overlaps(addr, count << PAGE_WIDTH,
     387                return !overlaps(va, size,
    383388                    KERNEL_ADDRESS_SPACE_START,
    384389                    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
     
    407412    mem_backend_data_t *backend_data)
    408413{
    409         if ((base % PAGE_SIZE) != 0)
     414        if (base % PAGE_SIZE)
    410415                return NULL;
    411416       
    412         if (size == 0)
     417        if (!size)
    413418                return NULL;
    414        
    415         size_t pages = SIZE2FRAMES(size);
    416419       
    417420        /* Writeable executable areas are not supported. */
     
    421424        mutex_lock(&as->lock);
    422425       
    423         if (!check_area_conflicts(as, base, pages, NULL)) {
     426        if (!check_area_conflicts(as, base, size, NULL)) {
    424427                mutex_unlock(&as->lock);
    425428                return NULL;
     
    433436        area->flags = flags;
    434437        area->attributes = attrs;
    435         area->pages = pages;
    436         area->resident = 0;
     438        area->pages = SIZE2FRAMES(size);
    437439        area->base = base;
    438440        area->sh_info = NULL;
     
    443445        else
    444446                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         }
    453447       
    454448        btree_create(&area->used_space);
     
    485479         * to find out whether this is a miss or va belongs to an address
    486480         * space area found there.
     481         *
    487482         */
    488483       
     
    495490                mutex_lock(&area->lock);
    496491               
    497                 if ((area->base <= va) &&
    498                     (va < area->base + (area->pages << PAGE_WIDTH)))
     492                if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))
    499493                        return area;
    500494               
     
    505499         * Second, locate the left neighbour and test its last record.
    506500         * Because of its position in the B+tree, it must have base < va.
     501         *
    507502         */
    508503        btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
     
    512507                mutex_lock(&area->lock);
    513508               
    514                 if (va < area->base + (area->pages << PAGE_WIDTH))
     509                if (va < area->base + area->pages * PAGE_SIZE)
    515510                        return area;
    516511               
     
    539534        /*
    540535         * Locate the area.
     536         *
    541537         */
    542538        as_area_t *area = find_area_and_lock(as, address);
     
    550546                 * Remapping of address space areas associated
    551547                 * with memory mapped devices is not supported.
     548                 *
    552549                 */
    553550                mutex_unlock(&area->lock);
     
    560557                 * Remapping of shared address space areas
    561558                 * is not supported.
     559                 *
    562560                 */
    563561                mutex_unlock(&area->lock);
     
    570568                /*
    571569                 * Zero size address space areas are not allowed.
     570                 *
    572571                 */
    573572                mutex_unlock(&area->lock);
     
    577576       
    578577        if (pages < area->pages) {
    579                 uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
     578                uintptr_t start_free = area->base + pages * PAGE_SIZE;
    580579               
    581580                /*
    582581                 * Shrinking the area.
    583582                 * No need to check for overlaps.
     583                 *
    584584                 */
    585585               
     
    588588                /*
    589589                 * Start TLB shootdown sequence.
     590                 *
    590591                 */
    591592                ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
    592                     area->base + (pages << PAGE_WIDTH), area->pages - pages);
     593                    area->base + pages * PAGE_SIZE, area->pages - pages);
    593594               
    594595                /*
     
    598599                 * is also the right way to remove part of the used_space
    599600                 * B+tree leaf list.
     601                 *
    600602                 */
    601603                bool cond = true;
     
    613615                                size_t i = 0;
    614616                               
    615                                 if (overlaps(ptr, size << PAGE_WIDTH, area->base,
    616                                     pages << PAGE_WIDTH)) {
     617                                if (overlaps(ptr, size * PAGE_SIZE, area->base,
     618                                    pages * PAGE_SIZE)) {
    617619                                       
    618                                         if (ptr + (size << PAGE_WIDTH) <= start_free) {
     620                                        if (ptr + size * PAGE_SIZE <= start_free) {
    619621                                                /*
    620622                                                 * The whole interval fits
    621623                                                 * completely in the resized
    622624                                                 * address space area.
     625                                                 *
    623626                                                 */
    624627                                                break;
     
    629632                                         * to b and c overlaps with the resized
    630633                                         * address space area.
     634                                         *
    631635                                         */
    632636                                       
     
    648652                                for (; i < size; i++) {
    649653                                        pte_t *pte = page_mapping_find(as, ptr +
    650                                             (i << PAGE_WIDTH));
     654                                            i * PAGE_SIZE);
    651655                                       
    652656                                        ASSERT(pte);
     
    657661                                            (area->backend->frame_free)) {
    658662                                                area->backend->frame_free(area,
    659                                                     ptr + (i << PAGE_WIDTH),
     663                                                    ptr + i * PAGE_SIZE,
    660664                                                    PTE_GET_FRAME(pte));
    661665                                        }
    662666                                       
    663667                                        page_mapping_remove(as, ptr +
    664                                             (i << PAGE_WIDTH));
     668                                            i * PAGE_SIZE);
    665669                                }
    666670                        }
     
    669673                /*
    670674                 * Finish TLB shootdown sequence.
    671                  */
    672                
    673                 tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
     675                 *
     676                 */
     677               
     678                tlb_invalidate_pages(as->asid, area->base + pages * PAGE_SIZE,
    674679                    area->pages - pages);
    675680               
    676681                /*
    677682                 * Invalidate software translation caches (e.g. TSB on sparc64).
     683                 *
    678684                 */
    679685                as_invalidate_translation_cache(as, area->base +
    680                     (pages << PAGE_WIDTH), area->pages - pages);
     686                    pages * PAGE_SIZE, area->pages - pages);
    681687                tlb_shootdown_finalize(ipl);
    682688               
     
    686692                 * Growing the area.
    687693                 * Check for overlaps with other address space areas.
    688                  */
    689                 if (!check_area_conflicts(as, address, pages, area)) {
     694                 *
     695                 */
     696                if (!check_area_conflicts(as, address, pages * PAGE_SIZE,
     697                    area)) {
    690698                        mutex_unlock(&area->lock);
    691699                        mutex_unlock(&as->lock);
    692700                        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);
    773770       
    774771        uintptr_t base = area->base;
     
    797794                       
    798795                        for (size = 0; size < (size_t) node->value[i]; size++) {
    799                                 pte_t *pte =
    800                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     796                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    801797                               
    802798                                ASSERT(pte);
     
    807803                                    (area->backend->frame_free)) {
    808804                                        area->backend->frame_free(area,
    809                                             ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
     805                                            ptr + size * PAGE_SIZE, PTE_GET_FRAME(pte));
    810806                                }
    811807                               
    812                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     808                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    813809                        }
    814810                }
     
    817813        /*
    818814         * Finish TLB shootdown sequence.
     815         *
    819816         */
    820817       
     
    824821         * Invalidate potential software translation caches (e.g. TSB on
    825822         * sparc64).
     823         *
    826824         */
    827825        as_invalidate_translation_cache(as, area->base, area->pages);
     
    841839        /*
    842840         * Remove the empty area from address space.
     841         *
    843842         */
    844843        btree_remove(&as->as_area_btree, base, NULL);
     
    882881                /*
    883882                 * 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                 *
    893894                 */
    894895                mutex_unlock(&src_area->lock);
     
    897898        }
    898899       
    899         size_t src_size = src_area->pages << PAGE_WIDTH;
     900        size_t src_size = src_area->pages * PAGE_SIZE;
    900901        unsigned int src_flags = src_area->flags;
    901902        mem_backend_t *src_backend = src_area->backend;
     
    917918         * First, prepare the area for sharing.
    918919         * Then it will be safe to unlock it.
     920         *
    919921         */
    920922        share_info_t *sh_info = src_area->sh_info;
     
    928930                /*
    929931                 * Call the backend to setup sharing.
     932                 *
    930933                 */
    931934                src_area->backend->share(src_area);
     
    946949         * The flags of the source area are masked against dst_flags_mask
    947950         * to support sharing in less privileged mode.
     951         *
    948952         */
    949953        as_area_t *dst_area = as_area_create(dst_as, dst_flags_mask, src_size,
     
    962966         * fully initialized. Clear the AS_AREA_ATTR_PARTIAL
    963967         * attribute and set the sh_info.
     968         *
    964969         */
    965970        mutex_lock(&dst_as->lock);
     
    984989NO_TRACE bool as_area_check_access(as_area_t *area, pf_access_t access)
    985990{
    986         ASSERT(mutex_locked(&area->lock));
    987        
    988991        int flagmap[] = {
    989992                [PF_ACCESS_READ] = AS_AREA_READ,
     
    991994                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    992995        };
     996
     997        ASSERT(mutex_locked(&area->lock));
    993998       
    994999        if (!(area->flags & flagmap[access]))
     
    10611066        /*
    10621067         * Compute total number of used pages in the used_space B+tree
     1068         *
    10631069         */
    10641070        size_t used_pages = 0;
     
    10821088        /*
    10831089         * Start TLB shootdown sequence.
     1090         *
    10841091         */
    10851092        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
     
    10891096         * Remove used pages from page tables and remember their frame
    10901097         * numbers.
     1098         *
    10911099         */
    10921100        size_t frame_idx = 0;
     
    11031111                       
    11041112                        for (size = 0; size < (size_t) node->value[i]; size++) {
    1105                                 pte_t *pte =
    1106                                     page_mapping_find(as, ptr + (size << PAGE_WIDTH));
     1113                                pte_t *pte = page_mapping_find(as, ptr + size * PAGE_SIZE);
    11071114                               
    11081115                                ASSERT(pte);
     
    11131120                               
    11141121                                /* Remove old mapping */
    1115                                 page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
     1122                                page_mapping_remove(as, ptr + size * PAGE_SIZE);
    11161123                        }
    11171124                }
     
    11201127        /*
    11211128         * Finish TLB shootdown sequence.
     1129         *
    11221130         */
    11231131       
     
    11271135         * Invalidate potential software translation caches (e.g. TSB on
    11281136         * sparc64).
     1137         *
    11291138         */
    11301139        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11591168                               
    11601169                                /* Insert the new mapping */
    1161                                 page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
     1170                                page_mapping_insert(as, ptr + size * PAGE_SIZE,
    11621171                                    old_frame[frame_idx++], page_flags);
    11631172                               
     
    12081217                 * No area contained mapping for 'page'.
    12091218                 * Signal page fault to low-level handler.
     1219                 *
    12101220                 */
    12111221                mutex_unlock(&AS->lock);
     
    12271237                 * The address space area is not backed by any backend
    12281238                 * or the backend cannot handle page faults.
     1239                 *
    12291240                 */
    12301241                mutex_unlock(&area->lock);
     
    12381249         * To avoid race condition between two page faults on the same address,
    12391250         * we need to make sure the mapping has not been already inserted.
     1251         *
    12401252         */
    12411253        pte_t *pte;
     
    12551267        /*
    12561268         * Resort to the backend page fault handler.
     1269         *
    12571270         */
    12581271        if (area->backend->page_fault(area, page, access) != AS_PF_OK) {
     
    13091322                 * preemption is disabled. We should not be
    13101323                 * holding any other lock.
     1324                 *
    13111325                 */
    13121326                (void) interrupts_enable();
     
    13281342                         * list of inactive address spaces with assigned
    13291343                         * ASID.
     1344                         *
    13301345                         */
    13311346                        ASSERT(old_as->asid != ASID_INVALID);
     
    13381353                 * Perform architecture-specific tasks when the address space
    13391354                 * is being removed from the CPU.
     1355                 *
    13401356                 */
    13411357                as_deinstall_arch(old_as);
     
    13441360        /*
    13451361         * Second, prepare the new address space.
     1362         *
    13461363         */
    13471364        if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
     
    13591376         * Perform architecture-specific steps.
    13601377         * (e.g. write ASID to hardware register etc.)
     1378         *
    13611379         */
    13621380        as_install_arch(new_as);
     
    13771395{
    13781396        ASSERT(mutex_locked(&area->lock));
    1379        
     1397
    13801398        return area_flags_to_page_flags(area->flags);
    13811399}
     
    14811499       
    14821500        if (src_area) {
    1483                 size = src_area->pages << PAGE_WIDTH;
     1501                size = src_area->pages * PAGE_SIZE;
    14841502                mutex_unlock(&src_area->lock);
    14851503        } else
     
    14981516 * @param count Number of page to be marked.
    14991517 *
    1500  * @return False on failure or true on success.
    1501  *
    1502  */
    1503 bool used_space_insert(as_area_t *area, uintptr_t page, size_t count)
     1518 * @return Zero on failure and non-zero on success.
     1519 *
     1520 */
     1521int used_space_insert(as_area_t *area, uintptr_t page, size_t count)
    15041522{
    15051523        ASSERT(mutex_locked(&area->lock));
     
    15121530                /*
    15131531                 * We hit the beginning of some used space.
    1514                  */
    1515                 return false;
     1532                 *
     1533                 */
     1534                return 0;
    15161535        }
    15171536       
    15181537        if (!leaf->keys) {
    15191538                btree_insert(&area->used_space, page, (void *) count, leaf);
    1520                 goto success;
     1539                return 1;
    15211540        }
    15221541       
     
    15321551                 * somewhere between the rightmost interval of
    15331552                 * the left neigbour and the first interval of the leaf.
     1553                 *
    15341554                 */
    15351555               
    15361556                if (page >= right_pg) {
    15371557                        /* Do nothing. */
    1538                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1539                     left_cnt << PAGE_WIDTH)) {
     1558                } else if (overlaps(page, count * PAGE_SIZE, left_pg,
     1559                    left_cnt * PAGE_SIZE)) {
    15401560                        /* The interval intersects with the left interval. */
    1541                         return false;
    1542                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1543                     right_cnt << PAGE_WIDTH)) {
     1561                        return 0;
     1562                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1563                    right_cnt * PAGE_SIZE)) {
    15441564                        /* The interval intersects with the right interval. */
    1545                         return false;
    1546                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1547                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1565                        return 0;
     1566                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1567                    (page + count * PAGE_SIZE == right_pg)) {
    15481568                        /*
    15491569                         * The interval can be added by merging the two already
    15501570                         * present intervals.
     1571                         *
    15511572                         */
    15521573                        node->value[node->keys - 1] += count + right_cnt;
    15531574                        btree_remove(&area->used_space, right_pg, leaf);
    1554                         goto success;
    1555                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1575                        return 1;
     1576                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    15561577                        /*
    15571578                         * The interval can be added by simply growing the left
    15581579                         * interval.
     1580                         *
    15591581                         */
    15601582                        node->value[node->keys - 1] += count;
    1561                         goto success;
    1562                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1583                        return 1;
     1584                } else if (page + count * PAGE_SIZE == right_pg) {
    15631585                        /*
    15641586                         * The interval can be addded by simply moving base of
    15651587                         * the right interval down and increasing its size
    15661588                         * accordingly.
     1589                         *
    15671590                         */
    15681591                        leaf->value[0] += count;
    15691592                        leaf->key[0] = page;
    1570                         goto success;
     1593                        return 1;
    15711594                } else {
    15721595                        /*
    15731596                         * The interval is between both neigbouring intervals,
    15741597                         * but cannot be merged with any of them.
     1598                         *
    15751599                         */
    15761600                        btree_insert(&area->used_space, page, (void *) count,
    15771601                            leaf);
    1578                         goto success;
     1602                        return 1;
    15791603                }
    15801604        } else if (page < leaf->key[0]) {
     
    15851609                 * Investigate the border case in which the left neighbour does
    15861610                 * not exist but the interval fits from the left.
    1587                  */
    1588                
    1589                 if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1590                     right_cnt << PAGE_WIDTH)) {
     1611                 *
     1612                 */
     1613               
     1614                if (overlaps(page, count * PAGE_SIZE, right_pg,
     1615                    right_cnt * PAGE_SIZE)) {
    15911616                        /* The interval intersects with the right interval. */
    1592                         return false;
    1593                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1617                        return 0;
     1618                } else if (page + count * PAGE_SIZE == right_pg) {
    15941619                        /*
    15951620                         * The interval can be added by moving the base of the
    15961621                         * right interval down and increasing its size
    15971622                         * accordingly.
     1623                         *
    15981624                         */
    15991625                        leaf->key[0] = page;
    16001626                        leaf->value[0] += count;
    1601                         goto success;
     1627                        return 1;
    16021628                } else {
    16031629                        /*
    16041630                         * The interval doesn't adjoin with the right interval.
    16051631                         * It must be added individually.
     1632                         *
    16061633                         */
    16071634                        btree_insert(&area->used_space, page, (void *) count,
    16081635                            leaf);
    1609                         goto success;
     1636                        return 1;
    16101637                }
    16111638        }
     
    16221649                 * somewhere between the leftmost interval of
    16231650                 * the right neigbour and the last interval of the leaf.
     1651                 *
    16241652                 */
    16251653               
    16261654                if (page < left_pg) {
    16271655                        /* Do nothing. */
    1628                 } else if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1629                     left_cnt << PAGE_WIDTH)) {
     1656                } else if (overlaps(page, count * PAGE_SIZE, left_pg,
     1657                    left_cnt * PAGE_SIZE)) {
    16301658                        /* The interval intersects with the left interval. */
    1631                         return false;
    1632                 } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1633                     right_cnt << PAGE_WIDTH)) {
     1659                        return 0;
     1660                } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1661                    right_cnt * PAGE_SIZE)) {
    16341662                        /* The interval intersects with the right interval. */
    1635                         return false;
    1636                 } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1637                     (page + (count << PAGE_WIDTH) == right_pg)) {
     1663                        return 0;
     1664                } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1665                    (page + count * PAGE_SIZE == right_pg)) {
    16381666                        /*
    16391667                         * The interval can be added by merging the two already
    16401668                         * present intervals.
     1669                         *
    16411670                         */
    16421671                        leaf->value[leaf->keys - 1] += count + right_cnt;
    16431672                        btree_remove(&area->used_space, right_pg, node);
    1644                         goto success;
    1645                 } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1673                        return 1;
     1674                } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    16461675                        /*
    16471676                         * The interval can be added by simply growing the left
    16481677                         * interval.
     1678                         *
    16491679                         */
    1650                         leaf->value[leaf->keys - 1] += count;
    1651                         goto success;
    1652                 } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1680                        leaf->value[leaf->keys - 1] +=  count;
     1681                        return 1;
     1682                } else if (page + count * PAGE_SIZE == right_pg) {
    16531683                        /*
    16541684                         * The interval can be addded by simply moving base of
    16551685                         * the right interval down and increasing its size
    16561686                         * accordingly.
     1687                         *
    16571688                         */
    16581689                        node->value[0] += count;
    16591690                        node->key[0] = page;
    1660                         goto success;
     1691                        return 1;
    16611692                } else {
    16621693                        /*
    16631694                         * The interval is between both neigbouring intervals,
    16641695                         * but cannot be merged with any of them.
     1696                         *
    16651697                         */
    16661698                        btree_insert(&area->used_space, page, (void *) count,
    16671699                            leaf);
    1668                         goto success;
     1700                        return 1;
    16691701                }
    16701702        } else if (page >= leaf->key[leaf->keys - 1]) {
     
    16751707                 * Investigate the border case in which the right neighbour
    16761708                 * does not exist but the interval fits from the right.
    1677                  */
    1678                
    1679                 if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1680                     left_cnt << PAGE_WIDTH)) {
     1709                 *
     1710                 */
     1711               
     1712                if (overlaps(page, count * PAGE_SIZE, left_pg,
     1713                    left_cnt * PAGE_SIZE)) {
    16811714                        /* The interval intersects with the left interval. */
    1682                         return false;
    1683                 } else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
     1715                        return 0;
     1716                } else if (left_pg + left_cnt * PAGE_SIZE == page) {
    16841717                        /*
    16851718                         * The interval can be added by growing the left
    16861719                         * interval.
     1720                         *
    16871721                         */
    16881722                        leaf->value[leaf->keys - 1] += count;
    1689                         goto success;
     1723                        return 1;
    16901724                } else {
    16911725                        /*
    16921726                         * The interval doesn't adjoin with the left interval.
    16931727                         * It must be added individually.
     1728                         *
    16941729                         */
    16951730                        btree_insert(&area->used_space, page, (void *) count,
    16961731                            leaf);
    1697                         goto success;
     1732                        return 1;
    16981733                }
    16991734        }
     
    17031738         * only between two other intervals of the leaf. The two border cases
    17041739         * were already resolved.
     1740         *
    17051741         */
    17061742        btree_key_t i;
     
    17141750                        /*
    17151751                         * The interval fits between left_pg and right_pg.
     1752                         *
    17161753                         */
    17171754                       
    1718                         if (overlaps(page, count << PAGE_WIDTH, left_pg,
    1719                             left_cnt << PAGE_WIDTH)) {
     1755                        if (overlaps(page, count * PAGE_SIZE, left_pg,
     1756                            left_cnt * PAGE_SIZE)) {
    17201757                                /*
    17211758                                 * The interval intersects with the left
    17221759                                 * interval.
     1760                                 *
    17231761                                 */
    1724                                 return false;
    1725                         } else if (overlaps(page, count << PAGE_WIDTH, right_pg,
    1726                             right_cnt << PAGE_WIDTH)) {
     1762                                return 0;
     1763                        } else if (overlaps(page, count * PAGE_SIZE, right_pg,
     1764                            right_cnt * PAGE_SIZE)) {
    17271765                                /*
    17281766                                 * The interval intersects with the right
    17291767                                 * interval.
     1768                                 *
    17301769                                 */
    1731                                 return false;
    1732                         } else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
    1733                             (page + (count << PAGE_WIDTH) == right_pg)) {
     1770                                return 0;
     1771                        } else if ((page == left_pg + left_cnt * PAGE_SIZE) &&
     1772                            (page + count * PAGE_SIZE == right_pg)) {
    17341773                                /*
    17351774                                 * The interval can be added by merging the two
    17361775                                 * already present intervals.
     1776                                 *
    17371777                                 */
    17381778                                leaf->value[i - 1] += count + right_cnt;
    17391779                                btree_remove(&area->used_space, right_pg, leaf);
    1740                                 goto success;
    1741                         } else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
     1780                                return 1;
     1781                        } else if (page == left_pg + left_cnt * PAGE_SIZE) {
    17421782                                /*
    17431783                                 * The interval can be added by simply growing
    17441784                                 * the left interval.
     1785                                 *
    17451786                                 */
    17461787                                leaf->value[i - 1] += count;
    1747                                 goto success;
    1748                         } else if (page + (count << PAGE_WIDTH) == right_pg) {
     1788                                return 1;
     1789                        } else if (page + count * PAGE_SIZE == right_pg) {
    17491790                                /*
    17501791                                 * The interval can be addded by simply moving
    17511792                                 * base of the right interval down and
    17521793                                 * increasing its size accordingly.
     1794                                 *
    17531795                                 */
    17541796                                leaf->value[i] += count;
    17551797                                leaf->key[i] = page;
    1756                                 goto success;
     1798                                return 1;
    17571799                        } else {
    17581800                                /*
     
    17601802                                 * intervals, but cannot be merged with any of
    17611803                                 * them.
     1804                                 *
    17621805                                 */
    17631806                                btree_insert(&area->used_space, page,
    17641807                                    (void *) count, leaf);
    1765                                 goto success;
     1808                                return 1;
    17661809                        }
    17671810                }
    17681811        }
    17691812       
    1770         panic("Inconsistency detected while adding %zu pages of used "
    1771             "space at %p.", count, (void *) page);
    1772        
    1773 success:
    1774         area->resident += count;
    1775         return true;
     1813        panic("Inconsistency detected while adding %" PRIs " pages of used "
     1814            "space at %p.", count, page);
    17761815}
    17771816
     
    17841823 * @param count Number of page to be marked.
    17851824 *
    1786  * @return False on failure or true on success.
    1787  *
    1788  */
    1789 bool used_space_remove(as_area_t *area, uintptr_t page, size_t count)
     1825 * @return Zero on failure and non-zero on success.
     1826 *
     1827 */
     1828int used_space_remove(as_area_t *area, uintptr_t page, size_t count)
    17901829{
    17911830        ASSERT(mutex_locked(&area->lock));
     
    17981837                /*
    17991838                 * We are lucky, page is the beginning of some interval.
     1839                 *
    18001840                 */
    18011841                if (count > pages) {
    1802                         return false;
     1842                        return 0;
    18031843                } else if (count == pages) {
    18041844                        btree_remove(&area->used_space, page, leaf);
    1805                         goto success;
     1845                        return 1;
    18061846                } else {
    18071847                        /*
    18081848                         * Find the respective interval.
    18091849                         * Decrease its size and relocate its start address.
     1850                         *
    18101851                         */
    18111852                        btree_key_t i;
    18121853                        for (i = 0; i < leaf->keys; i++) {
    18131854                                if (leaf->key[i] == page) {
    1814                                         leaf->key[i] += count << PAGE_WIDTH;
     1855                                        leaf->key[i] += count * PAGE_SIZE;
    18151856                                        leaf->value[i] -= count;
    1816                                         goto success;
     1857                                        return 1;
    18171858                                }
    18181859                        }
    1819                        
    18201860                        goto error;
    18211861                }
     
    18271867                size_t left_cnt = (size_t) node->value[node->keys - 1];
    18281868               
    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)) {
     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) {
    18331873                                /*
    18341874                                 * The interval is contained in the rightmost
     
    18361876                                 * removed by updating the size of the bigger
    18371877                                 * interval.
     1878                                 *
    18381879                                 */
    18391880                                node->value[node->keys - 1] -= count;
    1840                                 goto success;
    1841                         } else if (page + (count << PAGE_WIDTH) <
    1842                             left_pg + (left_cnt << PAGE_WIDTH)) {
     1881                                return 1;
     1882                        } else if (page + count * PAGE_SIZE <
     1883                            left_pg + left_cnt*PAGE_SIZE) {
    18431884                                /*
    18441885                                 * The interval is contained in the rightmost
     
    18471888                                 * the original interval and also inserting a
    18481889                                 * new interval.
     1890                                 *
    18491891                                 */
    1850                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1851                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1892                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1893                                    (page + count*PAGE_SIZE)) >> PAGE_WIDTH;
    18521894                                node->value[node->keys - 1] -= count + new_cnt;
    18531895                                btree_insert(&area->used_space, page +
    1854                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
    1855                                 goto success;
     1896                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
     1897                                return 1;
    18561898                        }
    18571899                }
    1858                
    1859                 return false;
     1900                return 0;
    18601901        } else if (page < leaf->key[0])
    1861                 return false;
     1902                return 0;
    18621903       
    18631904        if (page > leaf->key[leaf->keys - 1]) {
     
    18651906                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18661907               
    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)) {
     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) {
    18711912                                /*
    18721913                                 * The interval is contained in the rightmost
    18731914                                 * interval of the leaf and can be removed by
    18741915                                 * updating the size of the bigger interval.
     1916                                 *
    18751917                                 */
    18761918                                leaf->value[leaf->keys - 1] -= count;
    1877                                 goto success;
    1878                         } else if (page + (count << PAGE_WIDTH) < left_pg +
    1879                             (left_cnt << PAGE_WIDTH)) {
     1919                                return 1;
     1920                        } else if (page + count * PAGE_SIZE < left_pg +
     1921                            left_cnt * PAGE_SIZE) {
    18801922                                /*
    18811923                                 * The interval is contained in the rightmost
     
    18841926                                 * original interval and also inserting a new
    18851927                                 * interval.
     1928                                 *
    18861929                                 */
    1887                                 size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
    1888                                     (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
     1930                                size_t new_cnt = ((left_pg + left_cnt * PAGE_SIZE) -
     1931                                    (page + count * PAGE_SIZE)) >> PAGE_WIDTH;
    18891932                                leaf->value[leaf->keys - 1] -= count + new_cnt;
    18901933                                btree_insert(&area->used_space, page +
    1891                                     (count << PAGE_WIDTH), (void *) new_cnt, leaf);
    1892                                 goto success;
     1934                                    count * PAGE_SIZE, (void *) new_cnt, leaf);
     1935                                return 1;
    18931936                        }
    18941937                }
    1895                
    1896                 return false;
     1938                return 0;
    18971939        }
    18981940       
    18991941        /*
    19001942         * The border cases have been already resolved.
    1901          * Now the interval can be only between intervals of the leaf.
     1943         * Now the interval can be only between intervals of the leaf. 
    19021944         */
    19031945        btree_key_t i;
     
    19111953                         * to (i - 1) and i.
    19121954                         */
    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)) {
     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) {
    19171959                                        /*
    19181960                                         * The interval is contained in the
     
    19201962                                         * be removed by updating the size of
    19211963                                         * the bigger interval.
     1964                                         *
    19221965                                         */
    19231966                                        leaf->value[i - 1] -= count;
    1924                                         goto success;
    1925                                 } else if (page + (count << PAGE_WIDTH) <
    1926                                     left_pg + (left_cnt << PAGE_WIDTH)) {
     1967                                        return 1;
     1968                                } else if (page + count * PAGE_SIZE <
     1969                                    left_pg + left_cnt * PAGE_SIZE) {
    19271970                                        /*
    19281971                                         * The interval is contained in the
     
    19331976                                         */
    19341977                                        size_t new_cnt = ((left_pg +
    1935                                             (left_cnt << PAGE_WIDTH)) -
    1936                                             (page + (count << PAGE_WIDTH))) >>
     1978                                            left_cnt * PAGE_SIZE) -
     1979                                            (page + count * PAGE_SIZE)) >>
    19371980                                            PAGE_WIDTH;
    19381981                                        leaf->value[i - 1] -= count + new_cnt;
    19391982                                        btree_insert(&area->used_space, page +
    1940                                             (count << PAGE_WIDTH), (void *) new_cnt,
     1983                                            count * PAGE_SIZE, (void *) new_cnt,
    19411984                                            leaf);
    1942                                         goto success;
     1985                                        return 1;
    19431986                                }
    19441987                        }
    1945                        
    1946                         return false;
     1988                        return 0;
    19471989                }
    19481990        }
    19491991       
    19501992error:
    1951         panic("Inconsistency detected while removing %zu pages of used "
    1952             "space from %p.", count, (void *) page);
    1953        
    1954 success:
    1955         area->resident -= count;
    1956         return true;
     1993        panic("Inconsistency detected while removing %" PRIs " pages of used "
     1994            "space from %p.", count, page);
    19571995}
    19581996
     
    19622000
    19632001/** Wrapper for as_area_create(). */
    1964 sysarg_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
     2002unative_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
    19652003{
    19662004        if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
    19672005            AS_AREA_ATTR_NONE, &anon_backend, NULL))
    1968                 return (sysarg_t) address;
     2006                return (unative_t) address;
    19692007        else
    1970                 return (sysarg_t) -1;
     2008                return (unative_t) -1;
    19712009}
    19722010
    19732011/** Wrapper for as_area_resize(). */
    1974 sysarg_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);
     2012unative_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);
    19772015}
    19782016
    19792017/** Wrapper for as_area_change_flags(). */
    1980 sysarg_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
    1981 {
    1982         return (sysarg_t) as_area_change_flags(AS, flags, address);
     2018unative_t sys_as_area_change_flags(uintptr_t address, unsigned int flags)
     2019{
     2020        return (unative_t) as_area_change_flags(AS, flags, address);
    19832021}
    19842022
    19852023/** Wrapper for as_area_destroy(). */
    1986 sysarg_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  */
    1999 sysarg_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;
     2024unative_t sys_as_area_destroy(uintptr_t address)
     2025{
     2026        return (unative_t) as_area_destroy(AS, address);
    20552027}
    20562028
     
    21212093        mutex_lock(&as->lock);
    21222094       
    2123         /* Print out info about address space areas */
     2095        /* print out info about address space areas */
    21242096        link_t *cur;
    21252097        for (cur = as->as_area_btree.leaf_head.next;
     
    21332105                       
    21342106                        mutex_lock(&area->lock);
    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)));
     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));
    21392110                        mutex_unlock(&area->lock);
    21402111                }
Note: See TracChangeset for help on using the changeset viewer.