Index: kernel/arch/ia32/src/drivers/ega.c
===================================================================
--- kernel/arch/ia32/src/drivers/ega.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/ia32/src/drivers/ega.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -47,4 +47,5 @@
 #include <console/console.h>
 #include <sysinfo/sysinfo.h>
+#include <ddi/ddi.h>
 
 /*
@@ -52,4 +53,6 @@
  * Simple and short. Function for displaying characters and "scrolling".
  */
+
+static parea_t ega_parea;	/**< Physical memory area for EGA video RAM. */
 
 SPINLOCK_INITIALIZE(egalock);
@@ -80,4 +83,10 @@
 	stdout = &ega_console;
 	
+	ega_parea.pbase = VIDEORAM;
+	ega_parea.vbase = (uintptr_t) videoram;
+	ega_parea.frames = 1;
+	ega_parea.cacheable = false;
+	ddi_parea_register(&ega_parea);
+
 	sysinfo_set_item_val("fb", NULL, true);
 	sysinfo_set_item_val("fb.kind", NULL, 2);
@@ -85,4 +94,6 @@
 	sysinfo_set_item_val("fb.height", NULL, ROWS);
 	sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM);
+	sysinfo_set_item_val("fb.address.color", NULL, PAGE_COLOR((uintptr_t)
+		videoram));
 	
 #ifndef CONFIG_FB
Index: kernel/arch/sparc64/include/interrupt.h
===================================================================
--- kernel/arch/sparc64/include/interrupt.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/include/interrupt.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -48,6 +48,5 @@
 
 enum {
-	IPI_TLB_SHOOTDOWN = VECTOR_TLB_SHOOTDOWN_IPI,
-	IPI_DCACHE_SHOOTDOWN
+	IPI_TLB_SHOOTDOWN = VECTOR_TLB_SHOOTDOWN_IPI
 };		
 
Index: kernel/arch/sparc64/include/mm/cache.h
===================================================================
--- kernel/arch/sparc64/include/mm/cache.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/include/mm/cache.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -36,14 +36,4 @@
 #define KERN_sparc64_CACHE_H_
 
-#ifdef CONFIG_SMP
-extern void dcache_shootdown_start(void);
-extern void dcache_shootdown_finalize(void);
-extern void dcache_shootdown_ipi_recv(void);
-#else /* CONFIG_SMP */
-#define dcache_shootdown_start();
-#define dcache_shootdown_finalize();
-#define dcache_shootdown_ipi_recv();
-#endif /* CONFIG_SMP */
-
 extern void dcache_flush(void);
 
Index: kernel/arch/sparc64/src/mm/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/as.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/src/mm/as.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -49,8 +49,4 @@
 #include <macros.h>
 #endif /* CONFIG_TSB */
-
-#ifdef CONFIG_VIRT_IDX_DCACHE
-#include <arch/mm/cache.h>
-#endif /* CONFIG_VIRT_IDX_DCACHE */
 
 /** Architecture dependent address space init. */
@@ -163,21 +159,4 @@
 	dtsb_base_write(tsb_base.value);
 #endif
-#ifdef CONFIG_VIRT_IDX_DCACHE
-	if (as->dcache_flush_on_install) {
-		/*
-		 * Some mappings in this address space are illegal address
-		 * aliases. Upon their creation, the dcache_flush_on_install
-		 * flag was set.
-		 *
-		 * We are now obliged to flush the D-cache in order to guarantee
-		 * that there will be at most one cache line for each address
-		 * alias.
-		 *
-		 * This flush performs a cleanup after another address space in
-		 * which the alias might have existed.
-		 */
-		dcache_flush();
-	}
-#endif /* CONFIG_VIRT_IDX_DCACHE */
 }
 
@@ -214,24 +193,4 @@
 	}
 #endif
-#ifdef CONFIG_VIRT_IDX_DCACHE
-	if (as->dcache_flush_on_deinstall) {
-		/*
-		 * Some mappings in this address space are illegal address
-		 * aliases. Upon their creation, the dcache_flush_on_deinstall
-		 * flag was set.
-		 *
-		 * We are now obliged to flush the D-cache in order to guarantee
-		 * that there will be at most one cache line for each address
-		 * alias.
-		 *
-		 * This flush performs a cleanup after this address space. It is
-		 * necessary because other address spaces that contain the same
-		 * alias are not necessarily aware of the need to carry out the
-		 * cache flush. The only address spaces that are aware of it are
-		 * those that created the illegal alias. 
-		 */
-		dcache_flush();
-	}
-#endif /* CONFIG_VIRT_IDX_DCACHE */
 }
 
Index: kernel/arch/sparc64/src/mm/cache.c
===================================================================
--- kernel/arch/sparc64/src/mm/cache.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/src/mm/cache.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -32,66 +32,8 @@
 /**
  * @file
- * @brief	D-cache shootdown algorithm.
  */
 
 #include <arch/mm/cache.h>
 
-#ifdef CONFIG_SMP
-
-#include <smp/ipi.h>
-#include <arch/interrupt.h>
-#include <synch/spinlock.h>
-#include <arch.h>
-#include <debug.h>
-
-/**
- * This spinlock is used by the processors to synchronize during the D-cache
- * shootdown.
- */
-SPINLOCK_INITIALIZE(dcachelock);
-
-/** Initialize the D-cache shootdown sequence.
- *
- * Start the shootdown sequence by sending out an IPI and wait until all
- * processors spin on the dcachelock spinlock.
- */
-void dcache_shootdown_start(void)
-{
-	int i;
-
-	CPU->arch.dcache_active = 0;
-	spinlock_lock(&dcachelock);
-
-	ipi_broadcast(IPI_DCACHE_SHOOTDOWN);	
-
-busy_wait:
-	for (i = 0; i < config.cpu_count; i++)
-		if (cpus[i].arch.dcache_active)
-			goto busy_wait;
-}
-
-/** Finish the D-cache shootdown sequence. */
-void dcache_shootdown_finalize(void)
-{
-	spinlock_unlock(&dcachelock);
-	CPU->arch.dcache_active = 1;
-}
-
-/** Process the D-cache shootdown IPI. */
-void dcache_shootdown_ipi_recv(void)
-{
-	ASSERT(CPU);
-
-	CPU->arch.dcache_active = 0;
-	spinlock_lock(&dcachelock);
-	spinlock_unlock(&dcachelock);
-	
-	dcache_flush();
-
-	CPU->arch.dcache_active = 1;
-}
-
-#endif /* CONFIG_SMP */
-
 /** @}
  */
