Index: kernel/arch/sparc32/include/arch/arch.h
===================================================================
--- kernel/arch/sparc32/include/arch/arch.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/arch.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -38,5 +39,29 @@
 #ifndef __ASM__
 
-void arch_pre_main(void);
+#include <typedefs.h>
+
+/* ASI assignments: */
+#define	ASI_CACHEMISS	0x01
+#define	ASI_CACHECTRL	0x02
+#define	ASI_MMUREGS	0x19
+#define	ASI_MMUBYPASS	0x1c
+
+#define TASKMAP_MAX_RECORDS  32
+#define CPUMAP_MAX_RECORDS   32
+
+#define BOOTINFO_TASK_NAME_BUFLEN 32
+
+typedef struct {
+	void *addr;
+	size_t size;
+	char name[BOOTINFO_TASK_NAME_BUFLEN];
+} utask_t;
+
+typedef struct {
+	size_t cnt;
+	utask_t tasks[TASKMAP_MAX_RECORDS];
+} bootinfo_t;
+
+void arch_pre_main(bootinfo_t *bootinfo);
 
 #endif
Index: kernel/arch/sparc32/include/arch/asm.h
===================================================================
--- kernel/arch/sparc32/include/arch/asm.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/asm.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -142,4 +142,29 @@
 }
 
