Index: arch/amd64/src/dummy.s
===================================================================
--- arch/amd64/src/dummy.s	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/amd64/src/dummy.s	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -29,4 +29,5 @@
 .text
 
+.global memcopy
 .global cpu_priority_high
 .global cpu_priority_low
@@ -54,4 +55,5 @@
 .global dummy
 
+memcopy:
 cpu_priority_high:
 cpu_priority_low:
Index: arch/ia32/src/drivers/ega.c
===================================================================
--- arch/ia32/src/drivers/ega.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/ia32/src/drivers/ega.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -30,4 +30,5 @@
 #include <putchar.h>
 #include <mm/page.h>
+#include <arch/mm/page.h>
 #include <synch/spinlock.h>
 #include <arch/types.h>
Index: arch/ia32/src/mm/page.c
===================================================================
--- arch/ia32/src/mm/page.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/ia32/src/mm/page.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -37,13 +37,4 @@
 #include <synch/spinlock.h>
 #include <debug.h>
-
-/*
- * Note.
- * This is the preliminary code for controlling paging mechanism on ia32. It is
- * needed by other parts of the kernel for its ability to map virtual addresses
- * to physical. SMP code relies on this feature. Other than that, this code is
- * by no means meant to implement virtual memory in terms of swapping pages in
- * and out.
- */
 
 __address bootstrap_dba; 
Index: arch/ia32/src/pm.c
===================================================================
--- arch/ia32/src/pm.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/ia32/src/pm.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -35,4 +35,5 @@
 #include <arch/context.h>
 #include <panic.h>
+#include <arch/mm/page.h>
 
 /*
@@ -132,7 +133,7 @@
 static void clean_IOPL_NT_flags(void)
 {
-  asm
+	asm
 	(
-    "pushfl;"
+		"pushfl;"
 		"pop %%eax;"
 		"and $0xffff8fff,%%eax;"
@@ -148,7 +149,7 @@
 static void clean_AM_flag(void)
 {
-  asm
+	asm
 	(
-    "mov %%cr0,%%eax;"
+		"mov %%cr0,%%eax;"
 		"and $0xFFFBFFFF,%%eax;"
 		"mov %%eax,%%cr0;"
@@ -158,8 +159,4 @@
 	);
 }
-
-
-
-
 
 void pm_init(void)
Index: arch/ia32/src/proc/scheduler.c
===================================================================
--- arch/ia32/src/proc/scheduler.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/ia32/src/proc/scheduler.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -35,4 +35,4 @@
 {
 	CPU->arch.tss->esp0 = (__address) &THREAD->kstack[THREAD_STACK_SIZE-8];
-	CPU->arch.tss->ss0 = selector(KDATA_DES);	
+	CPU->arch.tss->ss0 = selector(KDATA_DES);
 }
Index: arch/ppc/src/dummy.s
===================================================================
--- arch/ppc/src/dummy.s	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ arch/ppc/src/dummy.s	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -29,4 +29,5 @@
 .text
 
+.global memcopy
 .global cpu_priority_high
 .global cpu_priority_low
@@ -51,4 +52,5 @@
 .global dummy
 
+memcopy:
 cpu_priority_high:
 cpu_priority_low:
Index: include/mm/page.h
===================================================================
--- include/mm/page.h	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ include/mm/page.h	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -107,6 +107,4 @@
 #define SET_FRAME_FLAGS(ptl3, i, x)	SET_FRAME_FLAGS_ARCH(ptl3, i, x)
 
-#include <arch/mm/page.h>
-
 extern void page_init(void);
 extern void map_page_to_frame(__address page, __address frame, int flags, __address root);
Index: include/mm/vm.h
===================================================================
--- include/mm/vm.h	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ include/mm/vm.h	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -77,5 +77,5 @@
 };
 
-extern vm_t * vm_create(void);
+extern vm_t * vm_create(pte_t *ptl0);
 extern void vm_destroy(vm_t *m);
 
@@ -83,6 +83,6 @@
 extern void vm_area_destroy(vm_area_t *a);
 
-extern void vm_area_map(vm_area_t *a);
-extern void vm_area_unmap(vm_area_t *a);
+extern void vm_area_map(vm_area_t *a, vm_t *m);
+extern void vm_area_unmap(vm_area_t *a, vm_t *m);
 
 extern void vm_install(vm_t *m);
Index: src/main/kinit.c
===================================================================
--- src/main/kinit.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ src/main/kinit.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -119,5 +119,5 @@
 	 * Create the first user task.
 	 */
-	m = vm_create();
+	m = vm_create(NULL);
 	if (!m)	panic("vm_create");
 	u = task_create(m);
@@ -131,4 +131,5 @@
 	a = vm_area_create(m, VMA_TEXT, 1, UTEXT_ADDRESS);
 	if (!a) panic("vm_area_create: vm_text");
+	vm_area_map(a, m);
 	memcopy((__address) utext, PA2KA(a->mapping[0]), utext_size < PAGE_SIZE ? utext_size : PAGE_SIZE);
 
@@ -138,4 +139,5 @@
 	a = vm_area_create(m, VMA_STACK, 1, USTACK_ADDRESS);
 	if (!a) panic("vm_area_create: vm_stack");
+	vm_area_map(a, m);	
 	
 	thread_ready(t);