Index: kernel/arch/sparc64/src/mm/page.c
===================================================================
--- kernel/arch/sparc64/src/mm/page.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/src/mm/page.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -74,6 +74,7 @@
 		for (i = 0; i < bsp_locked_dtlb_entries; i++) {
 			dtlb_insert_mapping(bsp_locked_dtlb_entry[i].virt_page,
-				bsp_locked_dtlb_entry[i].phys_page, bsp_locked_dtlb_entry[i].pagesize_code,
-				true, false);
+				bsp_locked_dtlb_entry[i].phys_page,
+				bsp_locked_dtlb_entry[i].pagesize_code,	true,
+				false);
 		}
 #endif	
@@ -152,7 +153,10 @@
 		 * Second, save the information about the mapping for APs.
 		 */
-		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].virt_page = virtaddr + i*sizemap[order].increment;
-		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].phys_page = physaddr + i*sizemap[order].increment;
-		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].pagesize_code = sizemap[order].pagesize_code;
+		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].virt_page =
+			virtaddr + i*sizemap[order].increment;
+		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].phys_page =
+			physaddr + i*sizemap[order].increment;
+		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].pagesize_code =
+			sizemap[order].pagesize_code;
 		bsp_locked_dtlb_entries++;
 #endif
Index: kernel/arch/sparc64/src/smp/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/ipi.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/src/smp/ipi.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -39,5 +39,4 @@
 #include <config.h>
 #include <mm/tlb.h>
-#include <arch/mm/cache.h>
 #include <arch/interrupt.h>
 #include <arch/trap/interrupt.h>
@@ -122,7 +121,4 @@
 		func = tlb_shootdown_ipi_recv;
 		break;
-	case IPI_DCACHE_SHOOTDOWN:
-		func = dcache_shootdown_ipi_recv;
-		break;
 	default:
 		panic("Unknown IPI (%d).\n", ipi);
Index: kernel/arch/sparc64/src/trap/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/interrupt.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/arch/sparc64/src/trap/interrupt.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -45,5 +45,4 @@
 #include <arch.h>
 #include <mm/tlb.h>
-#include <arch/mm/cache.h>
 #include <config.h>
 #include <synch/spinlock.h>
@@ -92,6 +91,4 @@
 		if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
 			tlb_shootdown_ipi_recv();
-		} else if (data0 == (uintptr_t) dcache_shootdown_ipi_recv) {
-			dcache_shootdown_ipi_recv();
 		}
 #endif
Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/genarch/src/fb/fb.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -46,6 +46,9 @@
 #include <bitops.h>
 #include <print.h>
+#include <ddi/ddi.h>
 
 #include "helenos.xbm"
+
+static parea_t fb_parea;		/**< Physical memory area for fb. */
 
 SPINLOCK_INITIALIZE(fb_lock);
@@ -435,4 +438,10 @@
 	columns = x / COL_WIDTH;
 
+	fb_parea.pbase = (uintptr_t) addr;
+	fb_parea.vbase = (uintptr_t) fbaddress;
+	fb_parea.frames = SIZE2FRAMES(fbsize);
+	fb_parea.cacheable = false;
+	ddi_parea_register(&fb_parea);
+
 	sysinfo_set_item_val("fb", NULL, true);
 	sysinfo_set_item_val("fb.kind", NULL, 1);
@@ -442,4 +451,6 @@
 	sysinfo_set_item_val("fb.visual", NULL, visual);
 	sysinfo_set_item_val("fb.address.physical", NULL, addr);
+	sysinfo_set_item_val("fb.address.color", NULL, PAGE_COLOR((uintptr_t)
+		fbaddress));
 	sysinfo_set_item_val("fb.invert-colors", NULL, invert_colors);
 
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/include/ddi/ddi.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -40,6 +40,17 @@
 #include <typedefs.h>
 
-unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t pages, 
-			 unative_t flags);
+/** Structure representing contiguous physical memory area. */
+typedef struct {
+	uintptr_t pbase;	/**< Physical base of the area. */
+	uintptr_t vbase;	/**< Virtual base of the area. */
+	count_t frames;		/**< Number of frames in the area. */
+	bool cacheable;		/**< Cacheability. */
+} parea_t;
+
+extern void ddi_init(void);
+extern void ddi_parea_register(parea_t *parea);
+
+extern unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
+	unative_t pages, unative_t flags);
 extern unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg);
 extern unative_t sys_preempt_control(int enable);
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/include/mm/as.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -95,9 +95,4 @@
 	asid_t asid;
 	
-#ifdef CONFIG_VIRT_IDX_DCACHE
-	bool dcache_flush_on_install;
-	bool dcache_flush_on_deinstall;
-#endif /* CONFIG_VIRT_IDX_DCACHE */
-
 	/** Architecture specific content. */
 	as_arch_t arch;
@@ -166,10 +161,4 @@
 	/** Data to be used by the backend. */
 	mem_backend_data_t backend_data;