+NO_TRACE static inline uint32_t asi_u32_read(int asi, uintptr_t va)
+{
+	uint32_t v;
+
+	asm volatile (
+		"lda [%[va]] %[asi], %[v]\n"
+		: [v] "=r" (v)
+		: [va] "r" (va),
+		  [asi] "i" ((unsigned int) asi)
+	);
+	
+	return v;
+}
+
+NO_TRACE static inline void asi_u32_write(int asi, uintptr_t va, uint32_t v)
+{
+	asm volatile (
+		"sta %[v], [%[va]] %[asi]\n"
+		:: [v] "r" (v),
+		   [va] "r" (va),
+		   [asi] "i" ((unsigned int) asi)
+		: "memory"
+	);
+}
+
 NO_TRACE static inline void psr_write(uint32_t psr)
 {
Index: kernel/arch/sparc32/include/arch/mm/as.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/as.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/mm/as.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -27,5 +28,5 @@
  */
 
-/** @addtogroup abs32lemm
+/** @addtogroup sparc32mm
  * @{
  */
@@ -33,6 +34,6 @@
  */
 
-#ifndef KERN_abs32le_AS_H_
-#define KERN_abs32le_AS_H_
+#ifndef KERN_sparc32_AS_H_
+#define KERN_sparc32_AS_H_
 
 #define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
@@ -51,7 +52,8 @@
 #define as_destructor_arch(as)          (as != as)
 #define as_create_arch(as, flags)       (as != as)
-#define as_install_arch(as)
 #define as_deinstall_arch(as)
 #define as_invalidate_translation_cache(as, page, cnt)
+
+uintptr_t as_context_table;
 
 extern void as_arch_init(void);
Index: kernel/arch/sparc32/include/arch/mm/asid.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/asid.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/mm/asid.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -27,10 +27,10 @@
  */
 
-/** @addtogroup abc32lemm
+/** @addtogroup sparc32mm
  * @{
  */
 
-#ifndef KERN_abs32le_ASID_H_
-#define KERN_abs32le_ASID_H_
+#ifndef KERN_sparc32_ASID_H_
+#define KERN_sparc32_ASID_H_
 
 #include <typedefs.h>
@@ -38,8 +38,5 @@
 typedef uint32_t asid_t;
 
-#define ASID_MAX_ARCH  3
-
-#define asid_get()      (ASID_START + 1)
-#define asid_put(asid)
+#define ASID_MAX_ARCH  255
 
 #endif
Index: kernel/arch/sparc32/include/arch/mm/frame.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/frame.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/mm/frame.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -41,4 +41,6 @@
 #include <typedefs.h>
 
+#define	PHYSMEM_START_ADDR	0x40000000
+
 #define	BOOT_PT_ADDRESS		0x40008000
 #define	BOOT_PT_START_FRAME	(BOOT_PT_ADDRESS >> FRAME_WIDTH)
Index: kernel/arch/sparc32/include/arch/mm/page.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/page.h	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/include/arch/mm/page.h	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -27,5 +28,5 @@
  */
 
-/** @addtogroup abs32lemm
+/** @addtogroup sparc32mm
  * @{
  */
@@ -33,6 +34,6 @@
  */
 
-#ifndef KERN_abs32le_PAGE_H_
-#define KERN_abs32le_PAGE_H_
+#ifndef KERN_sparc32_PAGE_H_
+#define KERN_sparc32_PAGE_H_
 
 #include <arch/mm/frame.h>
@@ -45,26 +46,34 @@
 #define PA2KA(x)  (((uintptr_t) (x)) + UINT32_C(0x40000000))
 
-/*
- * This is an example of 2-level page tables (PTL1 and PTL2 are left out)
- * on top of the generic 4-level page table interface.
- */
+#define	PTE_ET_INVALID		0
+#define	PTE_ET_DESCRIPTOR	1
+#define	PTE_ET_ENTRY		2
+
+#define	PTE_ACC_USER_RO_KERNEL_RO	0
+#define	PTE_ACC_USER_RW_KERNEL_RW	1
+#define	PTE_ACC_USER_RX_KERNEL_RX	2
+#define	PTE_ACC_USER_RWX_KERNEL_RWX	3
+#define	PTE_ACC_USER_XO_KERNEL_XO	4
+#define	PTE_ACC_USER_RO_KERNEL_RW	5
+#define	PTE_ACC_USER_NO_KERNEL_RX	6
+#define	PTE_ACC_USER_NO_KERNEL_RWX	7
 
 /* Number of entries in each level. */
-#define PTL0_ENTRIES_ARCH  1024
+#define PTL0_ENTRIES_ARCH  256
 #define PTL1_ENTRIES_ARCH  0
-#define PTL2_ENTRIES_ARCH  0
-#define PTL3_ENTRIES_ARCH  1024
+#define PTL2_ENTRIES_ARCH  64
+#define PTL3_ENTRIES_ARCH  64
 
 /* Page table sizes for each level. */
 #define PTL0_SIZE_ARCH  ONE_FRAME
 #define PTL1_SIZE_ARCH  0
-#define PTL2_SIZE_ARCH  0
+#define PTL2_SIZE_ARCH  ONE_FRAME
 #define PTL3_SIZE_ARCH  ONE_FRAME
 
 /* Macros calculating indices for each level. */
-#define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 22) & 0x3ffU)
+#define PTL0_INDEX_ARCH(vaddr)  (((vaddr) >> 24) & 0xffU)
 #define PTL1_INDEX_ARCH(vaddr)  0
-#define PTL2_INDEX_ARCH(vaddr)  0
-#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x3ffU)
+#define PTL2_INDEX_ARCH(vaddr)  (((vaddr) >> 18) & 0x3fU)
+#define PTL3_INDEX_ARCH(vaddr)  (((vaddr) >> 12) & 0x3fU)
 
 /* Get PTE address accessors for each level. */
@@ -72,7 +81,7 @@
 	((pte_t *) ((((pte_t *) (ptl0))[(i)].frame_address) << 12))
 #define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
-	(ptl1)
+	KA2PA(ptl1)
 #define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
-	(ptl2)
+	((pte_t *) ((((pte_t *) (ptl2))[(i)].frame_address) << 12))
 #define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
 	((uintptr_t) ((((pte_t *) (ptl3))[(i)].frame_address) << 12))
@@ -83,5 +92,6 @@
 	(((pte_t *) (ptl0))[(i)].frame_address = (a) >> 12)
 #define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
-#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
+#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) \
+	(((pte_t *) (ptl2))[(i)].frame_address = (a) >> 12)
 #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
 	(((pte_t *) (ptl3))[(i)].frame_address = (a) >> 12)
@@ -93,23 +103,23 @@
 	PAGE_PRESENT
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-	PAGE_PRESENT
+	get_pt_flags((pte_t *) (ptl2), (size_t) (i))
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
 	get_pt_flags((pte_t *) (ptl3), (size_t) (i))
 
 /* Set PTE flags accessors for each level. */
-#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)	\
-	set_pt_flags((pte_t *) (ptl0), (size_t) (i), (x))
+#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)
 #define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
 #define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
-	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
+	set_pte_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
 /* Set PTE present bit accessors for each level. */
 #define SET_PTL1_PRESENT_ARCH(ptl0, i)	\
-	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+	set_ptd_present((pte_t *) (ptl0), (size_t) (i))
 #define SET_PTL2_PRESENT_ARCH(ptl1, i)
-#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i) \
+	set_ptd_present((pte_t *) (ptl2), (size_t) (i))
 #define SET_FRAME_PRESENT_ARCH(ptl3, i) \
-	set_pt_present((pte_t *) (ptl3), (size_t) (i))
+	set_pte_present((pte_t *) (ptl3), (size_t) (i))
 
 /* Macros for querying the last level entries. */
@@ -117,10 +127,11 @@
 	(*((uint32_t *) (p)) != 0)
 #define PTE_PRESENT_ARCH(p) \
-	((p)->present != 0)
+	((p)->et != 0)
 #define PTE_GET_FRAME_ARCH(p) \
 	((p)->frame_address << FRAME_WIDTH)
 #define PTE_WRITABLE_ARCH(p) \
-	((p)->writeable != 0)
-#define PTE_EXECUTABLE_ARCH(p)  1
+	pte_is_writeable(p)
+#define PTE_EXECUTABLE_ARCH(p) \
+	pte_is_executable(p)
 
 #include <mm/mm.h>
@@ -128,64 +139,119 @@
 #include <typedefs.h>
 
+/** Page Table Descriptor. */
+typedef struct {
+	unsigned int table_pointer: 30;
+	unsigned int et: 2;
+} __attribute__((packed)) ptd_t;
+
 /** Page Table Entry. */
 typedef struct {
-	unsigned int present : 1;
-	unsigned int writeable : 1;
-	unsigned int uaccessible : 1;
-	unsigned int page_write_through : 1;
-	unsigned int page_cache_disable : 1;
-	unsigned int accessed : 1;
-	unsigned int dirty : 1;
-	unsigned int pat : 1;
-	unsigned int global : 1;
+	unsigned int frame_address: 24;
+	unsigned int cacheable: 1;
+	unsigned int modified: 1;
+	unsigned int referenced: 1;
+	unsigned int acc: 3;
+	unsigned int et: 2;
+} __attribute__((packed)) pte_t;
+
+NO_TRACE static inline void set_ptl0_addr(pte_t *pt)
+{
+}
+
+NO_TRACE static inline bool pte_is_writeable(pte_t *pt)
+{
+	return (
+		pt->acc == PTE_ACC_USER_RW_KERNEL_RW || 
+		pt->acc == PTE_ACC_USER_RWX_KERNEL_RWX || 
+		pt->acc == PTE_ACC_USER_RO_KERNEL_RW || 
+		pt->acc == PTE_ACC_USER_NO_KERNEL_RWX
+	);
+}
+
+NO_TRACE static inline bool pte_is_executable(pte_t *pt)
+{
+	return (
+		pt->acc != PTE_ACC_USER_RO_KERNEL_RO &&
+		pt->acc != PTE_ACC_USER_RW_KERNEL_RW &&
+		pt->acc != PTE_ACC_USER_RO_KERNEL_RW
+	);
+}
+
+NO_TRACE static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
+
+	bool notpresent = p->et == 0;
+
+	return (
+		(p->cacheable << PAGE_CACHEABLE_SHIFT) |
+		(notpresent << PAGE_PRESENT_SHIFT) |
+		((p->acc != PTE_ACC_USER_NO_KERNEL_RX && p->acc != PTE_ACC_USER_NO_KERNEL_RWX) << PAGE_USER_SHIFT) |
+		(1 << PAGE_READ_SHIFT) |
+		((
+			p->acc == PTE_ACC_USER_RW_KERNEL_RW || 
+			p->acc == PTE_ACC_USER_RWX_KERNEL_RWX || 
+			p->acc == PTE_ACC_USER_RO_KERNEL_RW || 
+			p->acc == PTE_ACC_USER_NO_KERNEL_RWX
+		) << PAGE_WRITE_SHIFT) |
+		((
+			p->acc != PTE_ACC_USER_RO_KERNEL_RO &&
+			p->acc != PTE_ACC_USER_RW_KERNEL_RW &&
+			p->acc != PTE_ACC_USER_RO_KERNEL_RW
+		) << PAGE_EXEC_SHIFT) |
+		(1 << PAGE_GLOBAL_SHIFT)
+	);
+}
+
+NO_TRACE static inline void set_ptd_flags(pte_t *pt, size_t i, int flags)
+    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
 	
