Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1047 → Rev 1048

/kernel/trunk/generic/include/mm/as.h
62,7 → 62,7
SPINLOCK_DECLARE(lock);
link_t link;
int flags;
size_t size; /**< Size of this area in multiples of PAGE_SIZE. */
count_t pages; /**< Size of this area in multiples of PAGE_SIZE. */
__address base; /**< Base address of this area. */
};
 
/kernel/trunk/generic/src/proc/task.c
125,7 → 125,7
/*
* Create the data as_area.
*/
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE, 1, USTACK_ADDRESS);
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE, PAGE_SIZE, USTACK_ADDRESS);
thread_ready(t);
 
/kernel/trunk/generic/src/lib/elf.c
193,7 → 193,7
} else /* Map identically original data */
segment = ((void *) elf) + entry->p_offset;
 
a = as_area_create(as, flags, SIZE2FRAMES(entry->p_memsz), entry->p_vaddr);
a = as_area_create(as, flags, entry->p_memsz, entry->p_vaddr);
if (!a)
return EE_IRRECOVERABLE;
/kernel/trunk/generic/src/mm/as.c
70,6 → 70,7
 
static int get_area_flags(as_area_t *a);
static as_area_t *find_area_and_lock(as_t *as, __address va);
static bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area);
 
/** Initialize address space subsystem. */
void as_init(void)
120,7 → 121,7
*
* @param as Target address space.
* @param flags Flags of the area.
* @param size Size of area in multiples of PAGE_SIZE.
* @param size Size of area.
* @param base Base address of area.
*
* @return Address space area on success or NULL on failure.
131,14 → 132,20
as_area_t *a;
if (base % PAGE_SIZE)
panic("addr not aligned to a page boundary");
return NULL;
 
/* Writeable executable areas are not supported. */
if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
return NULL;
ipl = interrupts_disable();
spinlock_lock(&as->lock);
/*
* TODO: test as_area which is to be created doesn't overlap with an existing one.
*/
if (!check_area_conflicts(as, base, size, NULL)) {
spinlock_unlock(&as->lock);
interrupts_restore(ipl);
return NULL;
}
a = (as_area_t *) malloc(sizeof(as_area_t), 0);
 
146,7 → 153,7
link_initialize(&a->link);
a->flags = flags;
a->size = size;
a->pages = SIZE2FRAMES(size);
a->base = base;
list_append(&a->link, &as->as_area_head);
431,17 → 438,24
area = find_area_and_lock(as, address);
if (!area) {
spinlock_unlock(&as->lock);
interrupts_restore(ipl);
return (__address) -1;
}
 
pages = SIZE2FRAMES((address - area->base) + size);
if (pages < area->size) {
if (!check_area_conflicts(as, address, pages * PAGE_SIZE, area)) {
spinlock_unlock(&as->lock);
interrupts_restore(ipl);
return (__address) -1;
}
 
if (pages < area->pages) {
int i;
 
/*
* Shrinking the area.
*/
for (i = pages; i < area->size; i++) {
for (i = pages; i < area->pages; i++) {
pte_t *pte;
/*
466,12 → 480,12
/*
* Invalidate TLB's.
*/
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->size - pages);
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
tlb_invalidate_pages(AS->asid, area->base + pages*PAGE_SIZE, area->pages - pages);
tlb_shootdown_finalize();
}
 
area->size = pages;
area->pages = pages;
spinlock_unlock(&area->lock);
spinlock_unlock(&as->lock);
498,8 → 512,8
a = list_get_instance(cur, as_area_t, link);
spinlock_lock(&a->lock);
 
if ((va >= a->base) && (va < a->base + a->size * PAGE_SIZE))
return a;
if ((va >= a->base) && (va < a->base + a->pages * PAGE_SIZE))
return a;
spinlock_unlock(&a->lock);
}
506,3 → 520,60
 
return NULL;
}
 
/** Check area conflicts with other areas.
*
* The address space must be locked and interrupts must be disabled.
*
* @param as Address space.
* @param va Starting virtual address of the area being tested.
* @param size Size of the area being tested.
* @param avoid_area Do not touch this area.
*
* @return True if there is no conflict, false otherwise.
*/
bool check_area_conflicts(as_t *as, __address va, size_t size, as_area_t *avoid_area)
{
link_t *cur;
as_area_t *a;
for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
__address start;
__address end;
a = list_get_instance(cur, as_area_t, link);
if (a == avoid_area)
continue;
spinlock_lock(&a->lock);
 
start = a->base;
end = a->base + a->pages * PAGE_SIZE - 1;
 
spinlock_unlock(&a->lock);
 
if ((va >= start) && (va <= end)) {
/*
* Tested area is inside another area.
*/
return false;
}
if ((start >= va) && (start < va + size)) {
/*
* Another area starts in tested area.
*/
return false;
}
if ((end >= va) && (end < va + size)) {
/*
* Another area ends in tested area.
*/
return false;
}
 
}
 
return true;
}