-
-	/** 
-	 * Virtual color of the original address space area that was at the beginning
-	 * of the share chain.
-	 */
-	int orig_color; 
 };
 
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/include/mm/page.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -71,5 +71,5 @@
  * Macro for computing page color.
  */
-#define PAGE_COLOR(va)		(((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1))
+#define PAGE_COLOR(va)	(((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1))
 
 /** Page fault access type. */
@@ -83,5 +83,6 @@
 /** Operations to manipulate page mappings. */
 struct page_mapping_operations {
-	void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame, int flags);
+	void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame, int
+		flags);
 	void (* mapping_remove)(as_t *as, uintptr_t page);
 	pte_t *(* mapping_find)(as_t *as, uintptr_t page);
@@ -94,5 +95,6 @@
 extern void page_table_lock(as_t *as, bool lock);
 extern void page_table_unlock(as_t *as, bool unlock);
-extern void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int flags);
+extern void page_mapping_insert(as_t *as, uintptr_t page, uintptr_t frame, int
+	flags);
 extern void page_mapping_remove(as_t *as, uintptr_t page);
 extern pte_t *page_mapping_find(as_t *as, uintptr_t page);
Index: kernel/generic/src/console/klog.c
===================================================================
--- kernel/generic/src/console/klog.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/console/klog.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -39,11 +39,15 @@
 #include <ddi/device.h>
 #include <ddi/irq.h>
+#include <ddi/ddi.h>
 #include <ipc/irq.h>
 
+/** Physical memory area used for klog. */
+static parea_t klog_parea;
+	
 /*
  * For now, we use 0 as INR.
- * However, on some architectures 0 is the clock interrupt (e.g. amd64 and ia32).
- * It is therefore desirable to have architecture specific definition of KLOG_VIRT_INR
- * in the future.
+ * However, on some architectures 0 is the clock interrupt (e.g. amd64 and
+ * ia32). It is therefore desirable to have architecture specific definition of
+ * KLOG_VIRT_INR in the future.
  */
 #define KLOG_VIRT_INR	0
@@ -76,9 +80,17 @@
 	if (!faddr)
 		panic("Cannot allocate page for klog");
-	klog = (char *)PA2KA(faddr);
+	klog = (char *) PA2KA(faddr);
 	
 	devno_t devno = device_assign_devno();
 	
-	sysinfo_set_item_val("klog.faddr", NULL, (unative_t)faddr);
+	klog_parea.pbase = (uintptr_t) faddr;
+	klog_parea.vbase = (uintptr_t) klog;
+	klog_parea.frames = 1 << KLOG_ORDER;
+	klog_parea.cacheable = true;
+	ddi_parea_register(&klog_parea);
+
+	sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr);
+	sysinfo_set_item_val("klog.fcolor", NULL, (unative_t)
+		PAGE_COLOR((uintptr_t) klog));
 	sysinfo_set_item_val("klog.pages", NULL, 1 << KLOG_ORDER);
 	sysinfo_set_item_val("klog.devno", NULL, devno);
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/ddi/ddi.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -48,18 +48,58 @@
 #include <synch/spinlock.h>
 #include <syscall/copy.h>
+#include <adt/btree.h>
 #include <arch.h>
 #include <align.h>
 #include <errno.h>
 
+/** This lock protects the parea_btree. */
+SPINLOCK_INITIALIZE(parea_lock);
+
+/** B+tree with enabled physical memory areas. */
+static btree_t parea_btree;
+
+/** Initialize DDI. */
+void ddi_init(void)
+{
+	btree_create(&parea_btree);
+}
+
+/** Enable piece of physical memory for mapping by physmem_map().
+ *
+ * @param parea Pointer to physical area structure.
+ *
+ * @todo This function doesn't check for overlaps. It depends on the kernel to
+ * create disjunct physical memory areas.
+ */
+void ddi_parea_register(parea_t *parea)
+{
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&parea_lock);
+	
+	/*
+	 * TODO: we should really check for overlaps here.
+	 * However, we should be safe because the kernel is pretty sane and
+	 * memory of different devices doesn't overlap. 
+	 */
+	btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
+
+	spinlock_unlock(&parea_lock);
+	interrupts_restore(ipl);	
+}
+
 /** Map piece of physical memory into virtual address space of current task.
  *
- * @param pf Physical frame address of the starting frame.
- * @param vp Virtual page address of the starting page.
+ * @param pf Physical address of the starting frame.
+ * @param vp Virtual address of the starting page.
  * @param pages Number of pages to map.
  * @param flags Address space area flags for the mapping.
  *
- * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
- *	   ENOENT if there is no task matching the specified ID and ENOMEM if
- *	   there was a problem in creating address space area.
+ * @return 0 on success, EPERM if the caller lacks capabilities to use this
+ * 	syscall, ENOENT if there is no task matching the specified ID or the
+ * 	physical address space is not enabled for mapping and ENOMEM if there
+ * 	was a problem in creating address space area. ENOTSUP is returned when
+ * 	an attempt to create an illegal address alias is detected.
  */
 static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
@@ -80,4 +120,38 @@
 
 	ipl = interrupts_disable();
+
+	/*
+	 * Check if the physical memory area is enabled for mapping.
+	 * If the architecture supports virtually indexed caches, intercept
+	 * attempts to create an illegal address alias.
+	 */
+	spinlock_lock(&parea_lock);
+	parea_t *parea;
+	btree_node_t *nodep;
+	parea = btree_search(&parea_btree, (btree_key_t) pf, &nodep);
+	if (!parea || parea->frames < pages || ((flags & AS_AREA_CACHEABLE) &&
+		!parea->cacheable) || (!(flags & AS_AREA_CACHEABLE) &&
+		parea->cacheable)) {
+		/*
+		 * This physical memory area cannot be mapped.
+		 */
+		spinlock_unlock(&parea_lock);
+		interrupts_restore(ipl);
+		return ENOENT;
+	}
+
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	if (PAGE_COLOR(parea->vbase) != PAGE_COLOR(vp)) {
+		/*
+		 * Refuse to create an illegal address alias.
+		 */
+		spinlock_unlock(&parea_lock);
+		interrupts_restore(ipl);
+		return ENOTSUP;
+	}
+#endif /* CONFIG_VIRT_IDX_DCACHE */
+
+	spinlock_unlock(&parea_lock);
+
 	spinlock_lock(&TASK->lock);
 	