-	/** Valid content even if the present bit is not set. */
-	unsigned int soft_valid : 1;
-	unsigned int avl : 2;
-	unsigned int frame_address : 20;
-} __attribute__((packed)) pte_t;
-
-NO_TRACE static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
-    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
-{
-	pte_t *p = &pt[i];
+	p->et = (flags & PAGE_NOT_PRESENT)
+		? PTE_ET_INVALID
+		: PTE_ET_DESCRIPTOR;
+}
+
+NO_TRACE static inline void set_pte_flags(pte_t *pt, size_t i, int flags)
+    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
+
+	p->et = PTE_ET_ENTRY;
+	p->acc = PTE_ACC_USER_NO_KERNEL_RWX;
 	
-	return (
-	    ((unsigned int) (!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT) |
-	    ((unsigned int) (!p->present) << PAGE_PRESENT_SHIFT) |
-	    ((unsigned int) p->uaccessible << PAGE_USER_SHIFT) |
-	    (1 << PAGE_READ_SHIFT) |
-	    ((unsigned int) p->writeable << PAGE_WRITE_SHIFT) |
-	    (1 << PAGE_EXEC_SHIFT) |
-	    ((unsigned int) p->global << PAGE_GLOBAL_SHIFT)
-	);
-}
-
-NO_TRACE static inline void set_pt_flags(pte_t *pt, size_t i, int flags)
-    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
-    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
-{
-	pte_t *p = &pt[i];
-	
-	p->page_cache_disable = !(flags & PAGE_CACHEABLE);
-	p->present = !(flags & PAGE_NOT_PRESENT);
-	p->uaccessible = (flags & PAGE_USER) != 0;
-	p->writeable = (flags & PAGE_WRITE) != 0;
-	p->global = (flags & PAGE_GLOBAL) != 0;
-	
-	/*
-	 * Ensure that there is at least one bit set even if the present bit is
-	 * cleared.
-	 */
-	p->soft_valid = true;
-}
-
-NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
-    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
-    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
-{
-	pte_t *p = &pt[i];
-
-	p->present = 1;
+	if (flags & PAGE_USER) {
+		if (flags & PAGE_READ)
+			p->acc = PTE_ACC_USER_RO_KERNEL_RW;
+		if (flags & PAGE_WRITE)
+			p->acc = PTE_ACC_USER_RW_KERNEL_RW;
+	}
+
+	if (flags & PAGE_NOT_PRESENT)
+		p->et = PTE_ET_INVALID;
+
+	p->cacheable = (flags & PAGE_CACHEABLE) != 0;
+}
+
+NO_TRACE static inline void set_ptd_present(pte_t *pt, size_t i)
+    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
+
+	p->et = PTE_ET_DESCRIPTOR;
+}
+
+NO_TRACE static inline void set_pte_present(pte_t *pt, size_t i)
+    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
+
+	p->et = PTE_ET_ENTRY;
 }
 
