Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision d0485c6a1e50e0398bb04d70d1e1ed89ea3db22a)
+++ kernel/generic/src/mm/as.c	(revision 92778f2136ec900a873b76c69db8efbdb1998fea)
@@ -79,4 +79,8 @@
 #include <arch/interrupt.h>
 
+#ifdef CONFIG_VIRT_IDX_DCACHE
+#include <arch/mm/cache.h>
+#endif /* CONFIG_VIRT_IDX_DCACHE */
+
 /**
  * Each architecture decides what functions will be used to carry out
@@ -162,4 +166,9 @@
 	as->cpu_refcount = 0;
 	as->page_table = page_table_create(flags);
+
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	as->dcache_flush_on_install = false;
+	as->dcache_flush_on_deinstall = false;
+#endif	/* CONFIG_VIRT_IDX_DCACHE */
 
 	return as;
@@ -269,4 +278,16 @@
 	else
 		memsetb((uintptr_t) &a->backend_data, sizeof(a->backend_data), 0);
+
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	/*
+	 * When the area is being created with the AS_AREA_ATTR_PARTIAL flag, the
+	 * orig_color is probably wrong until the flag is reset. In other words, it is
+	 * initialized with the color of the area being created and not with the color
+	 * of the original address space area at the beginning of the share chain. Of
+	 * course, the correct color is set by as_area_share() before the flag is
+	 * reset.
+	 */
+	a->orig_color = PAGE_COLOR(base);
+#endif /* CONFIG_VIRT_IDX_DCACHE */
 
 	btree_create(&a->used_space);
@@ -555,7 +576,5 @@
  * or ENOMEM if there was a problem in allocating destination address space
  * area. ENOTSUP is returned if the address space area backend does not support
- * sharing. It can be also returned if the architecture uses virtually indexed
- * caches and the source and destination areas start at pages with different
- * page colors.
+ * sharing.
  */
 int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
@@ -565,4 +584,5 @@
 	int src_flags;
 	size_t src_size;
+	int src_orig_color;
 	as_area_t *src_area, *dst_area;
 	share_info_t *sh_info;
@@ -582,9 +602,9 @@
 	}
 	
-#if 0	/* disable the check for now */
-#ifdef CONFIG_VIRT_IDX_CACHE
-	if (PAGE_COLOR(src_area->base) != PAGE_COLOR(dst_base)) {
-		/*
-		 * Refuse to create illegal address alias.
+
+	if (!src_area->backend || !src_area->backend->share) {
+		/*
+		 * There is no backend or the backend does not
+		 * know how to share the area.
 		 */
 		mutex_unlock(&src_area->lock);
@@ -593,17 +613,4 @@
 		return ENOTSUP;
 	}
-#endif /* CONFIG_VIRT_IDX_CACHE */
-#endif
-
-	if (!src_area->backend || !src_area->backend->share) {
-		/*
-		 * There is no backend or the backend does not
-		 * know how to share the area.
-		 */
-		mutex_unlock(&src_area->lock);
-		mutex_unlock(&src_as->lock);
-		interrupts_restore(ipl);
-		return ENOTSUP;
-	}
 	
 	src_size = src_area->pages * PAGE_SIZE;
@@ -611,4 +618,5 @@
 	src_backend = src_area->backend;
 	src_backend_data = src_area->backend_data;
+	src_orig_color = src_area->orig_color;
 
 	/* Share the cacheable flag from the original mapping */
@@ -665,5 +673,5 @@
 		return ENOMEM;
 	}
-	
+
 	/*
 	 * Now the destination address space area has been
@@ -671,9 +679,31 @@
 	 * attribute and set the sh_info.
 	 */	
+	mutex_lock(&dst_as->lock);	
 	mutex_lock(&dst_area->lock);
 	dst_area->attributes &= ~AS_AREA_ATTR_PARTIAL;
 	dst_area->sh_info = sh_info;
+	dst_area->orig_color = src_orig_color;
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	if (src_orig_color != PAGE_COLOR(dst_base)) {
+		/*
+ 		 * We have just detected an attempt to create an invalid address
+ 		 * alias. We allow this and set a special flag that tells the
+ 		 * architecture specific code to flush the D-cache when the
+ 		 * offending address space is installed and deinstalled
+ 		 * (cleanup).
+ 		 *
+ 		 * In order for the flags to take effect immediately, we also
+ 		 * perform a global D-cache shootdown.
+ 		 */
+		dcache_shootdown_start();
+		dst_as->dcache_flush_on_install = true;
+		dst_as->dcache_flush_on_deinstall = true;
+		dcache_flush();
+		dcache_shootdown_finalize();
+	}
+#endif /* CONFIG_VIRT_IDX_DCACHE */
 	mutex_unlock(&dst_area->lock);
-	
+	mutex_unlock(&dst_as->lock);	
+
 	interrupts_restore(ipl);
 	