@@ -108,6 +182,6 @@
  * @param size Size of the enabled I/O space..
  *
- * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
- *	   ENOENT if there is no task matching the specified ID.
+ * @return 0 on success, EPERM if the caller lacks capabilities to use this
+ * 	syscall, ENOENT if there is no task matching the specified ID.
  */
 static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
@@ -161,10 +235,10 @@
  * @return 0 on success, otherwise it returns error code found in errno.h
  */ 
-unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t pages, 
-			 unative_t flags)
-{
-	return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base, FRAME_SIZE),
-					  ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE), (count_t) pages,
-					  (int) flags);
+unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t
+	pages, unative_t flags)
+{
+	return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
+		FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
+		(count_t) pages, (int) flags);
 }
 
@@ -184,12 +258,13 @@
 		return (unative_t) rc;
 		
-	return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id, (uintptr_t) arg.ioaddr, (size_t) arg.size);
+	return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
+		(uintptr_t) arg.ioaddr, (size_t) arg.size);
 }
 
 /** Disable or enable preemption.
  *
- * @param enable If non-zero, the preemption counter will be decremented, leading to potential
- * 		 enabling of preemption. Otherwise the preemption counter will be incremented,
- *		 preventing preemption from occurring.
+ * @param enable If non-zero, the preemption counter will be decremented,
+ * 	leading to potential enabling of preemption. Otherwise the preemption
+ * 	counter will be incremented, preventing preemption from occurring.
  *
  * @return Zero on success or EPERM if callers capabilities are not sufficient.
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/lib/rd.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -42,9 +42,13 @@
 #include <mm/frame.h>
 #include <sysinfo/sysinfo.h>
+#include <ddi/ddi.h>
+
+static parea_t rd_parea;		/**< Physical memory area for rd. */
 
 int init_rd(rd_header * header, size_t size)
 {
 	/* Identify RAM disk */
-	if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) || (header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
+	if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) ||
+		(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
 		return RE_INVALID;
 	
@@ -77,7 +81,16 @@
 		dsize = size - hsize;
 	
+	rd_parea.pbase = KA2PA((void *) header + hsize);
+	rd_parea.vbase = (uintptr_t) ((void *) header + hsize);
+	rd_parea.frames = SIZE2FRAMES(dsize);
+	rd_parea.cacheable = true;
+	ddi_parea_register(&rd_parea);
+
 	sysinfo_set_item_val("rd", NULL, true);
 	sysinfo_set_item_val("rd.size", NULL, dsize);
-	sysinfo_set_item_val("rd.address.physical", NULL, (unative_t) KA2PA((void *) header + hsize));
+	sysinfo_set_item_val("rd.address.physical", NULL, (unative_t)
+		KA2PA((void *) header + hsize));
+	sysinfo_set_item_val("rd.address.color", NULL, (unative_t)
+		PAGE_COLOR((uintptr_t) header + hsize));
 
 	return RE_OK;
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/main/main.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -81,4 +81,5 @@
 #include <console/klog.h>
 #include <smp/smp.h>
+#include <ddi/ddi.h>
 
 /** Global configuration structure. */
@@ -103,9 +104,12 @@
  * appropriate sizes and addresses.
  */
-uintptr_t hardcoded_load_address = 0;	/**< Virtual address of where the kernel is loaded. */
-size_t hardcoded_ktext_size = 0;	/**< Size of the kernel code in bytes. */
-size_t hardcoded_kdata_size = 0;	/**< Size of the kernel data in bytes. */
-
-uintptr_t stack_safe = 0;		/**< Lowest safe stack virtual address */
+uintptr_t hardcoded_load_address = 0;	/**< Virtual address of where the kernel
+					  *  is loaded. */
+size_t hardcoded_ktext_size = 0;	/**< Size of the kernel code in bytes.
+					  */
+size_t hardcoded_kdata_size = 0;	/**< Size of the kernel data in bytes.
+					 */
+uintptr_t stack_safe = 0;		/**< Lowest safe stack virtual address.
+					  */
 
 void main_bsp(void);
@@ -142,5 +146,6 @@
 	config.memory_size = get_memory_size();
 	
-	config.kernel_size = ALIGN_UP(hardcoded_ktext_size + hardcoded_kdata_size, PAGE_SIZE);
+	config.kernel_size = ALIGN_UP(hardcoded_ktext_size +
+		hardcoded_kdata_size, PAGE_SIZE);
 	config.stack_size = CONFIG_STACK_SIZE;
 	
@@ -151,12 +156,16 @@
 	count_t i;
 	for (i = 0; i < init.cnt; i++) {
-		if (PA_overlaps(config.stack_base, config.stack_size, init.tasks[i].addr, init.tasks[i].size))
-			config.stack_base = ALIGN_UP(init.tasks[i].addr + init.tasks[i].size, config.stack_size);
+		if (PA_overlaps(config.stack_base, config.stack_size,
+			init.tasks[i].addr, init.tasks[i].size))
+			config.stack_base = ALIGN_UP(init.tasks[i].addr +
+				init.tasks[i].size, config.stack_size);
 	}
 
 	/* Avoid placing stack on top of boot allocations. */
 	if (ballocs.size) {
-		if (PA_overlaps(config.stack_base, config.stack_size, ballocs.base, ballocs.size))
-			config.stack_base = ALIGN_UP(ballocs.base + ballocs.size, PAGE_SIZE);
+		if (PA_overlaps(config.stack_base, config.stack_size,
+			ballocs.base, ballocs.size))
+			config.stack_base = ALIGN_UP(ballocs.base +
+				ballocs.size, PAGE_SIZE);
 	}
 	
@@ -165,5 +174,6 @@
 	
 	context_save(&ctx);
-	context_set(&ctx, FADDR(main_bsp_separated_stack), config.stack_base, THREAD_STACK_SIZE);
+	context_set(&ctx, FADDR(main_bsp_separated_stack), config.stack_base,
+		THREAD_STACK_SIZE);
 	context_restore(&ctx);
 	/* not reached */
@@ -201,5 +211,6 @@
 	 */	
 	arch_pre_mm_init();
-	frame_init();		/* Initialize at least 1 memory segment big enough for slab to work */
+	frame_init();		
+	/* Initialize at least 1 memory segment big enough for slab to work. */
 	slab_cache_init();
 	btree_init();
@@ -207,14 +218,19 @@
 	page_init();
 	tlb_init();
+	ddi_init();
 	arch_post_mm_init();
 
 	version_print();
-	printf("kernel: %.*p hardcoded_ktext_size=%zdK, hardcoded_kdata_size=%zdK\n", sizeof(uintptr_t) * 2, config.base, hardcoded_ktext_size >> 10, hardcoded_kdata_size >> 10);
-	printf("stack:  %.*p size=%zdK\n", sizeof(uintptr_t) * 2, config.stack_base, config.stack_size >> 10);
+	printf("kernel: %.*p hardcoded_ktext_size=%zdK, "
+		"hardcoded_kdata_size=%zdK\n", sizeof(uintptr_t) * 2,
+		config.base, hardcoded_ktext_size >> 10, hardcoded_kdata_size >>
+		10);
+	printf("stack:  %.*p size=%zdK\n", sizeof(uintptr_t) * 2,
+		config.stack_base, config.stack_size >> 10);
 
 	arch_pre_smp_init();
 	smp_init();
-	
-	slab_enable_cpucache();	/* Slab must be initialized AFTER we know the number of processors */
+	/* Slab must be initialized after we know the number of processors. */
+	slab_enable_cpucache();
 
 	printf("config.memory_size=%zdM\n", config.memory_size >> 20);
@@ -233,5 +249,7 @@
 	if (init.cnt > 0) {
 		for (i = 0; i < init.cnt; i++)
-			printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i, sizeof(uintptr_t) * 2, init.tasks[i].addr, i, init.tasks[i].size);
+			printf("init[%zd].addr=%.*p, init[%zd].size=%zd\n", i,
+				sizeof(uintptr_t) * 2, init.tasks[i].addr, i,
+				init.tasks[i].size);
 	} else
 		printf("No init binaries found\n");
