Changeset d3e7ff4 in mainline for generic/src/mm/as.c


Ignore:
Timestamp:
2006-03-14T14:10:25Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5581c45e
Parents:
5be1923
Message:

Add sys_mremap() syscall.

File:
1 edited

Legend:

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

    r5be1923 rd3e7ff4  
    7070
    7171static int get_area_flags(as_area_t *a);
     72static as_area_t *find_area_and_lock(as_t *as, __address va);
    7273
    7374/** Initialize address space subsystem. */
     
    169170void as_set_mapping(as_t *as, __address page, __address frame)
    170171{
    171         as_area_t *a, *area = NULL;
    172         link_t *cur;
     172        as_area_t *area;
    173173        ipl_t ipl;
    174174       
     
    176176        spinlock_lock(&as->lock);
    177177       
    178         /*
    179          * First, try locate an area.
    180          */
    181         for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
    182                 a = list_get_instance(cur, as_area_t, link);
    183                 spinlock_lock(&a->lock);
    184 
    185                 if ((page >= a->base) && (page < a->base + a->size * PAGE_SIZE)) {
    186                         area = a;
    187                         break;
    188                 }
    189                
    190                 spinlock_unlock(&a->lock);
    191         }
    192        
     178        area = find_area_and_lock(as, page);
    193179        if (!area) {
    194180                panic("page not part of any as_area\n");
    195181        }
    196182
    197         /*
    198          * Note: area->lock is held.
    199          */
    200        
    201183        page_mapping_insert(as, page, frame, get_area_flags(area));
    202184       
     
    217199int as_page_fault(__address page)
    218200{
    219         link_t *cur;
    220         as_area_t *a, *area = NULL;
     201        as_area_t *area;
    221202        __address frame;
    222203       
     
    224205        spinlock_lock(&AS->lock);
    225206       
    226         /*
    227          * Search this areas of this address space for presence of 'page'.
    228          */
    229         for (cur = AS->as_area_head.next; cur != &AS->as_area_head; cur = cur->next) {
    230                 a = list_get_instance(cur, as_area_t, link);
    231                 spinlock_lock(&a->lock);
    232 
    233                 if ((page >= a->base) && (page < a->base + a->size * PAGE_SIZE)) {
    234 
    235                         /*
    236                          * We found the area containing 'page'.
    237                          * TODO: access checking
    238                          */
    239                         area = a;
    240                         break;
    241                 }
    242                
    243                 spinlock_unlock(&a->lock);
    244         }
    245        
     207        area = find_area_and_lock(AS, page);   
    246208        if (!area) {
    247209                /*
     
    253215        }
    254216
    255         /*
    256          * Note: area->lock is held.
    257          */
    258        
    259217        /*
    260218         * In general, there can be several reasons that
     
    400358        return as_operations->page_table_create(flags);
    401359}
     360
     361/** Find address space area and change it.
     362 *
     363 * @param as Address space.
     364 * @param address Virtual address belonging to the area to be changed. Must be page-aligned.
     365 * @param size New size of the virtual memory block starting at address.
     366 * @param flags Flags influencing the remap operation. Currently unused.
     367 *
     368 * @return address on success, (__address) -1 otherwise.
     369 */
     370__address as_remap(as_t *as, __address address, size_t size, int flags)
     371{
     372        as_area_t *area = NULL;
     373        ipl_t ipl;
     374        size_t pages;
     375       
     376        ipl = interrupts_disable();
     377        spinlock_lock(&as->lock);
     378       
     379        /*
     380         * Locate the area.
     381         */
     382        area = find_area_and_lock(as, address);
     383        if (!area) {
     384                spinlock_unlock(&as->lock);
     385                return (__address) -1;
     386        }
     387
     388        pages = SIZE2FRAMES((address - area->base) + size);
     389        if (pages < area->size) {
     390                int i;
     391
     392                /*
     393                 * Shrinking the area.
     394                 */
     395                for (i = pages; i < area->size; i++) {
     396                        pte_t *pte;
     397                       
     398                        /*
     399                         * Releasing physical memory.
     400                         * This depends on the fact that the memory was allocated using frame_alloc().
     401                         */
     402                        pte = page_mapping_find(as, area->base + i*PAGE_SIZE);
     403                        if (pte) {
     404                                ASSERT(PTE_PRESENT(pte));
     405                                frame_free(ADDR2PFN(PTE_GET_FRAME(pte)));
     406                        }
     407                        page_mapping_remove(as, area->base + i*PAGE_SIZE);
     408                }
     409                /*
     410                 * Invalidate TLB's.
     411                 */
     412                tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
     413                tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
     414                tlb_shootdown_finalize();
     415        } else {
     416                /*
     417                 * Growing the area.
     418                 */
     419                area->size = size;
     420        }
     421       
     422        spinlock_unlock(&area->lock);
     423        spinlock_unlock(&as->lock);
     424        interrupts_restore(ipl);
     425
     426        return address;
     427}
     428
     429/** Find address space area and lock it.
     430 *
     431 * The address space must be locked and interrupts must be disabled.
     432 *
     433 * @param as Address space.
     434 * @param va Virtual address.
     435 *
     436 * @return Locked address space area containing va on success or NULL on failure.
     437 */
     438as_area_t *find_area_and_lock(as_t *as, __address va)
     439{
     440        link_t *cur;
     441        as_area_t *a;
     442       
     443        for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
     444                a = list_get_instance(cur, as_area_t, link);
     445                spinlock_lock(&a->lock);
     446
     447                if ((va >= a->base) && (va < a->base + a->size * PAGE_SIZE))
     448                         return a;
     449               
     450                spinlock_unlock(&a->lock);
     451        }
     452
     453        return NULL;
     454}
Note: See TracChangeset for help on using the changeset viewer.