Index: kernel/arch/sparc32/src/mm/as.c
===================================================================
--- kernel/arch/sparc32/src/mm/as.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/src/mm/as.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -27,15 +27,31 @@
  */
 
-/** @addtogroup abs32lemm
+/** @addtogroup sparc32mm
  * @{
  */
 
 #include <mm/as.h>
+#include <arch/arch.h>
+#include <arch/asm.h>
 #include <arch/mm/as.h>
+#include <arch/mm/page.h>
 #include <genarch/mm/page_pt.h>
+
+static ptd_t context_table[ASID_MAX_ARCH] __attribute__((aligned (1024)));
 
 void as_arch_init(void)
 {
 	as_operations = &as_pt_operations;
+	as_context_table = (uintptr_t)&context_table;
+}
+
+void as_install_arch(as_t *as)
+{
+	printf("as_install_arch(asid=%d)\n", as->asid);
+	printf("genarch.page_table=%p\n", as->genarch.page_table);
+
+	context_table[as->asid].table_pointer = (uintptr_t)as->genarch.page_table >> 6;
+	context_table[as->asid].et = PTE_ET_DESCRIPTOR;
+	asi_u32_write(ASI_MMUREGS, 0x200, as->asid);
 }
 
Index: kernel/arch/sparc32/src/mm/frame.c
===================================================================
--- kernel/arch/sparc32/src/mm/frame.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/src/mm/frame.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -48,5 +48,5 @@
 	//machine_get_memory_extents(&base, &size);
 	base = 0x40000000;
-	size = 0x2000000;
+	size = 0x4000000;
 
 	base = ALIGN_UP(base, FRAME_SIZE);
Index: kernel/arch/sparc32/src/mm/page.c
===================================================================
--- kernel/arch/sparc32/src/mm/page.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/src/mm/page.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -49,9 +49,33 @@
 #include <print.h>
 #include <interrupt.h>