@@ -305,5 +323,6 @@
 	 * switch to this cpu's private stack prior to waking kmp up.
 	 */
-	context_set(&CPU->saved_context, FADDR(main_ap_separated_stack), (uintptr_t) CPU->stack, CPU_STACK_SIZE);
+	context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
+		(uintptr_t) CPU->stack, CPU_STACK_SIZE);
 	context_restore(&CPU->saved_context);
 	/* not reached */
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/mm/as.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -167,9 +167,4 @@
 	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;
 }
@@ -278,16 +273,4 @@
 	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);
@@ -576,5 +559,6 @@
  * 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.
+ * sharing or if the kernel detects an attempt to create an illegal address
+ * alias.
  */
 int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
@@ -584,5 +568,4 @@
 	int src_flags;
 	size_t src_size;
-	int src_orig_color;
 	as_area_t *src_area, *dst_area;
 	share_info_t *sh_info;
@@ -601,5 +584,4 @@
 		return ENOENT;
 	}
-	
 
 	if (!src_area->backend || !src_area->backend->share) {
@@ -618,5 +600,4 @@
 	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 */
@@ -630,4 +611,18 @@
 		return EPERM;
 	}
+
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	if (!(dst_flags_mask & AS_AREA_EXEC)) {
+		if (PAGE_COLOR(src_area->base) != PAGE_COLOR(dst_base)) {
+			/*
+			 * Refuse to create an illegal address alias.
+			 */
+			mutex_unlock(&src_area->lock);
+			mutex_unlock(&src_as->lock);
+			interrupts_restore(ipl);
+			return ENOTSUP;
+		}
+	}
+#endif /* CONFIG_VIRT_IDX_DCACHE */
 
 	/*
@@ -683,24 +678,4 @@
 	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);	
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -231,19 +231,22 @@
 		
 		switch (root->val_type) {
-			case SYSINFO_VAL_UNDEFINED:
-				val = 0;
-				vtype = "UND";
-				break;
-			case SYSINFO_VAL_VAL:
-				val = root->val.val;
-				vtype = "VAL";
-				break;
-			case SYSINFO_VAL_FUNCTION:
-				val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
-				vtype = "FUN";
-				break;
+		case SYSINFO_VAL_UNDEFINED:
+			val = 0;
+			vtype = "UND";
+			break;
+		case SYSINFO_VAL_VAL:
+			val = root->val.val;
+			vtype = "VAL";
+			break;
+		case SYSINFO_VAL_FUNCTION:
+			val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
+			vtype = "FUN";
+			break;
 		}
 		
-		printf("%s    %s val:%d(%x) sub:%s\n", root->name, vtype, val, val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ? "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ? "TAB" : "FUN"));
+		printf("%s    %s val:%d(%x) sub:%s\n", root->name, vtype, val,
+			val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
+			"NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
+			"TAB" : "FUN"));
 		
 		if (root->subinfo_type == SYSINFO_SUBINFO_TABLE)
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ kernel/generic/src/time/clock.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -55,4 +55,9 @@
 #include <sysinfo/sysinfo.h>
 #include <arch/barrier.h>
+#include <mm/frame.h>
+#include <ddi/ddi.h>
+
+/** Physical memory area of the real time clock. */
+static parea_t clock_parea;
 
 /* Pointers to public variables with time */
