Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 753 → Rev 754

/kernel/trunk/generic/include/mm/as.h
65,7 → 65,6
as_area_type_t type;
size_t size; /**< Size of this area in multiples of PAGE_SIZE. */
__address base; /**< Base address of this area. */
index_t *mapping; /**< Map of physical frame numbers mapped to virtual page numbers in this area. */
};
 
/** Address space structure.
76,7 → 75,7
* set up during system initialization.
*/
struct as {
/** Protected by asidlock. Must be acquired before as-> lock. */
/** Protected by asidlock. Must be acquired before as->lock. */
link_t as_with_asid_link;
 
SPINLOCK_DECLARE(lock);
87,7 → 86,7
 
extern as_t * as_create(pte_t *ptl0, int flags);
extern as_area_t *as_area_create(as_t *as, as_area_type_t type, size_t size, __address base);
extern void as_area_set_mapping(as_area_t *a, index_t vpn, index_t pfn);
extern void as_set_mapping(as_t *as, __address page, __address frame);
extern int as_page_fault(__address page);
extern void as_install(as_t *m);
 
/kernel/trunk/generic/src/main/kinit.c
71,8 → 71,9
thread_t *t;
as_t *as;
as_area_t *a;
index_t frame, frames;
index_t pfn;
__address frame;
count_t frames;
int i;
task_t *u;
 
interrupts_disable();
160,7 → 161,7
* Create the text as_area and copy the userspace code there.
*/
frame = KA2PA(config.init_addr) / FRAME_SIZE;
frame = KA2PA(config.init_addr);
frames = config.init_size / FRAME_SIZE;
if (config.init_size % FRAME_SIZE > 0)
frames++;
169,9 → 170,6
if (!a)
panic("as_area_create: text\n");
for (pfn = 0; pfn < frames; pfn++)
as_area_set_mapping(a, pfn, frame + pfn);
/*
* Create the data as_area.
*/
178,6 → 176,13
a = as_area_create(as, AS_AREA_STACK, 1, USTACK_ADDRESS);
if (!a)
panic("as_area_create: stack\n");
 
/*
* Initialize text area mapping.
*/
for (i = 0; i < frames; i++)
as_set_mapping(as, UTEXT_ADDRESS + i * PAGE_SIZE, frame + i * FRAME_SIZE);
 
thread_ready(t);
}
/kernel/trunk/generic/src/mm/as.c
59,13 → 59,7
#define KAS_END_INDEX PTL0_INDEX(KERNEL_ADDRESS_SPACE_END)
#define KAS_INDICES (1+(KAS_END_INDEX-KAS_START_INDEX))
 
/*
* Here we assume that PFN (Physical Frame Number) space
* is smaller than the width of index_t. UNALLOCATED_PFN
* can be then used to mark mappings wich were not
* yet allocated a physical frame.
*/
#define UNALLOCATED_PFN ((index_t) -1)
static int get_area_flags(as_area_t *a);
 
/** Create address space. */
/*
133,26 → 127,7
*/
a = (as_area_t *) malloc(sizeof(as_area_t));
if (a) {
int i;
a->mapping = (index_t *) malloc(size * sizeof(index_t));
if (!a->mapping) {
free(a);
spinlock_unlock(&as->lock);
interrupts_restore(ipl);
return NULL;
}
for (i=0; i<size; i++) {
/*
* Frames will be allocated on-demand by
* as_page_fault() or preloaded by
* as_area_set_mapping().
*/
a->mapping[i] = UNALLOCATED_PFN;
}
if (a) {
spinlock_initialize(&a->lock, "as_area_lock");
link_initialize(&a->link);
161,7 → 136,6
a->base = base;
list_append(&a->link, &as->as_area_head);
 
}
 
spinlock_unlock(&as->lock);
170,28 → 144,52
return a;
}
 
