Index: kernel/generic/src/console/klog.c
===================================================================
--- kernel/generic/src/console/klog.c	(revision 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/console/klog.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/ddi/ddi.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/lib/rd.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/main/main.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/mm/as.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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 5a8b2a2e58c0aff599e30b00eed3a773ff644968)
+++ kernel/generic/src/time/clock.c	(revision 8cd140f26dd9503acc9c3b85b265d95ff017cea4)
@@ -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);
 }
 