@@ -73,6 +78,4 @@
  * information about realtime data. We allocate 1 page with these 
  * data and update it periodically.
- *
- * 
  */
 void clock_counter_init(void)
@@ -80,9 +83,9 @@
 	void *faddr;
 
-	faddr = frame_alloc(0, FRAME_ATOMIC);
+	faddr = frame_alloc(ONE_FRAME, FRAME_ATOMIC);
 	if (!faddr)
 		panic("Cannot allocate page for clock");
 	
-	public_time = (struct ptime *)PA2KA(faddr);
+	public_time = (struct ptime *) PA2KA(faddr);
 
         /* TODO: We would need some arch dependent settings here */
@@ -91,5 +94,18 @@
 	public_time->useconds = 0; 
 
-	sysinfo_set_item_val("clock.faddr", NULL, (unative_t)faddr);
+	clock_parea.pbase = (uintptr_t) faddr;
+	clock_parea.vbase = (uintptr_t) public_time;
+	clock_parea.frames = 1;
+	clock_parea.cacheable = true;
+	ddi_parea_register(&clock_parea);
+
+	/*
+	 * Prepare information for the userspace so that it can successfully
+	 * physmem_map() the clock_parea.
+	 */
+	sysinfo_set_item_val("clock.cacheable", NULL, (unative_t) true);
+	sysinfo_set_item_val("clock.fcolor", NULL, (unative_t)
+		PAGE_COLOR(clock_parea.vbase));
+	sysinfo_set_item_val("clock.faddr", NULL, (unative_t) faddr);
 }
 
Index: uspace/fb/ega.c
===================================================================
--- uspace/fb/ega.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/fb/ega.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -35,5 +35,4 @@
  */
 
-
 #include <stdlib.h>
 #include <unistd.h>
@@ -63,5 +62,4 @@
 saved_screen saved_screens[MAX_SAVED_SCREENS];
 
-
 #define EGA_IO_ADDRESS 0x3d4
 #define EGA_IO_SIZE 2
@@ -127,10 +125,12 @@
 	int i;
 	if (rows > 0) {
-		memcpy (scr_addr,((char *)scr_addr) + rows * scr_width * 2, scr_width * scr_height * 2 - rows * scr_width * 2);
+		memcpy (scr_addr,((char *)scr_addr) + rows * scr_width * 2,
+			scr_width * scr_height * 2 - rows * scr_width * 2);
 		for (i = 0; i < rows * scr_width ; i ++)
-			(((short *)scr_addr) + scr_width * scr_height - rows * scr_width) [i] = ((style << 8) + ' ');
+			(((short *)scr_addr) + scr_width * scr_height - rows *
+				scr_width) [i] = ((style << 8) + ' ');
 	} else if (rows < 0) {
-
-		memcpy (((char *)scr_addr) - rows * scr_width * 2 ,scr_addr ,scr_width * scr_height * 2 + rows * scr_width * 2);
+		memcpy (((char *)scr_addr) - rows * scr_width * 2, scr_addr,
+			scr_width * scr_height * 2 + rows * scr_width * 2);
 		for (i = 0; i < - rows * scr_width ; i++)
 			((short *)scr_addr) [i] = ((style << 8 ) + ' ');
@@ -309,11 +309,12 @@
 	scr_width=sysinfo_value("fb.width");
 	scr_height=sysinfo_value("fb.height");
-	iospace_enable(task_get_id(),(void *)EGA_IO_ADDRESS,2);
-
-	sz = scr_width*scr_height*2;
-	scr_addr = as_get_mappable_page(sz);
-
-	physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >> PAGE_WIDTH,
-		    AS_AREA_READ | AS_AREA_WRITE);
+	iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2);
+
+	sz = scr_width * scr_height * 2;
+	scr_addr = as_get_mappable_page(sz, (int)
+		sysinfo_value("fb.address.color"));
+
+	physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
+		PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
 
 	async_set_client_connection(ega_client_connection);
Index: uspace/fb/fb.c
===================================================================
--- uspace/fb/fb.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/fb/fb.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -705,7 +705,8 @@
 		/* We accept one area for data interchange */
 		if (IPC_GET_ARG1(*call) == shm_id) {
-			void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
+			void *dest = as_get_mappable_page(IPC_GET_ARG2(*call),
+				PAGE_COLOR(IPC_GET_ARG1(*call)));
 			shm_size = IPC_GET_ARG2(*call);
-			if (!ipc_answer_fast(callid, 0, (sysarg_t)dest, 0)) 
+			if (!ipc_answer_fast(callid, 0, (sysarg_t) dest, 0)) 
 				shm = dest;
 			else
@@ -717,5 +718,5 @@
 		} else {
 			intersize = IPC_GET_ARG2(*call);
-			receive_comm_area(callid,call,(void *)&interbuffer);
+			receive_comm_area(callid, call, (void *) &interbuffer);
 		}
 		return 1;
@@ -1283,10 +1284,11 @@
 
 	asz = fb_scanline * fb_height;
-	fb_addr = as_get_mappable_page(asz);
+	fb_addr = as_get_mappable_page(asz, (int) sysinfo_value("fb.address.color"));
 	
 	physmem_map(fb_ph_addr, fb_addr, ALIGN_UP(asz, PAGE_SIZE) >> PAGE_WIDTH,
 		    AS_AREA_READ | AS_AREA_WRITE);
 
-	if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual, fb_invert_colors))
+	if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual,
+		fb_invert_colors))
 		return 0;
 	
