Ignore:
File:
1 edited

Legend:

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

    r908bb96 r826599a2  
    488488       
    489489        /* Eventually check the addresses behind each area */
    490         list_foreach(as->as_area_btree.leaf_list, cur) {
    491                 btree_node_t *node =
    492                     list_get_instance(cur, btree_node_t, leaf_link);
     490        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t, node) {
    493491               
    494492                for (btree_key_t i = 0; i < node->keys; i++) {
     
    522520}
    523521
     522/** Remove reference to address space area share info.
     523 *
     524 * If the reference count drops to 0, the sh_info is deallocated.
     525 *
     526 * @param sh_info Pointer to address space area share info.
     527 *
     528 */
     529NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)
     530{
     531        bool dealloc = false;
     532       
     533        mutex_lock(&sh_info->lock);
     534        ASSERT(sh_info->refcount);
     535       
     536        if (--sh_info->refcount == 0) {
     537                dealloc = true;
     538               
     539                /*
     540                 * Now walk carefully the pagemap B+tree and free/remove
     541                 * reference from all frames found there.
     542                 */
     543                list_foreach(sh_info->pagemap.leaf_list, leaf_link,
     544                    btree_node_t, node) {
     545                        btree_key_t i;
     546                       
     547                        for (i = 0; i < node->keys; i++)
     548                                frame_free((uintptr_t) node->value[i], 1);
     549                }
     550               
     551        }
     552        mutex_unlock(&sh_info->lock);
     553       
     554        if (dealloc) {
     555                if (sh_info->backend && sh_info->backend->destroy_shared_data) {
     556                        sh_info->backend->destroy_shared_data(
     557                            sh_info->backend_shared_data);
     558                }
     559                btree_destroy(&sh_info->pagemap);
     560                free(sh_info);
     561        }
     562}
     563
     564
    524565/** Create address space area of common attributes.
    525566 *
     
    531572 * @param attrs        Attributes of the area.
    532573 * @param backend      Address space area backend. NULL if no backend is used.
    533  * @param backend_data NULL or a pointer to an array holding two void *.
     574 * @param backend_data NULL or a pointer to custom backend data.
    534575 * @param base         Starting virtual address of the area.
    535576 *                     If set to -1, a suitable mappable area is found.
     
    544585    mem_backend_data_t *backend_data, uintptr_t *base, uintptr_t bound)
    545586{
    546         if ((*base != (uintptr_t) -1) && ((*base % PAGE_SIZE) != 0))
     587        if ((*base != (uintptr_t) -1) && !IS_ALIGNED(*base, PAGE_SIZE))
    547588                return NULL;
    548589       
     
    568609        }
    569610
    570         if (overflows_into_positive(*base, size))
     611        if (overflows_into_positive(*base, size)) {
     612                mutex_unlock(&as->lock);
    571613                return NULL;
     614        }
    572615
    573616        if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
     
    586629        area->resident = 0;
    587630        area->base = *base;
     631        area->backend = backend;
    588632        area->sh_info = NULL;
    589         area->backend = backend;
    590633       
    591634        if (backend_data)
     
    593636        else
    594637                memsetb(&area->backend_data, sizeof(area->backend_data), 0);
    595        
     638
     639        share_info_t *si = NULL;
     640
     641        /*
     642         * Create the sharing info structure.
     643         * We do this in advance for every new area, even if it is not going
     644         * to be shared.
     645         */
     646        if (!(attrs & AS_AREA_ATTR_PARTIAL)) {
     647                si = (share_info_t *) malloc(sizeof(share_info_t), 0);
     648                mutex_initialize(&si->lock, MUTEX_PASSIVE);
     649                si->refcount = 1;
     650                si->shared = false;
     651                si->backend_shared_data = NULL;
     652                si->backend = backend;
     653                btree_create(&si->pagemap);
     654
     655                area->sh_info = si;
     656       
     657                if (area->backend && area->backend->create_shared_data) {
     658                        if (!area->backend->create_shared_data(area)) {
     659                                free(area);
     660                                mutex_unlock(&as->lock);
     661                                sh_info_remove_reference(si);
     662                                return NULL;
     663                        }
     664                }
     665        }
     666
    596667        if (area->backend && area->backend->create) {
    597668                if (!area->backend->create(area)) {
    598669                        free(area);
    599670                        mutex_unlock(&as->lock);
     671                        if (!(attrs & AS_AREA_ATTR_PARTIAL))
     672                                sh_info_remove_reference(si);
    600673                        return NULL;
    601674                }
    602675        }
    603        
     676
    604677        btree_create(&area->used_space);
    605678        btree_insert(&as->as_area_btree, *base, (void *) area,
     
    688761int as_area_resize(as_t *as, uintptr_t address, size_t size, unsigned int flags)
    689762{
     763        if (!IS_ALIGNED(address, PAGE_SIZE))
     764                return EINVAL;
     765
    690766        mutex_lock(&as->lock);
    691767       
     
    708784        }
    709785       
    710         if (area->sh_info) {
     786        mutex_lock(&area->sh_info->lock);
     787        if (area->sh_info->shared) {
    711788                /*
    712789                 * Remapping of shared address space areas
    713790                 * is not supported.
    714791                 */
     792                mutex_unlock(&area->sh_info->lock);
    715793                mutex_unlock(&area->lock);
    716794                mutex_unlock(&as->lock);
    717795                return ENOTSUP;
    718796        }
     797        mutex_unlock(&area->sh_info->lock);
    719798       
    720799        size_t pages = SIZE2FRAMES((address - area->base) + size);
     
    880959}
    881960
    882 /** Remove reference to address space area share info.
    883  *
    884  * If the reference count drops to 0, the sh_info is deallocated.
    885  *
    886  * @param sh_info Pointer to address space area share info.
    887  *
    888  */
    889 NO_TRACE static void sh_info_remove_reference(share_info_t *sh_info)
    890 {
    891         bool dealloc = false;
    892        
    893         mutex_lock(&sh_info->lock);
    894         ASSERT(sh_info->refcount);
    895        
    896         if (--sh_info->refcount == 0) {
    897                 dealloc = true;
    898                
    899                 /*
    900                  * Now walk carefully the pagemap B+tree and free/remove
    901                  * reference from all frames found there.
    902                  */
    903                 list_foreach(sh_info->pagemap.leaf_list, cur) {
    904                         btree_node_t *node
    905                             = list_get_instance(cur, btree_node_t, leaf_link);
    906                         btree_key_t i;
    907                        
    908                         for (i = 0; i < node->keys; i++)
    909                                 frame_free((uintptr_t) node->value[i]);
    910                 }
    911                
    912         }
    913         mutex_unlock(&sh_info->lock);
    914        
    915         if (dealloc) {
    916                 btree_destroy(&sh_info->pagemap);
    917                 free(sh_info);
    918         }
    919 }
    920 
    921961/** Destroy address space area.
    922962 *
     
    953993         * Visit only the pages mapped by used_space B+tree.
    954994         */
    955         list_foreach(area->used_space.leaf_list, cur) {
    956                 btree_node_t *node;
     995        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     996            node) {
    957997                btree_key_t i;
    958998               
    959                 node = list_get_instance(cur, btree_node_t, leaf_link);
    960999                for (i = 0; i < node->keys; i++) {
    9611000                        uintptr_t ptr = node->key[i];
     
    10011040        area->attributes |= AS_AREA_ATTR_PARTIAL;
    10021041       
    1003         if (area->sh_info)
    1004                 sh_info_remove_reference(area->sh_info);
     1042        sh_info_remove_reference(area->sh_info);
    10051043       
    10061044        mutex_unlock(&area->lock);
     
    10891127         */
    10901128        share_info_t *sh_info = src_area->sh_info;
    1091         if (!sh_info) {
    1092                 sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
    1093                 mutex_initialize(&sh_info->lock, MUTEX_PASSIVE);
    1094                 sh_info->refcount = 2;
    1095                 btree_create(&sh_info->pagemap);
    1096                 src_area->sh_info = sh_info;
    1097                
     1129       
     1130        mutex_lock(&sh_info->lock);
     1131        sh_info->refcount++;
     1132        bool shared = sh_info->shared;
     1133        sh_info->shared = true;
     1134        mutex_unlock(&sh_info->lock);
     1135
     1136        if (!shared) {
    10981137                /*
    10991138                 * Call the backend to setup sharing.
     1139                 * This only happens once for each sh_info.
    11001140                 */
    11011141                src_area->backend->share(src_area);
    1102         } else {
    1103                 mutex_lock(&sh_info->lock);
    1104                 sh_info->refcount++;
    1105                 mutex_unlock(&sh_info->lock);
    11061142        }
    11071143       
     
    12221258        }
    12231259       
    1224         if ((area->sh_info) || (area->backend != &anon_backend)) {
    1225                 /* Copying shared areas not supported yet */
     1260        if (area->backend != &anon_backend) {
    12261261                /* Copying non-anonymous memory not supported yet */
    12271262                mutex_unlock(&area->lock);
     
    12291264                return ENOTSUP;
    12301265        }
     1266
     1267        mutex_lock(&area->sh_info->lock);
     1268        if (area->sh_info->shared) {
     1269                /* Copying shared areas not supported yet */
     1270                mutex_unlock(&area->sh_info->lock);
     1271                mutex_unlock(&area->lock);
     1272                mutex_unlock(&as->lock);
     1273                return ENOTSUP;
     1274        }
     1275        mutex_unlock(&area->sh_info->lock);
    12311276       
    12321277        /*
     
    12351280        size_t used_pages = 0;
    12361281       
    1237         list_foreach(area->used_space.leaf_list, cur) {
    1238                 btree_node_t *node
    1239                     = list_get_instance(cur, btree_node_t, leaf_link);
     1282        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1283            node) {
    12401284                btree_key_t i;
    12411285               
     
    12611305        size_t frame_idx = 0;
    12621306       
    1263         list_foreach(area->used_space.leaf_list, cur) {
    1264                 btree_node_t *node = list_get_instance(cur, btree_node_t,
    1265                     leaf_link);
     1307        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1308            node) {
    12661309                btree_key_t i;
    12671310               
     
    13131356        frame_idx = 0;
    13141357       
    1315         list_foreach(area->used_space.leaf_list, cur) {
    1316                 btree_node_t *node
    1317                     = list_get_instance(cur, btree_node_t, leaf_link);
     1358        list_foreach(area->used_space.leaf_list, leaf_link, btree_node_t,
     1359            node) {
    13181360                btree_key_t i;
    13191361               
     
    13501392 * Interrupts are assumed disabled.
    13511393 *
    1352  * @param page   Faulting page.
    1353  * @param access Access mode that caused the page fault (i.e.
    1354  *               read/write/exec).
    1355  * @param istate Pointer to the interrupted state.
     1394 * @param address Faulting address.
     1395 * @param access  Access mode that caused the page fault (i.e.
     1396 *                read/write/exec).
     1397 * @param istate  Pointer to the interrupted state.
    13561398 *
    13571399 * @return AS_PF_FAULT on page fault.
     
    13611403 *
    13621404 */
    1363 int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
    1364 {
     1405int as_page_fault(uintptr_t address, pf_access_t access, istate_t *istate)
     1406{
     1407        uintptr_t page = ALIGN_DOWN(address, PAGE_SIZE);
    13651408        int rc = AS_PF_FAULT;
    13661409
     
    14521495                task_kill_self(true);
    14531496        } else {
    1454                 fault_if_from_uspace(istate, "Page fault: %p.", (void *) page);
    1455                 panic_memtrap(istate, access, page, NULL);
     1497                fault_if_from_uspace(istate, "Page fault: %p.", (void *) address);
     1498                panic_memtrap(istate, access, address, NULL);
    14561499        }
    14571500       
     
    16791722{
    16801723        ASSERT(mutex_locked(&area->lock));
    1681         ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
     1724        ASSERT(IS_ALIGNED(page, PAGE_SIZE));
    16821725        ASSERT(count);
    16831726       
    1684         btree_node_t *leaf;
     1727        btree_node_t *leaf = NULL;
    16851728        size_t pages = (size_t) btree_search(&area->used_space, page, &leaf);
    16861729        if (pages) {
     
    16901733                return false;
    16911734        }
     1735
     1736        ASSERT(leaf != NULL);
    16921737       
    16931738        if (!leaf->keys) {
     
    19632008{
    19642009        ASSERT(mutex_locked(&area->lock));
    1965         ASSERT(page == ALIGN_DOWN(page, PAGE_SIZE));
     2010        ASSERT(IS_ALIGNED(page, PAGE_SIZE));
    19662011        ASSERT(count);
    19672012       
     
    21402185{
    21412186        uintptr_t virt = base;
    2142         as_area_t *area = as_area_create(AS, flags | AS_AREA_CACHEABLE, size,
     2187        as_area_t *area = as_area_create(AS, flags, size,
    21432188            AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, bound);
    21442189        if (area == NULL)
     
    21782223        size_t area_cnt = 0;
    21792224       
    2180         list_foreach(as->as_area_btree.leaf_list, cur) {
    2181                 btree_node_t *node =
    2182                     list_get_instance(cur, btree_node_t, leaf_link);
     2225        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2226            node) {
    21832227                area_cnt += node->keys;
    21842228        }
     
    21912235        size_t area_idx = 0;
    21922236       
    2193         list_foreach(as->as_area_btree.leaf_list, cur) {
    2194                 btree_node_t *node =
    2195                     list_get_instance(cur, btree_node_t, leaf_link);
     2237        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2238            node) {
    21962239                btree_key_t i;
    21972240               
     
    22272270       
    22282271        /* Print out info about address space areas */
    2229         list_foreach(as->as_area_btree.leaf_list, cur) {
    2230                 btree_node_t *node
    2231                     = list_get_instance(cur, btree_node_t, leaf_link);
     2272        list_foreach(as->as_area_btree.leaf_list, leaf_link, btree_node_t,
     2273            node) {
    22322274                btree_key_t i;
    22332275               
Note: See TracChangeset for help on using the changeset viewer.