Index: src/main/main.c
===================================================================
--- src/main/main.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ src/main/main.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -150,5 +150,5 @@
 	 * Create kernel vm mapping.
 	 */
-	m = vm_create();
+	m = vm_create(GET_PTL0_ADDRESS());
 	if (!m) panic("can't create kernel vm address space\n");
 
Index: src/mm/vm.c
===================================================================
--- src/mm/vm.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ src/mm/vm.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -40,6 +40,11 @@
 #include <panic.h>
 #include <arch/asm.h>
+#include <debug.h>
 
-vm_t *vm_create(void)
+#define KAS_START_INDEX		PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)
+#define KAS_END_INDEX		PTL0_INDEX(KERNEL_ADDRESS_SPACE_END)
+#define KAS_INDICES		(1+(KAS_END_INDEX-KAS_START_INDEX))
+
+vm_t *vm_create(pte_t *ptl0)
 {
 	vm_t *m;
@@ -49,5 +54,18 @@
 		spinlock_initialize(&m->lock);
 		list_initialize(&m->vm_area_head);
-		m->ptl0 = NULL;
+
+		/*
+		 * Each vm_t is supposed to have its own page table.
+		 * It is either passed one or it has to allocate and set one up.
+		 */
+		if (!(m->ptl0 = ptl0)) {
+			pte_t *src_ptl0, *dst_ptl0;
+		
+			src_ptl0 = (pte_t *) PA2KA(GET_PTL0_ADDRESS());
+			dst_ptl0 = (pte_t *) frame_alloc(FRAME_KA | FRAME_PANIC);
+			memsetb((__address) dst_ptl0, PAGE_SIZE, 0);
+			memcopy((__address) &src_ptl0[KAS_START_INDEX], (__address) &dst_ptl0[KAS_START_INDEX], KAS_INDICES*sizeof(pte_t));
+			m->ptl0 = (pte_t *) KA2PA(dst_ptl0);
+		}
 	}
 	
@@ -110,5 +128,5 @@
 }
 
-void vm_area_map(vm_area_t *a)
+void vm_area_map(vm_area_t *a, vm_t *m)
 {
 	int i, flags;
@@ -116,4 +134,5 @@
 	
 	pri = cpu_priority_high();
+	spinlock_lock(&m->lock);
 	spinlock_lock(&a->lock);
 
@@ -127,15 +146,17 @@
 			break;
 		default:
-			panic("unexpected vm_type_t %d", a->type); 
+			panic("unexpected vm_type_t %d", a->type);
 	}
-	
+
+	ASSERT(m->ptl0);
 	for (i=0; i<a->size; i++)
-		map_page_to_frame(a->address + i*PAGE_SIZE, a->mapping[i], flags, 0);
+		map_page_to_frame(a->address + i*PAGE_SIZE, a->mapping[i], flags, (__address) m->ptl0);
 		
 	spinlock_unlock(&a->lock);
+	spinlock_unlock(&m->lock);
 	cpu_priority_restore(pri);
 }
 
-void vm_area_unmap(vm_area_t *a)
+void vm_area_unmap(vm_area_t *a, vm_t *m)
 {
 	int i;
@@ -143,10 +164,13 @@
 	
 	pri = cpu_priority_high();
+	spinlock_lock(&m->lock);
 	spinlock_lock(&a->lock);
 
+	ASSERT(m->ptl0);
 	for (i=0; i<a->size; i++)		
-		map_page_to_frame(a->address + i*PAGE_SIZE, 0, PAGE_NOT_PRESENT, 0);
+		map_page_to_frame(a->address + i*PAGE_SIZE, 0, PAGE_NOT_PRESENT, (__address) m->ptl0);
 	
 	spinlock_unlock(&a->lock);
+	spinlock_unlock(&m->lock);
 	cpu_priority_restore(pri);
 }
@@ -158,29 +182,12 @@
 	
 	pri = cpu_priority_high();
+
+	tlb_shootdown_start();
 	spinlock_lock(&m->lock);
 
-	for(l = m->vm_area_head.next; l != &m->vm_area_head; l = l->next)
-		vm_area_map(list_get_instance(l, vm_area_t, link));
+	ASSERT(m->ptl0);
+	SET_PTL0_ADDRESS(m->ptl0);
 
 	spinlock_unlock(&m->lock);
-	cpu_priority_restore(pri);
-}
-
-void vm_uninstall(vm_t *m)
-{
-	link_t *l;
-	pri_t pri;
-	
-	pri = cpu_priority_high();
-
-	tlb_shootdown_start();
-
-	spinlock_lock(&m->lock);
-
-	for(l = m->vm_area_head.next; l != &m->vm_area_head; l = l->next)
-		vm_area_unmap(list_get_instance(l, vm_area_t, link));
-
-	spinlock_unlock(&m->lock);
-
 	tlb_shootdown_finalize();
 
Index: src/proc/scheduler.c
===================================================================
--- src/proc/scheduler.c	(revision 6a4177a1237ca725e81e02acf6e04bb1b931e68c)
+++ src/proc/scheduler.c	(revision b07769b60d28ebef7ed6f9ae8366f444e8ecc7fa)
@@ -381,7 +381,4 @@
 			 * Replace the old one with the new one.
 			 */
-			if (m1) {
-				vm_uninstall(m1);
-			}
 			vm_install(m2);
 		}