Index: uspace/fb/main.c
===================================================================
--- uspace/fb/main.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/fb/main.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -44,5 +44,6 @@
 	void *dest;
 
-	dest = as_get_mappable_page(IPC_GET_ARG2(*call));
+	dest = as_get_mappable_page(IPC_GET_ARG2(*call),
+		PAGE_COLOR(IPC_GET_ARG1(*call)));
 	if (ipc_answer_fast(callid, 0, (sysarg_t)dest, 0) == 0) {
 		if (*area)
Index: uspace/klog/klog.c
===================================================================
--- uspace/klog/klog.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/klog/klog.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -64,8 +64,8 @@
 	printf("Kernel console output.\n");
 	
-	mapping = as_get_mappable_page(PAGE_SIZE);
+	mapping = as_get_mappable_page(PAGE_SIZE, sysinfo_value("klog.fcolor"));
 	res = ipc_call_sync_3(PHONE_NS, IPC_M_AS_AREA_RECV, 
-			      (sysarg_t)mapping, PAGE_SIZE, SERVICE_MEM_KLOG,
-			      NULL,NULL,NULL);
+			      (sysarg_t) mapping, PAGE_SIZE, SERVICE_MEM_KLOG,
+			      NULL, NULL, NULL);
 	if (res) {
 		printf("Failed to initialize klog memarea\n");
Index: uspace/libc/arch/amd64/include/config.h
===================================================================
--- uspace/libc/arch/amd64/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/amd64/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	12
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/ia32/include/config.h
===================================================================
--- uspace/libc/arch/ia32/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/ia32/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	12
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/ia64/include/config.h
===================================================================
--- uspace/libc/arch/ia64/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/ia64/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	14
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/mips32/include/config.h
===================================================================
--- uspace/libc/arch/mips32/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/mips32/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	14
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/ppc32/include/config.h
===================================================================
--- uspace/libc/arch/ppc32/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/ppc32/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	12
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/ppc64/include/config.h
===================================================================
--- uspace/libc/arch/ppc64/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/ppc64/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	12
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	0		/* dummy */
 
 #endif
Index: uspace/libc/arch/sparc64/include/config.h
===================================================================
--- uspace/libc/arch/sparc64/include/config.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/arch/sparc64/include/config.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #define PAGE_WIDTH	13
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
+#define PAGE_COLOR_BITS	1		/**< Bit 13 is the page color. */
 
 #endif
Index: uspace/libc/generic/as.c
===================================================================
--- uspace/libc/generic/as.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/generic/as.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -38,4 +38,5 @@
 #include <align.h>
 #include <types.h>
+#include <bitops.h>
 
 /**
@@ -54,10 +55,12 @@
 void *as_area_create(void *address, size_t size, int flags)
 {
-	return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t ) address, (sysarg_t) size, (sysarg_t) flags);
+	return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t ) address,
+		(sysarg_t) size, (sysarg_t) flags);
 }
 
 /** Resize address space area.
  *
- * @param address Virtual address pointing into already existing address space area.
+ * @param address Virtual address pointing into already existing address space
+ * 	area.
  * @param size New requested size of the area.
  * @param flags Currently unused.
@@ -67,10 +70,12 @@
 int as_area_resize(void *address, size_t size, int flags)
 {
-	return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t ) address, (sysarg_t) size, (sysarg_t) flags);
+	return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t ) address, (sysarg_t)
+		size, (sysarg_t) flags);
 }
 
 /** Destroy address space area.
  *
- * @param address Virtual address pointing into the address space area being destroyed.
+ * @param address Virtual address pointing into the address space area being
+ * 	destroyed.
  *
  * @return Zero on success or a code from @ref errno.h on failure.
@@ -134,15 +139,27 @@
 	/* Return pointer to area not managed by sbrk */
 	return ((void *) &_heap + maxheapsize);
-
 }
 
 /** Return pointer to some unmapped area, where fits new as_area
  *
+ * @param sz Requested size of the allocation.
+ * @param color Requested virtual color of the allocation.
+ *
+ * @return Pointer to the beginning 
+ *
  * TODO: make some first_fit/... algorithm, we are now just incrementing
  *       the pointer to last area
  */
