Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision 2299914109fe20b32a7226821981f5eb11a8394a)
+++ generic/src/mm/as.c	(revision 37c57f29513b54c8a95f330fce386b8a26dffa7e)
@@ -71,4 +71,5 @@
 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. */
@@ -121,5 +122,5 @@
  * @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.
  *
@@ -132,12 +133,18 @@
 	
 	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);
@@ -147,5 +154,5 @@
 	link_initialize(&a->link);			
 	a->flags = flags;
-	a->size = size;
+	a->pages = SIZE2FRAMES(size);
 	a->base = base;
 	
@@ -432,9 +439,16 @@
 	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;
 
@@ -442,5 +456,5 @@
 		 * Shrinking the area.
 		 */
-		for (i = pages; i < area->size; i++) {
+		for (i = pages; i < area->pages; i++) {
 			pte_t *pte;
 			
@@ -467,10 +481,10 @@
 		 * 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);
@@ -499,6 +513,6 @@
 		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);
@@ -507,2 +521,59 @@
 	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;
+}
