Ignore:
File:
1 edited

Legend:

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

    r1b20da0 ra35b458  
    114114{
    115115        as_t *as = (as_t *) obj;
    116        
     116
    117117        link_initialize(&as->inactive_as_with_asid_link);
    118118        mutex_initialize(&as->lock, MUTEX_PASSIVE);
    119        
     119
    120120        return as_constructor_arch(as, flags);
    121121}
     
    130130{
    131131        as_arch_init();
    132        
     132
    133133        as_cache = slab_cache_create("as_t", sizeof(as_t), 0,
    134134            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
    135        
     135
    136136        AS_KERNEL = as_create(FLAG_AS_KERNEL);
    137137        if (!AS_KERNEL)
    138138                panic("Cannot create kernel address space.");
    139        
     139
    140140        /*
    141141         * Make sure the kernel address space
     
    155155        as_t *as = (as_t *) slab_alloc(as_cache, 0);
    156156        (void) as_create_arch(as, 0);
    157        
     157
    158158        btree_create(&as->as_area_btree);
    159        
     159
    160160        if (flags & FLAG_AS_KERNEL)
    161161                as->asid = ASID_KERNEL;
    162162        else
    163163                as->asid = ASID_INVALID;
    164        
     164
    165165        atomic_set(&as->refcount, 0);
    166166        as->cpu_refcount = 0;
    167        
     167
    168168#ifdef AS_PAGE_TABLE
    169169        as->genarch.page_table = page_table_create(flags);
     
    171171        page_table_create(flags);
    172172#endif
    173        
     173
    174174        return as;
    175175}
     
    188188{
    189189        DEADLOCK_PROBE_INIT(p_asidlock);
    190        
     190
    191191        assert(as != AS);
    192192        assert(atomic_get(&as->refcount) == 0);
    193        
     193
    194194        /*
    195195         * Since there is no reference to this address space, it is safe not to
    196196         * lock its mutex.
    197197         */
    198        
     198
    199199        /*
    200200         * We need to avoid deadlock between TLB shootdown and asidlock.
     
    206206        preemption_disable();
    207207        ipl_t ipl = interrupts_read();
    208        
     208
    209209retry:
    210210        interrupts_disable();
     
    214214                goto retry;
    215215        }
    216        
     216
    217217        /* Interrupts disabled, enable preemption */
    218218        preemption_enable();
    219        
     219
    220220        if ((as->asid != ASID_INVALID) && (as != AS_KERNEL)) {
    221221                if (as->cpu_refcount == 0)
    222222                        list_remove(&as->inactive_as_with_asid_link);
    223                
     223
    224224                asid_put(as->asid);
    225225        }
    226        
     226
    227227        spinlock_unlock(&asidlock);
    228228        interrupts_restore(ipl);
    229        
    230        
     229
     230
    231231        /*
    232232         * Destroy address space areas of the address space.
     
    237237        while (cond) {
    238238                assert(!list_empty(&as->as_area_btree.leaf_list));
    239                
     239
    240240                btree_node_t *node =
    241241                    list_get_instance(list_first(&as->as_area_btree.leaf_list),
    242242                    btree_node_t, leaf_link);
    243                
     243
    244244                if ((cond = node->keys))
    245245                        as_area_destroy(as, node->key[0]);
    246246        }
    247        
     247
    248248        btree_destroy(&as->as_area_btree);
    249        
     249
    250250#ifdef AS_PAGE_TABLE
    251251        page_table_destroy(as->genarch.page_table);
     
    253253        page_table_destroy(NULL);
    254254#endif
    255        
     255
    256256        slab_free(as_cache, as);
    257257}
     
    307307        if (overflows_into_positive(addr, P2SZ(count)))
    308308                return false;
    309        
     309
    310310        /*
    311311         * We don't want any area to have conflicts with NULL page.
     
    328328                        return false;
    329329        }
    330        
     330
    331331        /* First, check the two border cases. */
    332332        btree_node_t *node =
     
    334334        if (node) {
    335335                area = (as_area_t *) node->value[node->keys - 1];
    336                
     336
    337337                if (area != avoid) {
    338338                        mutex_lock(&area->lock);
     
    346346                        int const gp = (guarded ||
    347347                            (area->flags & AS_AREA_GUARD)) ? 1 : 0;
    348                        
     348
    349349                        /*
    350350                         * The area comes from the left neighbour node, which
     
    358358                                return false;
    359359                        }
    360                        
     360
    361361                        mutex_unlock(&area->lock);
    362362                }
    363363        }
    364        
     364
    365365        node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
    366366        if (node) {
    367367                area = (as_area_t *) node->value[0];
    368                
     368
    369369                if (area != avoid) {
    370370                        int gp;
     
    382382                                gp--;
    383383                        }
    384                        
     384
    385385                        if (overlaps(addr, P2SZ(count + gp), area->base,
    386386                            P2SZ(area->pages))) {
     
    388388                                return false;
    389389                        }
    390                        
     390
    391391                        mutex_unlock(&area->lock);
    392392                }
    393393        }
    394        
     394
    395395        /* Second, check the leaf node. */
    396396        btree_key_t i;
     
    399399                int agp;
    400400                int gp;
    401                
     401
    402402                if (area == avoid)
    403403                        continue;
    404                
     404
    405405                mutex_lock(&area->lock);
    406406
     
    421421                        return false;
    422422                }
    423                
     423
    424424                mutex_unlock(&area->lock);
    425425        }
    426        
     426
    427427        /*
    428428         * So far, the area does not conflict with other areas.
     
    434434                    addr, P2SZ(count));
    435435        }
    436        
     436
    437437        return true;
    438438}
     
    456456{
    457457        assert(mutex_locked(&as->lock));
    458        
     458
    459459        if (size == 0)
    460460                return (uintptr_t) -1;
    461        
     461
    462462        /*
    463463         * Make sure we allocate from page-aligned
     
    465465         * each step.
    466466         */
    467        
     467
    468468        size_t pages = SIZE2FRAMES(size);
    469        
     469
    470470        /*
    471471         * Find the lowest unmapped address aligned on the size
    472472         * boundary, not smaller than bound and of the required size.
    473473         */
    474        
     474
    475475        /* First check the bound address itself */
    476476        uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
     
    486486                        return addr;
    487487        }
    488        
     488
    489489        /* Eventually check the addresses behind each area */
    490490        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t, node) {
    491                
     491
    492492                for (btree_key_t i = 0; i < node->keys; i++) {
    493493                        as_area_t *area = (as_area_t *) node->value[i];
    494                        
     494
    495495                        mutex_lock(&area->lock);
    496                        
     496
    497497                        addr =
    498498                            ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
     
    508508                            ((addr >= bound) && (addr >= area->base) &&
    509509                            (check_area_conflicts(as, addr, pages, guarded, area)));
    510                        
     510
    511511                        mutex_unlock(&area->lock);
    512                        
     512
    513513                        if (avail)
    514514                                return addr;
    515515                }
    516516        }
    517        
     517
    518518        /* No suitable address space area found */
    519519        return (uintptr_t) -1;
     
    530530{
    531531        bool dealloc = false;
    532        
     532
    533533        mutex_lock(&sh_info->lock);
    534534        assert(sh_info->refcount);
    535        
     535
    536536        if (--sh_info->refcount == 0) {
    537537                dealloc = true;
    538                
     538
    539539                /*
    540540                 * Now walk carefully the pagemap B+tree and free/remove
     
    544544                    btree_node_t, node) {
    545545                        btree_key_t i;
    546                        
     546
    547547                        for (i = 0; i < node->keys; i++)
    548548                                frame_free((uintptr_t) node->value[i], 1);
    549549                }
    550                
     550
    551551        }
    552552        mutex_unlock(&sh_info->lock);
    553        
     553
    554554        if (dealloc) {
    555555                if (sh_info->backend && sh_info->backend->destroy_shared_data) {
     
    588588        if ((*base != (uintptr_t) AS_AREA_ANY) && !IS_ALIGNED(*base, PAGE_SIZE))
    589589                return NULL;
    590        
     590
    591591        if (size == 0)
    592592                return NULL;
    593593
    594594        size_t pages = SIZE2FRAMES(size);
    595        
     595
    596596        /* Writeable executable areas are not supported. */
    597597        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
     
    599599
    600600        bool const guarded = flags & AS_AREA_GUARD;
    601        
     601
    602602        mutex_lock(&as->lock);
    603        
     603
    604604        if (*base == (uintptr_t) AS_AREA_ANY) {
    605605                *base = as_get_unmapped_area(as, bound, size, guarded);
     
    619619                return NULL;
    620620        }
    621        
     621
    622622        as_area_t *area = (as_area_t *) malloc(sizeof(as_area_t), 0);
    623        
     623
    624624        mutex_initialize(&area->lock, MUTEX_PASSIVE);
    625        
     625
    626626        area->as = as;
    627627        area->flags = flags;
     
    632632        area->backend = backend;
    633633        area->sh_info = NULL;
    634        
     634
    635635        if (backend_data)
    636636                area->backend_data = *backend_data;
     
    655655
    656656                area->sh_info = si;
    657        
     657
    658658                if (area->backend && area->backend->create_shared_data) {
    659659                        if (!area->backend->create_shared_data(area)) {
     
    679679        btree_insert(&as->as_area_btree, *base, (void *) area,
    680680            NULL);
    681        
     681
    682682        mutex_unlock(&as->lock);
    683        
     683
    684684        return area;
    685685}
     
    697697{
    698698        assert(mutex_locked(&as->lock));
    699        
     699
    700700        btree_node_t *leaf;
    701701        as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va,
     
    706706                return area;
    707707        }
    708        
     708
    709709        /*
    710710         * Search the leaf node and the rightmost record of its left neighbour
     
    712712         * space area found there.
    713713         */
    714        
     714
    715715        /* First, search the leaf node itself. */
    716716        btree_key_t i;
    717        
     717
    718718        for (i = 0; i < leaf->keys; i++) {
    719719                area = (as_area_t *) leaf->value[i];
    720                
     720
    721721                mutex_lock(&area->lock);
    722722
     
    724724                    (va <= area->base + (P2SZ(area->pages) - 1)))
    725725                        return area;
    726                
     726
    727727                mutex_unlock(&area->lock);
    728728        }
    729        
     729
    730730        /*
    731731         * Second, locate the left neighbour and test its last record.
     
    736736        if (lnode) {
    737737                area = (as_area_t *) lnode->value[lnode->keys - 1];
    738                
     738
    739739                mutex_lock(&area->lock);
    740                
     740
    741741                if (va <= area->base + (P2SZ(area->pages) - 1))
    742742                        return area;
    743                
     743
    744744                mutex_unlock(&area->lock);
    745745        }
    746        
     746
    747747        return NULL;
    748748}
     
    766766
    767767        mutex_lock(&as->lock);
    768        
     768
    769769        /*
    770770         * Locate the area.
     
    784784                return ENOTSUP;
    785785        }
    786        
     786
    787787        mutex_lock(&area->sh_info->lock);
    788788        if (area->sh_info->shared) {
     
    797797        }
    798798        mutex_unlock(&area->sh_info->lock);
    799        
     799
    800800        size_t pages = SIZE2FRAMES((address - area->base) + size);
    801801        if (!pages) {
     
    807807                return EPERM;
    808808        }
    809        
     809
    810810        if (pages < area->pages) {
    811811                uintptr_t start_free = area->base + P2SZ(pages);
    812                
     812
    813813                /*
    814814                 * Shrinking the area.
    815815                 * No need to check for overlaps.
    816816                 */
    817                
     817
    818818                page_table_lock(as, false);
    819                
     819
    820820                /*
    821821                 * Remove frames belonging to used space starting from
     
    828828                while (cond) {
    829829                        assert(!list_empty(&area->used_space.leaf_list));
    830                        
     830
    831831                        btree_node_t *node =
    832832                            list_get_instance(list_last(&area->used_space.leaf_list),
    833833                            btree_node_t, leaf_link);
    834                        
     834
    835835                        if ((cond = (node->keys != 0))) {
    836836                                uintptr_t ptr = node->key[node->keys - 1];
     
    838838                                    (size_t) node->value[node->keys - 1];
    839839                                size_t i = 0;
    840                                
     840
    841841                                if (overlaps(ptr, P2SZ(node_size), area->base,
    842842                                    P2SZ(pages))) {
    843                                        
     843
    844844                                        if (ptr + P2SZ(node_size) <= start_free) {
    845845                                                /*
     
    850850                                                break;
    851851                                        }
    852                                        
     852
    853853                                        /*
    854854                                         * Part of the interval corresponding
     
    856856                                         * address space area.
    857857                                         */
    858                                        
     858
    859859                                        /* We are almost done */
    860860                                        cond = false;
     
    871871                                                panic("Cannot remove used space.");
    872872                                }
    873                                
     873
    874874                                /*
    875875                                 * Start TLB shootdown sequence.
     
    887887                                    as->asid, area->base + P2SZ(pages),
    888888                                    area->pages - pages);
    889                
     889
    890890                                for (; i < node_size; i++) {
    891891                                        pte_t pte;
    892892                                        bool found = page_mapping_find(as,
    893893                                            ptr + P2SZ(i), false, &pte);
    894                                        
     894
    895895                                        assert(found);
    896896                                        assert(PTE_VALID(&pte));
    897897                                        assert(PTE_PRESENT(&pte));
    898                                        
     898
    899899                                        if ((area->backend) &&
    900900                                            (area->backend->frame_free)) {
     
    903903                                                    PTE_GET_FRAME(&pte));
    904904                                        }
    905                                        
     905
    906906                                        page_mapping_remove(as, ptr + P2SZ(i));
    907907                                }
    908                
     908
    909909                                /*
    910910                                 * Finish TLB shootdown sequence.
    911911                                 */
    912                
     912
    913913                                tlb_invalidate_pages(as->asid,
    914914                                    area->base + P2SZ(pages),
    915915                                    area->pages - pages);
    916                
     916
    917917                                /*
    918918                                 * Invalidate software translation caches
     
    944944                }
    945945        }
    946        
     946
    947947        if (area->backend && area->backend->resize) {
    948948                if (!area->backend->resize(area, pages)) {
     
    952952                }
    953953        }
    954        
     954
    955955        area->pages = pages;
    956        
     956
    957957        mutex_unlock(&area->lock);
    958958        mutex_unlock(&as->lock);
    959        
     959
    960960        return 0;
    961961}
     
    972972{
    973973        mutex_lock(&as->lock);
    974        
     974
    975975        as_area_t *area = find_area_and_lock(as, address);
    976976        if (!area) {
     
    981981        if (area->backend && area->backend->destroy)
    982982                area->backend->destroy(area);
    983        
     983
    984984        uintptr_t base = area->base;
    985        
     985
    986986        page_table_lock(as, false);
    987        
     987
    988988        /*
    989989         * Start TLB shootdown sequence.
     
    991991        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    992992            area->pages);
    993        
     993
    994994        /*
    995995         * Visit only the pages mapped by used_space B+tree.
     
    998998            node) {
    999999                btree_key_t i;
    1000                
     1000
    10011001                for (i = 0; i < node->keys; i++) {
    10021002                        uintptr_t ptr = node->key[i];
    10031003                        size_t size;
    1004                        
     1004
    10051005                        for (size = 0; size < (size_t) node->value[i]; size++) {
    10061006                                pte_t pte;
    10071007                                bool found = page_mapping_find(as,
    10081008                                     ptr + P2SZ(size), false, &pte);
    1009                                
     1009
    10101010                                assert(found);
    10111011                                assert(PTE_VALID(&pte));
    10121012                                assert(PTE_PRESENT(&pte));
    1013                                
     1013
    10141014                                if ((area->backend) &&
    10151015                                    (area->backend->frame_free)) {
     
    10181018                                            PTE_GET_FRAME(&pte));
    10191019                                }
    1020                                
     1020
    10211021                                page_mapping_remove(as, ptr + P2SZ(size));
    10221022                        }
    10231023                }
    10241024        }
    1025        
     1025
    10261026        /*
    10271027         * Finish TLB shootdown sequence.
    10281028         */
    1029        
     1029
    10301030        tlb_invalidate_pages(as->asid, area->base, area->pages);
    1031        
     1031
    10321032        /*
    10331033         * Invalidate potential software translation caches
     
    10361036        as_invalidate_translation_cache(as, area->base, area->pages);
    10371037        tlb_shootdown_finalize(ipl);
    1038        
     1038
    10391039        page_table_unlock(as, false);
    1040        
     1040
    10411041        btree_destroy(&area->used_space);
    1042        
     1042
    10431043        area->attributes |= AS_AREA_ATTR_PARTIAL;
    1044        
     1044
    10451045        sh_info_remove_reference(area->sh_info);
    1046        
     1046
    10471047        mutex_unlock(&area->lock);
    1048        
     1048
    10491049        /*
    10501050         * Remove the empty area from address space.
    10511051         */
    10521052        btree_remove(&as->as_area_btree, base, NULL);
    1053        
     1053
    10541054        free(area);
    1055        
     1055
    10561056        mutex_unlock(&as->lock);
    10571057        return 0;
     
    10981098                return ENOENT;
    10991099        }
    1100        
     1100
    11011101        if (!src_area->backend->is_shareable(src_area)) {
    11021102                /*
     
    11071107                return ENOTSUP;
    11081108        }
    1109        
     1109
    11101110        size_t src_size = P2SZ(src_area->pages);
    11111111        unsigned int src_flags = src_area->flags;
    11121112        mem_backend_t *src_backend = src_area->backend;
    11131113        mem_backend_data_t src_backend_data = src_area->backend_data;
    1114        
     1114
    11151115        /* Share the cacheable flag from the original mapping */
    11161116        if (src_flags & AS_AREA_CACHEABLE)
    11171117                dst_flags_mask |= AS_AREA_CACHEABLE;
    1118        
     1118
    11191119        if ((src_size != acc_size) ||
    11201120            ((src_flags & dst_flags_mask) != dst_flags_mask)) {
     
    11231123                return EPERM;
    11241124        }
    1125        
     1125
    11261126        /*
    11271127         * Now we are committed to sharing the area.
     
    11301130         */
    11311131        share_info_t *sh_info = src_area->sh_info;
    1132        
     1132
    11331133        mutex_lock(&sh_info->lock);
    11341134        sh_info->refcount++;
     
    11441144                src_area->backend->share(src_area);
    11451145        }
    1146        
     1146
    11471147        mutex_unlock(&src_area->lock);
    11481148        mutex_unlock(&src_as->lock);
    1149        
     1149
    11501150        /*
    11511151         * Create copy of the source address space area.
     
    11641164                 */
    11651165                sh_info_remove_reference(sh_info);
    1166                
     1166
    11671167                return ENOMEM;
    11681168        }
    1169        
     1169
    11701170        /*
    11711171         * Now the destination address space area has been
     
    11791179        mutex_unlock(&dst_area->lock);
    11801180        mutex_unlock(&dst_as->lock);
    1181        
     1181
    11821182        return 0;
    11831183}
     
    11951195{
    11961196        assert(mutex_locked(&area->lock));
    1197        
     1197
    11981198        int flagmap[] = {
    11991199                [PF_ACCESS_READ] = AS_AREA_READ,
     
    12011201                [PF_ACCESS_EXEC] = AS_AREA_EXEC
    12021202        };
    1203        
     1203
    12041204        if (!(area->flags & flagmap[access]))
    12051205                return false;
    1206        
     1206
    12071207        return true;
    12081208}
     
    12181218{
    12191219        unsigned int flags = PAGE_USER | PAGE_PRESENT;
    1220        
     1220
    12211221        if (aflags & AS_AREA_READ)
    12221222                flags |= PAGE_READ;
    1223                
     1223
    12241224        if (aflags & AS_AREA_WRITE)
    12251225                flags |= PAGE_WRITE;
    1226        
     1226
    12271227        if (aflags & AS_AREA_EXEC)
    12281228                flags |= PAGE_EXEC;
    1229        
     1229
    12301230        if (aflags & AS_AREA_CACHEABLE)
    12311231                flags |= PAGE_CACHEABLE;
    1232        
     1232
    12331233        return flags;
    12341234}
     
    12521252        /* Flags for the new memory mapping */
    12531253        unsigned int page_flags = area_flags_to_page_flags(flags);
    1254        
     1254
    12551255        mutex_lock(&as->lock);
    1256        
     1256
    12571257        as_area_t *area = find_area_and_lock(as, address);
    12581258        if (!area) {
     
    12601260                return ENOENT;
    12611261        }
    1262        
     1262
    12631263        if (area->backend != &anon_backend) {
    12641264                /* Copying non-anonymous memory not supported yet */
     
    12771277        }
    12781278        mutex_unlock(&area->sh_info->lock);
    1279        
     1279
    12801280        /*
    12811281         * Compute total number of used pages in the used_space B+tree
    12821282         */
    12831283        size_t used_pages = 0;
    1284        
     1284
    12851285        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
    12861286            node) {
    12871287                btree_key_t i;
    1288                
     1288
    12891289                for (i = 0; i < node->keys; i++)
    12901290                        used_pages += (size_t) node->value[i];
    12911291        }
    1292        
     1292
    12931293        /* An array for storing frame numbers */
    12941294        uintptr_t *old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
    1295        
     1295
    12961296        page_table_lock(as, false);
    1297        
     1297
    12981298        /*
    12991299         * Start TLB shootdown sequence.
     
    13011301        ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base,
    13021302            area->pages);
    1303        
     1303
    13041304        /*
    13051305         * Remove used pages from page tables and remember their frame
     
    13071307         */
    13081308        size_t frame_idx = 0;
    1309        
     1309
    13101310        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
    13111311            node) {
    13121312                btree_key_t i;
    1313                
     1313
    13141314                for (i = 0; i < node->keys; i++) {
    13151315                        uintptr_t ptr = node->key[i];
    13161316                        size_t size;
    1317                        
     1317
    13181318                        for (size = 0; size < (size_t) node->value[i]; size++) {
    13191319                                pte_t pte;
    13201320                                bool found = page_mapping_find(as,
    13211321                                    ptr + P2SZ(size), false, &pte);
    1322                                
     1322
    13231323                                assert(found);
    13241324                                assert(PTE_VALID(&pte));
    13251325                                assert(PTE_PRESENT(&pte));
    1326                                
     1326
    13271327                                old_frame[frame_idx++] = PTE_GET_FRAME(&pte);
    1328                                
     1328
    13291329                                /* Remove old mapping */
    13301330                                page_mapping_remove(as, ptr + P2SZ(size));
     
    13321332                }
    13331333        }
    1334        
     1334
    13351335        /*
    13361336         * Finish TLB shootdown sequence.
    13371337         */
    1338        
     1338
    13391339        tlb_invalidate_pages(as->asid, area->base, area->pages);
    1340        
     1340
    13411341        /*
    13421342         * Invalidate potential software translation caches
     
    13451345        as_invalidate_translation_cache(as, area->base, area->pages);
    13461346        tlb_shootdown_finalize(ipl);
    1347        
     1347
    13481348        page_table_unlock(as, false);
    1349        
     1349
    13501350        /*
    13511351         * Set the new flags.
    13521352         */
    13531353        area->flags = flags;
    1354        
     1354
    13551355        /*
    13561356         * Map pages back in with new flags. This step is kept separate
     
    13591359         */
    13601360        frame_idx = 0;
    1361        
     1361
    13621362        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
    13631363            node) {
    13641364                btree_key_t i;
    1365                
     1365
    13661366                for (i = 0; i < node->keys; i++) {
    13671367                        uintptr_t ptr = node->key[i];
    13681368                        size_t size;
    1369                        
     1369
    13701370                        for (size = 0; size < (size_t) node->value[i]; size++) {
    13711371                                page_table_lock(as, false);
    1372                                
     1372
    13731373                                /* Insert the new mapping */
    13741374                                page_mapping_insert(as, ptr + P2SZ(size),
    13751375                                    old_frame[frame_idx++], page_flags);
    1376                                
     1376
    13771377                                page_table_unlock(as, false);
    13781378                        }
    13791379                }
    13801380        }
    1381        
     1381
    13821382        free(old_frame);
    1383        
     1383
    13841384        mutex_unlock(&area->lock);
    13851385        mutex_unlock(&as->lock);
    1386        
     1386
    13871387        return 0;
    13881388}
     
    14141414        if (!THREAD)
    14151415                goto page_fault;
    1416        
     1416
    14171417        if (!AS)
    14181418                goto page_fault;
    1419        
     1419
    14201420        mutex_lock(&AS->lock);
    14211421        as_area_t *area = find_area_and_lock(AS, page);
     
    14281428                goto page_fault;
    14291429        }
    1430        
     1430
    14311431        if (area->attributes & AS_AREA_ATTR_PARTIAL) {
    14321432                /*
     
    14381438                goto page_fault;
    14391439        }
    1440        
     1440
    14411441        if ((!area->backend) || (!area->backend->page_fault)) {
    14421442                /*
     
    14481448                goto page_fault;
    14491449        }
    1450        
     1450
    14511451        page_table_lock(AS, false);
    1452        
     1452
    14531453        /*
    14541454         * To avoid race condition between two page faults on the same address,
     
    14671467                }
    14681468        }
    1469        
     1469
    14701470        /*
    14711471         * Resort to the backend page fault handler.
     
    14781478                goto page_fault;
    14791479        }
    1480        
     1480
    14811481        page_table_unlock(AS, false);
    14821482        mutex_unlock(&area->lock);
    14831483        mutex_unlock(&AS->lock);
    14841484        return AS_PF_OK;
    1485        
     1485
    14861486page_fault:
    14871487        if (THREAD->in_copy_from_uspace) {
     
    15011501                panic_memtrap(istate, access, address, NULL);
    15021502        }
    1503        
     1503
    15041504        return AS_PF_DEFER;
    15051505}
     
    15211521        DEADLOCK_PROBE_INIT(p_asidlock);
    15221522        preemption_disable();
    1523        
     1523
    15241524retry:
    15251525        (void) interrupts_disable();
     
    15361536        }
    15371537        preemption_enable();
    1538        
     1538
    15391539        /*
    15401540         * First, take care of the old address space.
     
    15421542        if (old_as) {
    15431543                assert(old_as->cpu_refcount);
    1544                
     1544
    15451545                if ((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
    15461546                        /*
     
    15511551                         */
    15521552                        assert(old_as->asid != ASID_INVALID);
    1553                        
     1553
    15541554                        list_append(&old_as->inactive_as_with_asid_link,
    15551555                            &inactive_as_with_asid_list);
    15561556                }
    1557                
     1557
    15581558                /*
    15591559                 * Perform architecture-specific tasks when the address space
     
    15621562                as_deinstall_arch(old_as);
    15631563        }
    1564        
     1564
    15651565        /*
    15661566         * Second, prepare the new address space.
     
    15721572                        new_as->asid = asid_get();
    15731573        }
    1574        
     1574
    15751575#ifdef AS_PAGE_TABLE
    15761576        SET_PTL0_ADDRESS(new_as->genarch.page_table);
    15771577#endif
    1578        
     1578
    15791579        /*
    15801580         * Perform architecture-specific steps.
     
    15821582         */
    15831583        as_install_arch(new_as);
    1584        
     1584
    15851585        spinlock_unlock(&asidlock);
    1586        
     1586
    15871587        AS = new_as;
    15881588}
     
    15981598{
    15991599        assert(mutex_locked(&area->lock));
    1600        
     1600
    16011601        return area_flags_to_page_flags(area->flags);
    16021602}
     
    16171617        assert(as_operations);
    16181618        assert(as_operations->page_table_create);
    1619        
     1619
    16201620        return as_operations->page_table_create(flags);
    16211621}
     
    16321632        assert(as_operations);
    16331633        assert(as_operations->page_table_destroy);
    1634        
     1634
    16351635        as_operations->page_table_destroy(page_table);
    16361636}
     
    16531653        assert(as_operations);
    16541654        assert(as_operations->page_table_lock);
    1655        
     1655
    16561656        as_operations->page_table_lock(as, lock);
    16571657}
     
    16671667        assert(as_operations);
    16681668        assert(as_operations->page_table_unlock);
    1669        
     1669
    16701670        as_operations->page_table_unlock(as, unlock);
    16711671}
     
    16971697{
    16981698        size_t size;
    1699        
     1699
    17001700        page_table_lock(AS, true);
    17011701        as_area_t *src_area = find_area_and_lock(AS, base);
    1702        
     1702
    17031703        if (src_area) {
    17041704                size = P2SZ(src_area->pages);
     
    17061706        } else
    17071707                size = 0;
    1708        
     1708
    17091709        page_table_unlock(AS, true);
    17101710        return size;
     
    17271727        assert(IS_ALIGNED(page, PAGE_SIZE));
    17281728        assert(count);
    1729        
     1729
    17301730        btree_node_t *leaf = NULL;
    17311731        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     
    17381738
    17391739        assert(leaf != NULL);
    1740        
     1740
    17411741        if (!leaf->keys) {
    17421742                btree_insert(&area->used_space, page, (void *) count, leaf);
    17431743                goto success;
    17441744        }
    1745        
     1745
    17461746        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
    17471747        if (node) {
     
    17501750                size_t left_cnt = (size_t) node->value[node->keys - 1];
    17511751                size_t right_cnt = (size_t) leaf->value[0];
    1752                
     1752
    17531753                /*
    17541754                 * Examine the possibility that the interval fits
     
    17561756                 * the left neigbour and the first interval of the leaf.
    17571757                 */
    1758                
     1758
    17591759                if (page >= right_pg) {
    17601760                        /* Do nothing. */
     
    18041804                uintptr_t right_pg = leaf->key[0];
    18051805                size_t right_cnt = (size_t) leaf->value[0];
    1806                
     1806
    18071807                /*
    18081808                 * Investigate the border case in which the left neighbour does
    18091809                 * not exist but the interval fits from the left.
    18101810                 */
    1811                
     1811
    18121812                if (overlaps(page, P2SZ(count), right_pg, P2SZ(right_cnt))) {
    18131813                        /* The interval intersects with the right interval. */
     
    18321832                }
    18331833        }
    1834        
     1834
    18351835        node = btree_leaf_node_right_neighbour(&area->used_space, leaf);
    18361836        if (node) {
     
    18391839                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    18401840                size_t right_cnt = (size_t) node->value[0];
    1841                
     1841
    18421842                /*
    18431843                 * Examine the possibility that the interval fits
     
    18451845                 * the right neigbour and the last interval of the leaf.
    18461846                 */
    1847                
     1847
    18481848                if (page < left_pg) {
    18491849                        /* Do nothing. */
     
    18931893                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    18941894                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    1895                
     1895
    18961896                /*
    18971897                 * Investigate the border case in which the right neighbour
    18981898                 * does not exist but the interval fits from the right.
    18991899                 */
    1900                
     1900
    19011901                if (overlaps(page, P2SZ(count), left_pg, P2SZ(left_cnt))) {
    19021902                        /* The interval intersects with the left interval. */
     
    19191919                }
    19201920        }
    1921        
     1921
    19221922        /*
    19231923         * Note that if the algorithm made it thus far, the interval can fit
     
    19321932                        size_t left_cnt = (size_t) leaf->value[i - 1];
    19331933                        size_t right_cnt = (size_t) leaf->value[i];
    1934                        
     1934
    19351935                        /*
    19361936                         * The interval fits between left_pg and right_pg.
    19371937                         */
    1938                        
     1938
    19391939                        if (overlaps(page, P2SZ(count), left_pg,
    19401940                            P2SZ(left_cnt))) {
     
    19881988                }
    19891989        }
    1990        
     1990
    19911991        panic("Inconsistency detected while adding %zu pages of used "
    19921992            "space at %p.", count, (void *) page);
    1993        
     1993
    19941994success:
    19951995        area->resident += count;
     
    20132013        assert(IS_ALIGNED(page, PAGE_SIZE));
    20142014        assert(count);
    2015        
     2015
    20162016        btree_node_t *leaf;
    20172017        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
     
    20382038                                }
    20392039                        }
    2040                        
     2040
    20412041                        goto error;
    20422042                }
    20432043        }
    2044        
     2044
    20452045        btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space,
    20462046            leaf);
     
    20482048                uintptr_t left_pg = node->key[node->keys - 1];
    20492049                size_t left_cnt = (size_t) node->value[node->keys - 1];
    2050                
     2050
    20512051                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
    20522052                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
     
    20782078                        }
    20792079                }
    2080                
     2080
    20812081                return false;
    20822082        } else if (page < leaf->key[0])
    20832083                return false;
    2084        
     2084
    20852085        if (page > leaf->key[leaf->keys - 1]) {
    20862086                uintptr_t left_pg = leaf->key[leaf->keys - 1];
    20872087                size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
    2088                
     2088
    20892089                if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
    20902090                        if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
     
    21152115                        }
    21162116                }
    2117                
     2117
    21182118                return false;
    21192119        }
    2120        
     2120
    21212121        /*
    21222122         * The border cases have been already resolved.
     
    21282128                        uintptr_t left_pg = leaf->key[i - 1];
    21292129                        size_t left_cnt = (size_t) leaf->value[i - 1];
    2130                        
     2130
    21312131                        /*
    21322132                         * Now the interval is between intervals corresponding
     
    21662166                                }
    21672167                        }
    2168                        
     2168
    21692169                        return false;
    21702170                }
    21712171        }
    2172        
     2172
    21732173error:
    21742174        panic("Inconsistency detected while removing %zu pages of used "
    21752175            "space from %p.", count, (void *) page);
    2176        
     2176
    21772177success:
    21782178        area->resident -= count;
     
    22042204        if (area == NULL)
    22052205                return (sysarg_t) AS_MAP_FAILED;
    2206        
     2206
    22072207        return (sysarg_t) virt;
    22082208}
     
    22332233{
    22342234        mutex_lock(&as->lock);
    2235        
     2235
    22362236        /* First pass, count number of areas. */
    2237        
     2237
    22382238        size_t area_cnt = 0;
    2239        
     2239
    22402240        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
    22412241            node) {
    22422242                area_cnt += node->keys;
    22432243        }
    2244        
     2244
    22452245        size_t isize = area_cnt * sizeof(as_area_info_t);
    22462246        as_area_info_t *info = malloc(isize, 0);
    2247        
     2247
    22482248        /* Second pass, record data. */
    2249        
     2249
    22502250        size_t area_idx = 0;
    2251        
     2251
    22522252        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
    22532253            node) {
    22542254                btree_key_t i;
    2255                
     2255
    22562256                for (i = 0; i < node->keys; i++) {
    22572257                        as_area_t *area = node->value[i];
    2258                        
     2258
    22592259                        assert(area_idx < area_cnt);
    22602260                        mutex_lock(&area->lock);
    2261                        
     2261
    22622262                        info[area_idx].start_addr = area->base;
    22632263                        info[area_idx].size = P2SZ(area->pages);
    22642264                        info[area_idx].flags = area->flags;
    22652265                        ++area_idx;
    2266                        
     2266
    22672267                        mutex_unlock(&area->lock);
    22682268                }
    22692269        }
    2270        
     2270
    22712271        mutex_unlock(&as->lock);
    2272        
     2272
    22732273        *obuf = info;
    22742274        *osize = isize;
     
    22832283{
    22842284        mutex_lock(&as->lock);
    2285        
     2285
    22862286        /* Print out info about address space areas */
    22872287        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
    22882288            node) {
    22892289                btree_key_t i;
    2290                
     2290
    22912291                for (i = 0; i < node->keys; i++) {
    22922292                        as_area_t *area = node->value[i];
    2293                        
     2293
    22942294                        mutex_lock(&area->lock);
    22952295                        printf("as_area: %p, base=%p, pages=%zu"
     
    23002300                }
    23012301        }
    2302        
     2302
    23032303        mutex_unlock(&as->lock);
    23042304}
Note: See TracChangeset for help on using the changeset viewer.