-void * as_get_mappable_page(size_t sz)
+#include <stdio.h>
+void *as_get_mappable_page(size_t sz, int color)
 {
 	void *res;
+	uint64_t asz;
+	int i;
+	
+	if (!sz)
+		return NULL;	
+
+	asz = 1 << (fnzb64(sz - 1) + 1);
 
 	/* Set heapsize to some meaningful value */
@@ -150,10 +167,23 @@
 		set_maxheapsize(MAX_HEAP_SIZE);
 	
-	if (!last_allocated)
-		last_allocated = (void *) ALIGN_UP((void *) &_heap + maxheapsize, PAGE_SIZE);
-	
-	sz = ALIGN_UP(sz, PAGE_SIZE);
+	/*
+	 * Make sure we allocate from naturally aligned address and a page of
+	 * appropriate color.
+	 */
+	i = 0;
+	do {
+		if (!last_allocated) {
+			last_allocated = (void *) ALIGN_UP((void *) &_heap +
+				maxheapsize, asz);
+		} else {
+			last_allocated = (void *) ALIGN_UP(((uintptr_t)
+				last_allocated) + (int) (i > 0), asz);
+		}
+	} while ((asz < (1 << (PAGE_COLOR_BITS + PAGE_WIDTH))) &&
+		(PAGE_COLOR((uintptr_t) last_allocated) != color) &&
+		(++i < (1 << PAGE_COLOR_BITS)));
+
 	res = last_allocated;
-	last_allocated += sz;
+	last_allocated += ALIGN_UP(sz, PAGE_SIZE);
 
 	return res;
Index: uspace/libc/generic/mman.c
===================================================================
--- uspace/libc/generic/mman.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/generic/mman.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -40,5 +40,5 @@
 {
 	if (!start)
-		start = as_get_mappable_page(length);
+		start = as_get_mappable_page(length, 0);
 	
 //	if (! ((flags & MAP_SHARED) ^ (flags & MAP_PRIVATE)))
Index: uspace/libc/generic/time.c
===================================================================
--- uspace/libc/generic/time.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/generic/time.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -41,4 +41,5 @@
 #include <atomic.h>
 #include <futex.h>
+#include <sysinfo.h>
 #include <ipc/services.h>
 
@@ -72,7 +73,10 @@
 
 	if (!ktime) {
-		mapping = as_get_mappable_page(PAGE_SIZE);
+		mapping = as_get_mappable_page(PAGE_SIZE, (int)
+			sysinfo_value("clock.fcolor"));
 		/* Get the mapping of kernel clock */
-		res = ipc_call_sync_3(PHONE_NS, IPC_M_AS_AREA_RECV, (sysarg_t) mapping, PAGE_SIZE, SERVICE_MEM_REALTIME, NULL, &rights, NULL);
+		res = ipc_call_sync_3(PHONE_NS, IPC_M_AS_AREA_RECV, (sysarg_t)
+			mapping, PAGE_SIZE, SERVICE_MEM_REALTIME, NULL, &rights,
+			NULL);
 		if (res) {
 			printf("Failed to initialize timeofday memarea\n");
Index: uspace/libc/include/as.h
===================================================================
--- uspace/libc/include/as.h	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/libc/include/as.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -40,4 +40,7 @@
 #include <kernel/arch/mm/as.h>
 #include <kernel/mm/as.h>
+#include <libarch/config.h>
+
+#define PAGE_COLOR(va)	(((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1))
 
 extern void *as_area_create(void *address, size_t size, int flags);
@@ -45,5 +48,5 @@
 extern int as_area_destroy(void *address);
 extern void *set_maxheapsize(size_t mhs);
-extern void * as_get_mappable_page(size_t sz);
+extern void * as_get_mappable_page(size_t sz, int color);
 
 #endif
Index: uspace/libc/include/bitops.h
===================================================================
--- uspace/libc/include/bitops.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
+++ uspace/libc/include/bitops.h	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_BITOPS_H_
+#define LIBC_BITOPS_H_
+
+#include <types.h>
+
+
+/** Return position of first non-zero bit from left (i.e. [log_2(arg)]).
+ *
+ * If number is zero, it returns 0
+ */
+static inline int fnzb32(uint32_t arg)
+{
+	int n = 0;
+
+	if (arg >> 16) {
+		arg >>= 16;
+		n += 16;
+	}
+	
+	if (arg >> 8) {
+		arg >>= 8;
+		n += 8;
+	}
+	
+	if (arg >> 4) {
+		arg >>= 4;
+		n += 4;
+	}
+	
+	if (arg >> 2) {
+		arg >>= 2;
+		n += 2;
+	}
+	
+	if (arg >> 1) {
+		arg >>= 1;
+		n += 1;
+	}
+	
+	return n;
+}
+
+static inline int fnzb64(uint64_t arg)
+{
+	int n = 0;
+
+	if (arg >> 32) {
+		arg >>= 32;
+		n += 32;
+	}
+	
+	return n + fnzb32((uint32_t) arg);
+}
+
+#define fnzb(x) fnzb32(x)
+
+#endif
+
+/** @}
+ */
Index: uspace/ns/ns.c
===================================================================
--- uspace/ns/ns.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/ns/ns.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -84,15 +84,17 @@
 static void *klogaddr = NULL;
 
-static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, void **addr)
+static void get_as_area(ipc_callid_t callid, ipc_call_t *call, char *name, char *colstr, void **addr)
 {
 	void *ph_addr;
+	int ph_color;
 
 	if (!*addr) {
-		ph_addr = (void *)sysinfo_value(name);
+		ph_addr = (void *) sysinfo_value(name);
 		if (!ph_addr) {
 			ipc_answer_fast(callid, ENOENT, 0, 0);
 			return;
 		}
-		*addr = as_get_mappable_page(PAGE_SIZE);
+		ph_color = (int) sysinfo_value(colstr);
+		*addr = as_get_mappable_page(PAGE_SIZE, ph_color);
 		physmem_map(ph_addr, *addr, 1, AS_AREA_READ | AS_AREA_CACHEABLE);
 	}
@@ -117,8 +119,10 @@
 			switch (IPC_GET_ARG3(call)) {
 			case SERVICE_MEM_REALTIME:
-				get_as_area(callid, &call, "clock.faddr", &clockaddr);
+				get_as_area(callid, &call, "clock.faddr",
+					"clock.fcolor", &clockaddr);
 				break;
 			case SERVICE_MEM_KLOG:
-				get_as_area(callid, &call, "klog.faddr", &klogaddr);
+				get_as_area(callid, &call, "klog.faddr",
+					"klog.fcolor", &klogaddr);
 				break;
 			default:
Index: uspace/rd/rd.c
===================================================================
--- uspace/rd/rd.c	(revision 9ab9c2ec85cf371e50f3b815722f6586f78add5b)
+++ uspace/rd/rd.c	(revision f8ddd176406660da88b0e9d63695413731cd58ff)
@@ -74,9 +74,10 @@
 	size_t rd_size = sysinfo_value("rd.size");
 	void * rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
+	int rd_color = (int) sysinfo_value("rd.address.color");
 	
 	if (rd_size == 0)
 		return false;
 	
-	void * rd_addr = as_get_mappable_page(rd_size);
+	void * rd_addr = as_get_mappable_page(rd_size, rd_color);
 	
 	physmem_map(rd_ph_addr, rd_addr, ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
