Changeset 00b595b in mainline


Ignore:
Timestamp:
2006-05-27T21:53:24Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
46fc2f9
Parents:
127c957b
Message:

Support for sharing address space areas backed up by ELF image.

Location:
generic/src/mm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified generic/src/mm/backend_anon.c

    r127c957b r00b595b  
    162162 * to the pagemap. Page faults will primarily search for frames there.
    163163 *
    164  * The address space area and page tables must be already locked.
     164 * The address space and address space area must be already locked.
    165165 *
    166166 * @param area Address space area to be shared.
  • TabularUnified generic/src/mm/backend_elf.c

    r127c957b r00b595b  
    3939#include <mm/frame.h>
    4040#include <mm/slab.h>
     41#include <mm/page.h>
     42#include <genarch/mm/page_pt.h>
     43#include <genarch/mm/page_ht.h>
    4144#include <align.h>
    4245#include <memstr.h>
     
    4649static int elf_page_fault(as_area_t *area, __address addr, pf_access_t access);
    4750static void elf_frame_free(as_area_t *area, __address page, __address frame);
     51static void elf_share(as_area_t *area);
    4852
    4953mem_backend_t elf_backend = {
    5054        .page_fault = elf_page_fault,
    5155        .frame_free = elf_frame_free,
    52         .share = NULL
     56        .share = elf_share
    5357};
    5458
     
    6771        elf_header_t *elf = area->backend_data.elf;
    6872        elf_segment_header_t *entry = area->backend_data.segment;
     73        btree_node_t *leaf;
    6974        __address base, frame;
    7075        index_t i;
     
    7782        base = (__address) (((void *) elf) + entry->p_offset);
    7883        ASSERT(ALIGN_UP(base, FRAME_SIZE) == base);
     84
     85        if (area->sh_info) {
     86                bool found = false;
     87
     88                /*
     89                 * The address space area is shared.
     90                 */
     91                 
     92                mutex_lock(&area->sh_info->lock);
     93                frame = (__address) btree_search(&area->sh_info->pagemap,
     94                        ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
     95                if (!frame) {
     96                        int i;
     97
     98                        /*
     99                         * Workaround for valid NULL address.
     100                         */
     101
     102                        for (i = 0; i < leaf->keys; i++) {
     103                                if (leaf->key[i] == ALIGN_DOWN(addr, PAGE_SIZE)) {
     104                                        found = true;
     105                                        break;
     106                                }
     107                        }
     108                }
     109                if (frame || found) {
     110                        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
     111                        if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
     112                                panic("Could not insert used space.\n");
     113                        mutex_unlock(&area->sh_info->lock);
     114                        return AS_PF_OK;
     115                }
     116        }
     117       
     118        /*
     119         * The area is either not shared or the pagemap does not contain the mapping.
     120         */
    79121       
    80122        if (ALIGN_DOWN(addr, PAGE_SIZE) + PAGE_SIZE < entry->p_vaddr + entry->p_filesz) {
     
    90132                        frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
    91133                        memcpy((void *) PA2KA(frame), (void *) (base + i*FRAME_SIZE), FRAME_SIZE);
     134                       
     135                        if (area->sh_info) {
     136                                btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
     137                                        (void *) frame, leaf);
     138                        }
     139
    92140                } else {
    93141                        frame = KA2PA(base + i*FRAME_SIZE);
     
    102150                frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
    103151                memsetb(PA2KA(frame), FRAME_SIZE, 0);
     152
     153                if (area->sh_info) {
     154                        btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
     155                                (void *) frame, leaf);
     156                }
     157
    104158        } else {
    105159                size_t size;
     
    113167                memsetb(PA2KA(frame) + size, FRAME_SIZE - size, 0);
    114168                memcpy((void *) PA2KA(frame), (void *) (base + i*FRAME_SIZE), size);
    115         }
     169
     170                if (area->sh_info) {
     171                        btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
     172                                (void *) frame, leaf);
     173                }
     174
     175        }
     176       
     177        if (area->sh_info)
     178                mutex_unlock(&area->sh_info->lock);
    116179       
    117180        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    118         if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
    119                 panic("Could not insert used space.\n");
     181        if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
     182                panic("Could not insert used space.\n");
    120183
    121184        return AS_PF_OK;
     
    159222        }
    160223}
     224
     225/** Share ELF image backed address space area.
     226 *
     227 * If the area is writable, then all mapped pages are duplicated in the pagemap.
     228 * Otherwise only portions of the area that are not backed by the ELF image
     229 * are put into the pagemap.
     230 *
     231 * The address space and address space area must be locked prior to the call.
     232 *
     233 * @param area Address space area.
     234 */
     235void elf_share(as_area_t *area)
     236{
     237        elf_segment_header_t *entry = area->backend_data.segment;
     238        link_t *cur;
     239        btree_node_t *leaf, *node;
     240        __address start_anon = entry->p_vaddr + entry->p_filesz;
     241
     242        /*
     243         * Find the node in which to start linear search.
     244         */
     245        if (area->flags & AS_AREA_WRITE) {
     246                node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link);
     247        } else {
     248                (void) btree_search(&area->sh_info->pagemap, start_anon, &leaf);
     249                node = btree_leaf_node_left_neighbour(&area->sh_info->pagemap, leaf);
     250                if (!node)
     251                        node = leaf;
     252        }
     253
     254        /*
     255         * Copy used anonymous portions of the area to sh_info's page map.
     256         */
     257        mutex_lock(&area->sh_info->lock);
     258        for (cur = &node->leaf_link; cur != &area->used_space.leaf_head; cur = cur->next) {
     259                int i;
     260               
     261                node = list_get_instance(cur, btree_node_t, leaf_link);
     262               
     263                for (i = 0; i < node->keys; i++) {
     264                        __address base = node->key[i];
     265                        count_t count = (count_t) node->value[i];
     266                        int j;
     267                       
     268                        /*
     269                         * Skip read-only areas of used space that are backed
     270                         * by the ELF image.
     271                         */
     272                        if (!(area->flags & AS_AREA_WRITE))
     273                                if (base + count*PAGE_SIZE <= start_anon)
     274                                        continue;
     275                       
     276                        for (j = 0; j < count; j++) {
     277                                pte_t *pte;
     278                       
     279                                /*
     280                                 * Skip read-only pages that are backed by the ELF image.
     281                                 */
     282                                if (!(area->flags & AS_AREA_WRITE))
     283                                        if (base + (j + 1)*PAGE_SIZE <= start_anon)
     284                                                continue;
     285                               
     286                                page_table_lock(area->as, false);
     287                                pte = page_mapping_find(area->as, base + j*PAGE_SIZE);
     288                                ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
     289                                btree_insert(&area->sh_info->pagemap, (base + j*PAGE_SIZE) - area->base,
     290                                        (void *) PTE_GET_FRAME(pte), NULL);
     291                                page_table_unlock(area->as, false);
     292                        }
     293                               
     294                }
     295        }
     296        mutex_unlock(&area->sh_info->lock);
     297}
Note: See TracChangeset for help on using the changeset viewer.