Index: generic/include/mm/as.h
===================================================================
--- generic/include/mm/as.h	(revision a60c748773e33375d25f66224916e5a8e7733d35)
+++ generic/include/mm/as.h	(revision 6a3c9a77923487a0b7ff489449084ef0796d88ef)
@@ -66,5 +66,4 @@
 	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. */
 };
 
@@ -77,5 +76,5 @@
  */
 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;
 
@@ -88,5 +87,5 @@
 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);
Index: generic/src/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision a60c748773e33375d25f66224916e5a8e7733d35)
+++ generic/src/main/kinit.c	(revision 6a3c9a77923487a0b7ff489449084ef0796d88ef)
@@ -72,6 +72,7 @@
 	as_t *as;
 	as_area_t *a;
-	index_t frame, frames;
-	index_t pfn;
+	__address frame;
+	count_t frames;
+	int i;
 	task_t *u;
 
@@ -161,5 +162,5 @@
 		 */
 		
-		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)
@@ -170,7 +171,4 @@
 			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.
@@ -179,4 +177,11 @@
 		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);
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision a60c748773e33375d25f66224916e5a8e7733d35)
+++ generic/src/mm/as.c	(revision 6a3c9a77923487a0b7ff489449084ef0796d88ef)
@@ -60,11 +60,5 @@
 #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. */
@@ -134,24 +128,5 @@
 	
 	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");
 			
@@ -162,5 +137,4 @@
 		
 		list_append(&a->link, &as->as_area_head);
-
 	}
 
@@ -171,26 +145,50 @@
 }
 
-/** Load mapping for address space area.
- *
- * Initialize a->mapping.
- *
- * @param a   Target address space area.
- * @param vpn Page number relative to area start.
- * @param pfn Frame number to map.
- */
-void as_area_set_mapping(as_area_t *a, index_t vpn, index_t pfn)
-{
-	ASSERT(vpn < a->size);
-	ASSERT(a->mapping[vpn] == UNALLOCATED_PFN);
-	ASSERT(pfn != UNALLOCATED_PFN);
-	
+/** Initialize mapping for one page of address space.
+ *
+ * This functions maps 'page' to 'frame' according
+ * to attributes of the address space area to
+ * wich 'page' belongs.
+ *
+ * @param a Target address space.
+ * @param page Virtual page within the area.
+ * @param frame Physical frame to which page will be mapped.
+ */
+void as_set_mapping(as_t *as, __address page, __address frame)
+{
+	as_area_t *a, *area = NULL;
+	link_t *cur;
 	ipl_t ipl;
 	
 	ipl = interrupts_disable();
-	spinlock_lock(&a->lock);
-	
-	a->mapping[vpn] = pfn;
-	
-	spinlock_unlock(&a->lock);
+	spinlock_lock(&as->lock);
+	
+	/*
+	 * 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);
+	}
+	
+	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);
 }
@@ -207,8 +205,6 @@
 int as_page_fault(__address page)
 {
-	int flags;
 	link_t *cur;
 	as_area_t *a, *area = NULL;
-	index_t vpn;
 	__address frame;
 	
@@ -229,6 +225,4 @@
 			 * TODO: access checking
 			 */
-			
-			vpn = (page - a->base) / PAGE_SIZE;
 			area = a;
 			break;
@@ -252,16 +246,73 @@
 	
 	/*
-	 * Decide if a frame needs to be allocated.
-	 * If so, allocate it and adjust area->mapping map.
-	 */
-	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;
-	
-	switch (area->type) {
+	 * 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
+	 */
+	frame = frame_alloc(0, ONE_FRAME, NULL);
+	memsetb(PA2KA(frame), FRAME_SIZE, 0);
+	
+	/*
+	 * 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, get_area_flags(area), (__address) AS->ptl0);
+	
+	spinlock_unlock(&area->lock);
+	spinlock_unlock(&AS->lock);
+
+	return 1;
+}
+
+/** Install address space on CPU.
+ *
+ * @param as Address space.
+ */
+void as_install(as_t *as)
+{
+	ipl_t ipl;
+	
+	asid_install(as);
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&as->lock);
+	ASSERT(as->ptl0);
+	SET_PTL0_ADDRESS(as->ptl0);
+	spinlock_unlock(&as->lock);
+	interrupts_restore(ipl);
+
+	/*
+	 * Perform architecture-specific steps.
+	 * (e.g. write ASID to hardware register etc.)
+	 */
+	as_install_arch(as);
+	
+	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;
@@ -272,43 +323,7 @@
 			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);
-	
-	spinlock_unlock(&area->lock);
-	spinlock_unlock(&AS->lock);
-
-	return 1;
-}
-
-/** Install address space on CPU.
- *
- * @param as Address space.
- */
-void as_install(as_t *as)
-{
-	ipl_t ipl;
-	
-	asid_install(as);
-	
-	ipl = interrupts_disable();
-	spinlock_lock(&as->lock);
-	ASSERT(as->ptl0);
-	SET_PTL0_ADDRESS(as->ptl0);
-	spinlock_unlock(&as->lock);
-	interrupts_restore(ipl);
-
-	/*
-	 * Perform architecture-specific steps.
-	 * (e.g. write ASID to hardware register etc.)
-	 */
-	as_install_arch(as);
-	
-	AS = as;
-}
+			panic("unexpected as_area_type_t %d", a->type);
+	}
+	
+	return flags;
+}
