Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/arm32/src/arm32.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -58,5 +58,5 @@
 	size_t i;
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr = (uintptr_t) bootinfo->tasks[i].addr;
+		init.tasks[i].paddr = KA2PA(bootinfo->tasks[i].addr);
 		init.tasks[i].size = bootinfo->tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/ia64/src/ia64.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -69,10 +69,11 @@
 void arch_pre_main(void)
 {
-	init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
+	init.cnt = min3(bootinfo->taskmap.cnt, TASKMAP_MAX_RECORDS,
+	    CONFIG_INIT_TASKS);
 	size_t i;
+
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr =
-		    ((unsigned long) bootinfo->taskmap.tasks[i].addr) |
-		    VRN_MASK;
+		init.tasks[i].paddr =
+		    (uintptr_t) bootinfo->taskmap.tasks[i].addr;
 		init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/mips32/src/mips32.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -78,5 +78,5 @@
 	size_t i;
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr = (uintptr_t) bootinfo->tasks[i].addr;
+		init.tasks[i].paddr = KA2PA(bootinfo->tasks[i].addr);
 		init.tasks[i].size = bootinfo->tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/arch/mips32/src/mm/frame.c
===================================================================
--- kernel/arch/mips32/src/mm/frame.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/mips32/src/mm/frame.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -123,5 +123,5 @@
 	for (i = 0; i < init.cnt; i++)
 		if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
-		    KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
+		    init.tasks[i].paddr, init.tasks[i].size)) {
 			safe = false;
 			break;
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/ppc32/src/ppc32.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -71,5 +71,5 @@
 	size_t i;
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr = (uintptr_t) bootinfo->taskmap.tasks[i].addr;
+		init.tasks[i].paddr = KA2PA(bootinfo->taskmap.tasks[i].addr);
 		init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/arch/sparc64/src/sun4u/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sun4u/sparc64.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/sparc64/src/sun4u/sparc64.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -62,5 +62,5 @@
 	size_t i;
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr = (uintptr_t) bootinfo->taskmap.tasks[i].addr;
+		init.tasks[i].paddr = KA2PA(bootinfo->taskmap.tasks[i].addr);
 		init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/arch/sparc64/src/sun4v/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sun4v/sparc64.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/arch/sparc64/src/sun4v/sparc64.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -64,5 +64,5 @@
 	size_t i;
 	for (i = 0; i < init.cnt; i++) {
-		init.tasks[i].addr = (uintptr_t) bootinfo->taskmap.tasks[i].addr;
+		init.tasks[i].paddr = KA2PA(bootinfo->taskmap.tasks[i].addr);
 		init.tasks[i].size = bootinfo->taskmap.tasks[i].size;
 		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
Index: kernel/genarch/src/multiboot/multiboot.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -77,5 +77,5 @@
 			break;
 		
-		init.tasks[init.cnt].addr = PA2KA(mods[i].start);
+		init.tasks[init.cnt].paddr = mods[i].start;
 		init.tasks[init.cnt].size = mods[i].end - mods[i].start;
 		
Index: kernel/genarch/src/multiboot/multiboot2.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot2.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/genarch/src/multiboot/multiboot2.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -45,5 +45,5 @@
 {
 	if (init.cnt < CONFIG_INIT_TASKS) {
-		init.tasks[init.cnt].addr = PA2KA(module->start);
+		init.tasks[init.cnt].paddr = module->start;
 		init.tasks[init.cnt].size = module->end - module->start;
 		multiboot_extract_command(init.tasks[init.cnt].name,
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/include/config.h	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -53,5 +53,5 @@
 
 typedef struct {
-	uintptr_t addr;
+	uintptr_t paddr;
 	size_t size;
 	char name[CONFIG_TASK_NAME_BUFLEN];
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/src/lib/rd.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -54,5 +54,5 @@
 void init_rd(void *data, size_t size)
 {
-	uintptr_t base = KA2PA((uintptr_t) data);
+	uintptr_t base = (uintptr_t) data;
 	ASSERT((base % FRAME_SIZE) == 0);
 	
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/src/main/kinit.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -57,4 +57,5 @@
 #include <mm/as.h>
 #include <mm/frame.h>
+#include <mm/km.h>
 #include <print.h>
 #include <memstr.h>
@@ -68,4 +69,5 @@
 #include <str.h>
 #include <sysinfo/stats.h>
+#include <align.h>
 
 #ifdef CONFIG_SMP
@@ -178,5 +180,5 @@
 	
 	for (i = 0; i < init.cnt; i++) {
-		if (init.tasks[i].addr % FRAME_SIZE) {
+		if (init.tasks[i].paddr % FRAME_SIZE) {
 			printf("init[%zu]: Address is not frame aligned\n", i);
 			programs[i].task = NULL;
@@ -199,7 +201,24 @@
 		str_cpy(namebuf + INIT_PREFIX_LEN,
 		    TASK_NAME_BUFLEN - INIT_PREFIX_LEN, name);
-		
-		int rc = program_create_from_image((void *) init.tasks[i].addr,
-		    namebuf, &programs[i]);
+
+		/*
+		 * Create virtual memory mappings for init task images.
+		 */
+		size_t size = ALIGN_UP(init.tasks[i].size, PAGE_SIZE);
+		size_t offs;
+		uintptr_t page = km_page_alloc(size, PAGE_SIZE);
+		uintptr_t frame = init.tasks[i].paddr;
+
+		page_table_lock(AS_KERNEL, true);
+		for (offs = 0; offs < size; offs += PAGE_SIZE) {
+			page_mapping_insert(AS_KERNEL, page + offs,
+			    frame + offs,
+			    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE |
+			    PAGE_PRESENT);
+		}
+		page_table_unlock(AS_KERNEL, true);
+		
+		int rc = program_create_from_image((void *) page, namebuf,
+		    &programs[i]);
 		
 		if (rc == 0) {
@@ -224,5 +243,5 @@
 			 * Assume the last task is the RAM disk.
 			 */
-			init_rd((void *) init.tasks[i].addr, init.tasks[i].size);
+			init_rd((void *) frame, init.tasks[i].size);
 		} else
 			printf("init[%zu]: Init binary load failed (error %d)\n", i, rc);
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/src/main/main.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -151,8 +151,15 @@
 	size_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 (overlaps(KA2PA(config.stack_base), config.stack_size,
+		    init.tasks[i].paddr, init.tasks[i].size)) {
+			/*
+			 * The init task overlaps with the memory behind the
+			 * kernel image so it must be in low memory and we can
+			 * use PA2KA on the init task's physical address.
+			 */
+			config.stack_base = ALIGN_UP(
+			    PA2KA(init.tasks[i].paddr) + init.tasks[i].size,
+			    config.stack_size);
+		}
 	}
 	
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/src/mm/backend_elf.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -318,5 +318,11 @@
 			dirty = true;
 		} else {
-			frame = KA2PA(base + i * FRAME_SIZE);
+			pte_t *pte = page_mapping_find(AS_KERNEL,
+			    base + i * FRAME_SIZE, true);
+
+			ASSERT(pte);
+			ASSERT(PTE_PRESENT(pte));
+
+			frame = PTE_GET_FRAME(pte);
 		}	
 	} else if (upage >= start_anon) {
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 7943c43ec7446695410d2e5521eb8121555e8c0c)
+++ kernel/generic/src/mm/frame.c	(revision 32817cc7228ed0a4db98be9cb5f00757af3d7e2c)
@@ -924,5 +924,5 @@
 				for (i = 0; i < init.cnt; i++)
 					if (overlaps(addr, PFN2ADDR(confcount),
-					    KA2PA(init.tasks[i].addr),
+					    init.tasks[i].paddr,
 					    init.tasks[i].size)) {
 						overlap = true;
@@ -1251,5 +1251,5 @@
 		size_t i;
 		for (i = 0; i < init.cnt; i++) {
-			pfn_t pfn = ADDR2PFN(KA2PA(init.tasks[i].addr));
+			pfn_t pfn = ADDR2PFN(init.tasks[i].paddr);
 			frame_mark_unavailable(pfn,
 			    SIZE2FRAMES(init.tasks[i].size));
