Changeset 37e7d2b9 in mainline


Ignore:
Timestamp:
2006-03-16T14:46:06Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
dabe6333
Parents:
e898a8d7
Message:

Restore interrupts when failing in as_remap().
Add check_area_conflicts() that checks whether address area overlaps with other areas.
Refuse to create writeable executable address space areas.
Rename as_area_t::size to as_area_t::pages.

Location:
generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • generic/include/mm/as.h

    re898a8d7 r37e7d2b9  
    6363        link_t link;
    6464        int flags;
    65         size_t size;            /**< Size of this area in multiples of PAGE_SIZE. */
     65        count_t pages;          /**< Size of this area in multiples of PAGE_SIZE. */
    6666        __address base;         /**< Base address of this area. */
    6767};
  • generic/src/lib/elf.c

    re898a8d7 r37e7d2b9  
    194194                segment = ((void *) elf) + entry->p_offset;
    195195
    196         a = as_area_create(as, flags, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
     196        a = as_area_create(as, flags, entry->p_memsz, entry->p_vaddr);
    197197        if (!a)
    198198                return EE_IRRECOVERABLE;
  • generic/src/mm/as.c

    re898a8d7 r37e7d2b9  
    7171static int get_area_flags(as_area_t *a);
    7272static as_area_t *find_area_and_lock(as_t *as, __address va);
     73static bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area);
    7374
    7475/** Initialize address space subsystem. */
     
    121122 * @param as Target address space.
    122123 * @param flags Flags of the area.
    123  * @param size Size of area in multiples of PAGE_SIZE.
     124 * @param size Size of area.
    124125 * @param base Base address of area.
    125126 *
     
    132133       
    133134        if (base % PAGE_SIZE)
    134                 panic("addr not aligned to a page boundary");
     135                return NULL;
     136
     137        /* Writeable executable areas are not supported. */
     138        if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
     139                return NULL;
    135140       
    136141        ipl = interrupts_disable();
    137142        spinlock_lock(&as->lock);
    138143       
    139         /*
    140          * TODO: test as_area which is to be created doesn't overlap with an existing one.
    141          */
     144        if (!check_area_conflicts(as, base, size, NULL)) {
     145                spinlock_unlock(&as->lock);
     146                interrupts_restore(ipl);
     147                return NULL;
     148        }
    142149       
    143150        a = (as_area_t *) malloc(sizeof(as_area_t), 0);
     
    147154        link_initialize(&a->link);                     
    148155        a->flags = flags;
    149         a->size = size;
     156        a->pages = SIZE2FRAMES(size);
    150157        a->base = base;
    151158       
     
    432439        if (!area) {
    433440                spinlock_unlock(&as->lock);
     441                interrupts_restore(ipl);
    434442                return (__address) -1;
    435443        }
    436444
    437445        pages = SIZE2FRAMES((address - area->base) + size);
    438         if (pages < area->size) {
     446        if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
     447                spinlock_unlock(&as->lock);
     448                interrupts_restore(ipl);
     449                return (__address) -1;
     450        }
     451
     452        if (pages < area->pages) {
    439453                int i;
    440454
     
    442456                 * Shrinking the area.
    443457                 */
    444                 for (i = pages; i < area->size; i++) {
     458                for (i = pages; i < area->pages; i++) {
    445459                        pte_t *pte;
    446460                       
     
    467481                 * Invalidate TLB's.
    468482                 */
    469                 tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
    470                 tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
     483                tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
     484                tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
    471485                tlb_shootdown_finalize();
    472486        }
    473487
    474         area->size = pages;
     488        area->pages = pages;
    475489       
    476490        spinlock_unlock(&area->lock);
     
    499513                spinlock_lock(&a->lock);
    500514
    501                 if ((va >= a->base) && (va < a->base + a->size * PAGE_SIZE))
    502                          return a;
     515                if ((va >= a->base) && (va < a->base + a->pages * PAGE_SIZE))
     516                        return a;
    503517               
    504518                spinlock_unlock(&a->lock);
     
    507521        return NULL;
    508522}
     523
     524/** Check area conflicts with other areas.
     525 *
     526 * The address space must be locked and interrupts must be disabled.
     527 *
     528 * @param as Address space.
     529 * @param va Starting virtual address of the area being tested.
     530 * @param size Size of the area being tested.
     531 * @param avoid_area Do not touch this area.
     532 *
     533 * @return True if there is no conflict, false otherwise.
     534 */
     535bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area)
     536{
     537        link_t *cur;
     538        as_area_t *a;
     539       
     540        for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
     541                __address start;
     542                __address end;
     543       
     544                a = list_get_instance(cur, as_area_t, link);
     545                if (a == avoid_area)
     546                        continue;
     547                       
     548                spinlock_lock(&a->lock);
     549
     550                start = a->base;
     551                end = a->base + a->pages * PAGE_SIZE - 1;
     552
     553                spinlock_unlock(&a->lock);
     554
     555                if ((va >= start) && (va <= end)) {
     556                        /*
     557                         * Tested area is inside another area.
     558                         */
     559                        return false;
     560                }
     561               
     562                if ((start >= va) && (start < va + size)) {
     563                        /*
     564                         * Another area starts in tested area.
     565                         */
     566                        return false;
     567                }
     568               
     569                if ((end >= va) && (end < va + size)) {
     570                        /*
     571                         * Another area ends in tested area.
     572                         */
     573                        return false;
     574                }
     575
     576        }
     577
     578        return true;
     579}
  • generic/src/proc/task.c

    re898a8d7 r37e7d2b9  
    126126         * Create the data as_area.
    127127         */
    128         a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE, 1, USTACK_ADDRESS);
     128        a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE, PAGE_SIZE, USTACK_ADDRESS);
    129129       
    130130        thread_ready(t);
Note: See TracChangeset for help on using the changeset viewer.