+#include <macros.h>
 
 void page_arch_init(void)
 {
-	if (config.cpu_active == 1)
-		page_mapping_operations = &pt_mapping_operations;
+	int flags = PAGE_CACHEABLE | PAGE_EXEC;
+	page_mapping_operations = &pt_mapping_operations;
+
+	page_table_lock(AS_KERNEL, true);
+	
+	/* Kernel identity mapping */
+	//FIXME: We need to consider the possibility that
+	//identity_base > identity_size and physmem_end.
+	//This might lead to overflow if identity_size is too big.
+	for (uintptr_t cur = PHYSMEM_START_ADDR;
+	    cur < min(KA2PA(config.identity_base) +
+	        config.identity_size, config.physmem_end);
+	    cur += FRAME_SIZE)
+		page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
+	
+
+	page_table_unlock(AS_KERNEL, true);
+	as_switch(NULL, AS_KERNEL);
+
+	printf("as_context_table=0x%08x\n", as_context_table);
+
+	/* Switch MMU to new context table */
+	asi_u32_write(ASI_MMUREGS, 0x100, KA2PA(as_context_table) >> 4);
+
+	//boot_page_table_free();
 }
 
Index: kernel/arch/sparc32/src/sparc32.c
===================================================================
--- kernel/arch/sparc32/src/sparc32.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/src/sparc32.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -49,11 +49,22 @@
 #include <syscall/syscall.h>
 #include <console/console.h>
+#include <macros.h>
 #include <memstr.h>
+#include <str.h>
 
 char memcpy_from_uspace_failover_address;
 char memcpy_to_uspace_failover_address;
 
-void arch_pre_main(void)
+void arch_pre_main(bootinfo_t *bootinfo)
 {
+	init.cnt = min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
+	
+	size_t i;
+	for (i = 0; i < init.cnt; i++) {
+		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,
+		    bootinfo->tasks[i].name);
+	}
 }
 
Index: kernel/arch/sparc32/src/start.S
===================================================================
--- kernel/arch/sparc32/src/start.S	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/arch/sparc32/src/start.S	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -51,4 +51,5 @@
 	sub	%sp, 96, %sp
 
+	mov	%o1, %i0
 	call arch_pre_main
 	nop
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/genarch/src/mm/page_pt.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -77,11 +77,20 @@
     unsigned int flags)
 {
+	//printf("pt_mapping_insert: as=%p, page=0x%08x, frame=0x%08x\n", as, page, frame);
+
 	pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
 
+	//printf("ptl0 = %p\n", ptl0);
+
 	ASSERT(page_table_locked(as));
-	
+
 	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
+	//	printf("allocating ptl1\n");
+
 		pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
 		    FRAME_LOWMEM | FRAME_KA);
+
+	//	printf("newpt = %p, index = %d\n", newpt, PTL0_INDEX(page));
+
 		memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
@@ -100,7 +109,14 @@
 	pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
 	
+//	printf("ptl1 = %p\n", ptl1);
+
 	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
+//		printf("allocating ptl2\n");
+
 		pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
 		    FRAME_LOWMEM | FRAME_KA);
+
+//		printf("newpt = %p, index = %d\n", newpt, PTL1_INDEX(page));
+
 		memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
 		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
@@ -117,7 +133,14 @@
 	pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
 	
+//	printf("ptl2 = %p\n", ptl2);
+
 	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
+//		printf("allocating ptl3\n");
+
 		pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
 		    FRAME_LOWMEM | FRAME_KA);
+
+//		printf("newpt = %p, index = %d\n", newpt, PTL2_INDEX(page));
+
 		memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
 		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
@@ -134,4 +157,6 @@
 	pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
 	
+//	printf("ptl3 = %p\n", ptl3);
+
 	SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
 	SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags | PAGE_NOT_PRESENT);
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision b6b02c0fa1670aace09bf1d3f51ce99017e6230e)
+++ kernel/generic/src/proc/scheduler.c	(revision ef9a2a897b47371cfb43b8b8bb95ad044136eccf)
@@ -64,4 +64,6 @@
 #include <stacktrace.h>
 
+//#define	SCHEDULER_VERBOSE 1
+
 static void scheduler_separated_stack(void);
 
@@ -518,5 +520,5 @@
 #ifdef SCHEDULER_VERBOSE
 	printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64 
-	    ", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
+	    ", nrdy=%d)\n", CPU->id, THREAD->tid, THREAD->priority,
 	    THREAD->ticks, atomic_get(&CPU->nrdy));
 #endif