/** Load mapping for address space area.
/** Initialize mapping for one page of address space.
*
* Initialize a->mapping.
* This functions maps 'page' to 'frame' according
* to attributes of the address space area to
* wich 'page' belongs.
*
* @param a Target address space area.
* @param vpn Page number relative to area start.
* @param pfn Frame number to map.
* @param a Target address space.
* @param page Virtual page within the area.
* @param frame Physical frame to which page will be mapped.
*/
void as_area_set_mapping(as_area_t *a, index_t vpn, index_t pfn)
void as_set_mapping(as_t *as, __address page, __address frame)
{
ASSERT(vpn < a->size);
ASSERT(a->mapping[vpn] == UNALLOCATED_PFN);
ASSERT(pfn != UNALLOCATED_PFN);
as_area_t *a, *area = NULL;
link_t *cur;
ipl_t ipl;
ipl = interrupts_disable();
spinlock_lock(&a->lock);
spinlock_lock(&as->lock);
a->mapping[vpn] = pfn;
/*
* First, try locate an area.
*/
for (cur = as->as_area_head.next; cur != &as->as_area_head; cur = cur->next) {
a = list_get_instance(cur, as_area_t, link);
spinlock_lock(&a->lock);
 
if ((page >= a->base) && (page < a->base + a->size * PAGE_SIZE)) {
area = a;
break;
}
spinlock_unlock(&a->lock);
}
spinlock_unlock(&a->lock);
if (!area) {
panic("page not part of any as_area\n");
}
 
/*
* Note: area->lock is held.
*/
page_mapping_insert(page, as->asid, frame, get_area_flags(area), (__address) as->ptl0);
spinlock_unlock(&area->lock);
spinlock_unlock(&as->lock);
interrupts_restore(ipl);
}
 
206,10 → 204,8
*/
int as_page_fault(__address page)
{
int flags;
link_t *cur;
as_area_t *a, *area = NULL;
index_t vpn;
__address frame;
ASSERT(AS);
228,8 → 224,6
* We found the area containing 'page'.
* TODO: access checking
*/
vpn = (page - a->base) / PAGE_SIZE;
area = a;
break;
}
251,35 → 245,28
*/
/*
* Decide if a frame needs to be allocated.
* If so, allocate it and adjust area->mapping map.
* In general, there can be several reasons that
* can have caused this fault.
*
* - non-existent mapping: the area is a scratch
* area (e.g. stack) and so far has not been
* allocated a frame for the faulting page
*
* - non-present mapping: another possibility,
* currently not implemented, would be frame
* reuse; when this becomes a possibility,
* do not forget to distinguish between
* the different causes
*/
if (area->mapping[vpn] == UNALLOCATED_PFN) {
frame = frame_alloc(0, ONE_FRAME, NULL);
memsetb(PA2KA(frame), FRAME_SIZE, 0);
area->mapping[vpn] = frame / FRAME_SIZE;
ASSERT(area->mapping[vpn] != UNALLOCATED_PFN);
} else
frame = area->mapping[vpn] * FRAME_SIZE;
frame = frame_alloc(0, ONE_FRAME, NULL);
memsetb(PA2KA(frame), FRAME_SIZE, 0);
switch (area->type) {
case AS_AREA_TEXT:
flags = PAGE_EXEC | PAGE_READ | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
break;
case AS_AREA_DATA:
case AS_AREA_STACK:
flags = PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
break;
default:
panic("unexpected as_area_type_t %d", area->type);
}
 
/*
* Map 'page' to 'frame'.
* Note that TLB shootdown is not attempted as only new information is being
* inserted into page tables.
*/
page_mapping_insert(page, AS->asid, frame, flags, (__address) AS->ptl0);
page_mapping_insert(page, AS->asid, frame, get_area_flags(area), (__address) AS->ptl0);
spinlock_unlock(&area->lock);
spinlock_unlock(&AS->lock);
312,3 → 299,31
AS = as;
}
 
/** Compute flags for virtual address translation subsytem.
*
* The address space area must be locked.
* Interrupts must be disabled.
*
* @param a Address space area.
*
* @return Flags to be used in page_mapping_insert().
*/
int get_area_flags(as_area_t *a)
{
int flags;
 
switch (a->type) {
case AS_AREA_TEXT:
flags = PAGE_EXEC | PAGE_READ | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
break;
case AS_AREA_DATA:
case AS_AREA_STACK:
flags = PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_PRESENT | PAGE_CACHEABLE;
break;
default:
panic("unexpected as_area_type_t %d", a->type);
}
return flags;
}