Changeset 1cc2974 in mainline for kernel/generic/src/mm/backend_elf.c


Ignore:
Timestamp:
2008-05-26T18:56:34Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5a55ae6
Parents:
fa832eb
Message:

Improve linking and loading of boot ELF images.
(Contributed by Jiri Svoboda)

File:
1 edited

Legend:

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

    rfa832eb r1cc2974  
    8080        elf_segment_header_t *entry = area->backend_data.segment;
    8181        btree_node_t *leaf;
    82         uintptr_t base, frame;
     82        uintptr_t base, frame, page, start_anon;
    8383        index_t i;
    8484        bool dirty = false;
     
    8787                return AS_PF_FAULT;
    8888
    89         ASSERT((addr >= entry->p_vaddr) &&
     89        ASSERT((addr >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) &&
    9090            (addr < entry->p_vaddr + entry->p_memsz));
    91         i = (addr - entry->p_vaddr) >> PAGE_WIDTH;
    92         base = (uintptr_t) (((void *) elf) + entry->p_offset);
    93         ASSERT(ALIGN_UP(base, FRAME_SIZE) == base);
     91        i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     92        base = (uintptr_t)
     93            (((void *) elf) + ALIGN_DOWN(entry->p_offset, PAGE_SIZE));
     94
     95        /* Virtual address of faulting page*/
     96        page = ALIGN_DOWN(addr, PAGE_SIZE);
     97
     98        /* Virtual address of the end of initialized part of segment */
     99        start_anon = entry->p_vaddr + entry->p_filesz;
    94100
    95101        if (area->sh_info) {
     
    99105                 * The address space area is shared.
    100106                 */
    101                  
     107               
    102108                mutex_lock(&area->sh_info->lock);
    103109                frame = (uintptr_t) btree_search(&area->sh_info->pagemap,
    104                         ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
     110                    page - area->base, &leaf);
    105111                if (!frame) {
    106112                        unsigned int i;
     
    111117
    112118                        for (i = 0; i < leaf->keys; i++) {
    113                                 if (leaf->key[i] ==
    114                                     ALIGN_DOWN(addr, PAGE_SIZE)) {
     119                                if (leaf->key[i] == page) {
    115120                                        found = true;
    116121                                        break;
     
    122127                        page_mapping_insert(AS, addr, frame,
    123128                            as_area_get_flags(area));
    124                         if (!used_space_insert(area,
    125                             ALIGN_DOWN(addr, PAGE_SIZE), 1))
     129                        if (!used_space_insert(area, page, 1))
    126130                                panic("Could not insert used space.\n");
    127131                        mutex_unlock(&area->sh_info->lock);
     
    129133                }
    130134        }
    131        
     135
    132136        /*
    133137         * The area is either not shared or the pagemap does not contain the
    134138         * mapping.
    135139         */
    136        
    137         if (ALIGN_DOWN(addr, PAGE_SIZE) + PAGE_SIZE <
    138             entry->p_vaddr + entry->p_filesz) {
     140        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    139141                /*
    140142                 * Initialized portion of the segment. The memory is backed
     
    150152                            (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
    151153                        dirty = true;
    152 
    153                         if (area->sh_info) {
    154                                 frame_reference_add(ADDR2PFN(frame));
    155                                 btree_insert(&area->sh_info->pagemap,
    156                                     ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
    157                                     (void *) frame, leaf);
    158                         }
    159 
    160154                } else {
    161                         frame = KA2PA(base + i*FRAME_SIZE);
     155                        frame = KA2PA(base + i * FRAME_SIZE);
    162156                }       
    163         } else if (ALIGN_DOWN(addr, PAGE_SIZE) >=
    164             ALIGN_UP(entry->p_vaddr + entry->p_filesz, PAGE_SIZE)) {
     157        } else if (page >= start_anon) {
    165158                /*
    166159                 * This is the uninitialized portion of the segment.
     
    172165                memsetb(PA2KA(frame), FRAME_SIZE, 0);
    173166                dirty = true;
    174 
    175                 if (area->sh_info) {
    176                         frame_reference_add(ADDR2PFN(frame));
    177                         btree_insert(&area->sh_info->pagemap,
    178                             ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
    179                             (void *) frame, leaf);
    180                 }
    181 
    182167        } else {
    183                 size_t size;
     168                size_t pad_lo, pad_hi;
    184169                /*
    185170                 * The mixed case.
    186                  * The lower part is backed by the ELF image and
    187                  * the upper part is anonymous memory.
     171                 *
     172                 * The middle part is backed by the ELF image and
     173                 * the lower and upper parts are anonymous memory.
     174                 * (The segment can be and often is shorter than 1 page).
    188175                 */
    189                 size = entry->p_filesz - (i<<PAGE_WIDTH);
     176                if (page < entry->p_vaddr)
     177                        pad_lo = entry->p_vaddr - page;
     178                else
     179                        pad_lo = 0;
     180
     181                if (start_anon < page + PAGE_SIZE)
     182                        pad_hi = page + PAGE_SIZE - start_anon;
     183                else
     184                        pad_hi = 0;
     185
    190186                frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
    191                 memsetb(PA2KA(frame) + size, FRAME_SIZE - size, 0);
    192                 memcpy((void *) PA2KA(frame), (void *) (base + i * FRAME_SIZE),
    193                     size);
     187                memcpy((void *) (PA2KA(frame) + pad_lo),
     188                    (void *) (base + i * FRAME_SIZE + pad_lo),
     189                    FRAME_SIZE - pad_lo - pad_hi);
     190                memsetb(PA2KA(frame), pad_lo, 0);
     191                memsetb(PA2KA(frame) + FRAME_SIZE - pad_hi, pad_hi, 0);
    194192                dirty = true;
    195 
    196                 if (area->sh_info) {
    197                         frame_reference_add(ADDR2PFN(frame));
    198                         btree_insert(&area->sh_info->pagemap,
    199                             ALIGN_DOWN(addr, PAGE_SIZE) - area->base,
    200                             (void *) frame, leaf);
    201                 }
    202 
    203         }
    204        
     193        }
     194
     195        if (dirty && area->sh_info) {
     196                frame_reference_add(ADDR2PFN(frame));
     197                btree_insert(&area->sh_info->pagemap, page - area->base,
     198                    (void *) frame, leaf);
     199        }
     200
    205201        if (area->sh_info)
    206202                mutex_unlock(&area->sh_info->lock);
    207        
     203
    208204        page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
    209         if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
     205        if (!used_space_insert(area, page, 1))
    210206                panic("Could not insert used space.\n");
    211207
     
    226222        elf_header_t *elf = area->backend_data.elf;
    227223        elf_segment_header_t *entry = area->backend_data.segment;
    228         uintptr_t base;
     224        uintptr_t base, start_anon;
    229225        index_t i;
    230        
    231         ASSERT((page >= entry->p_vaddr) &&
     226
     227        ASSERT((page >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) &&
    232228            (page < entry->p_vaddr + entry->p_memsz));
    233         i = (page - entry->p_vaddr) >> PAGE_WIDTH;
    234         base = (uintptr_t) (((void *) elf) + entry->p_offset);
    235         ASSERT(ALIGN_UP(base, FRAME_SIZE) == base);
    236        
    237         if (page + PAGE_SIZE <
    238             ALIGN_UP(entry->p_vaddr + entry->p_filesz, PAGE_SIZE)) {
     229        i = (page - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
     230        base = (uintptr_t) (((void *) elf) +
     231            ALIGN_DOWN(entry->p_offset, FRAME_SIZE));
     232        start_anon = entry->p_vaddr + entry->p_filesz;
     233
     234        if (page >= entry->p_vaddr && page + PAGE_SIZE <= start_anon) {
    239235                if (entry->p_flags & PF_W) {
    240236                        /*
     
    305301                         */
    306302                        if (!(area->flags & AS_AREA_WRITE))
    307                                 if (base + count * PAGE_SIZE <= start_anon)
     303                                if (base >= entry->p_vaddr &&
     304                                    base + count * PAGE_SIZE <= start_anon)
    308305                                        continue;
    309306                       
     
    316313                                 */
    317314                                if (!(area->flags & AS_AREA_WRITE))
    318                                         if (base + (j + 1) * PAGE_SIZE <=
     315                                        if (base >= entry->p_vaddr &&
     316                                            base + (j + 1) * PAGE_SIZE <=
    319317                                            start_anon)
    320318                                                continue;
Note: See TracChangeset for help on using the changeset viewer.