Index: kernel/arch/sparc64/include/asm.h
===================================================================
--- kernel/arch/sparc64/include/asm.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/include/asm.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -331,5 +331,5 @@
 extern void write_to_ig_g6(uint64_t val);
 
-extern void switch_to_userspace(uint64_t pc, uint64_t sp);
+extern void switch_to_userspace(uint64_t pc, uint64_t sp, uint64_t uarg);
 
 #endif
Index: kernel/arch/sparc64/include/mm/as.h
===================================================================
--- kernel/arch/sparc64/include/mm/as.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/include/mm/as.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -43,5 +43,5 @@
 #define USER_ADDRESS_SPACE_END_ARCH		(unsigned long) 0xffffffffffffffff
 
-#define USTACK_ADDRESS_ARCH	(0x7fffffffffffffff-(PAGE_SIZE-1))
+#define USTACK_ADDRESS_ARCH	(0xffffffffffffffffULL-(PAGE_SIZE-1))
 
 extern void as_arch_init(void);
Index: kernel/arch/sparc64/include/mm/tlb.h
===================================================================
--- kernel/arch/sparc64/include/mm/tlb.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/include/mm/tlb.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -180,5 +180,5 @@
 static inline void mmu_secondary_context_write(uint64_t v)
 {
-	asi_u64_write(ASI_DMMU, VA_PRIMARY_CONTEXT_REG, v);
+	asi_u64_write(ASI_DMMU, VA_SECONDARY_CONTEXT_REG, v);
 	flush();
 }
Index: kernel/arch/sparc64/include/trap/mmu.h
===================================================================
--- kernel/arch/sparc64/include/trap/mmu.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/include/trap/mmu.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -128,15 +128,14 @@
 .macro HANDLE_MMU_TRAPS_FROM_SPILL_OR_FILL
 	rdpr %tl, %g1
-	dec %g1
-	brz %g1, 0f			! if TL was 1, skip
+	sub %g1, 1, %g2
+	brz %g2, 0f			! if TL was 1, skip
 	nop
-	wrpr %g1, 0, %tl		! TL--
-	rdpr %tt, %g2
-	cmp %g2, TT_SPILL_1_NORMAL
-	be 0f				! trap from spill_1_normal
-	cmp %g2, TT_FILL_1_NORMAL
-	be 0f				! trap from fill_1_normal
-	inc %g1
-	wrpr %g1, 0, %tl		! another trap, TL++
+	wrpr %g2, 0, %tl		! TL--
+	rdpr %tt, %g3
+	cmp %g3, TT_SPILL_1_NORMAL
+	be 0f				! trap from spill_1_normal?
+	cmp %g3, TT_FILL_1_NORMAL
+	bne,a 0f			! trap from fill_1_normal? (negated condition)
+	wrpr %g1, 0, %tl		! TL++
 0:
 .endm
Index: kernel/arch/sparc64/src/asm.S
===================================================================
--- kernel/arch/sparc64/src/asm.S	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/asm.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -151,4 +151,5 @@
  * %o0	Userspace entry address.
  * %o1	Userspace stack pointer address.
+ * %o2  Userspace address of uarg structure.
  */
 .global switch_to_userspace
@@ -157,4 +158,6 @@
 	wrpr %g0, 0, %cleanwin		! avoid information leak
 	save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
+
+	mov %i3, %o0			! uarg
 
 	clr %i2
@@ -179,4 +182,9 @@
 	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
 	flush %i7
+
+	/*
+	 * Spills and fills will be handled by the userspace handlers.
+	 */
+	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
 	
 	done				! jump to userspace
Index: kernel/arch/sparc64/src/context.S
===================================================================
--- kernel/arch/sparc64/src/context.S	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/context.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -28,5 +28,4 @@
 
 #include <arch/context_offset.h>
-#include <arch/stack.h>
 
 /**
Index: kernel/arch/sparc64/src/mm/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tlb.c	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/mm/tlb.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -137,5 +137,5 @@
 	data.cp = t->c;
 	data.cv = t->c;
-	data.p = t->p;
+	data.p = t->k;		/* p like privileged */
 	data.w = ro ? false : t->w;
 	data.g = t->g;
@@ -167,5 +167,5 @@
 	data.cp = t->c;
 	data.cv = t->c;
-	data.p = t->p;
+	data.p = t->k;		/* p like privileged */
 	data.w = false;
 	data.g = t->g;
Index: kernel/arch/sparc64/src/proc/scheduler.c
===================================================================
--- kernel/arch/sparc64/src/proc/scheduler.c	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/proc/scheduler.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -127,6 +127,4 @@
 		ASSERT(THREAD->arch.uspace_window_buffer);
 		
-		flushw();	/* force all userspace windows into memory */
-		
 		uintptr_t uw_buf = ALIGN_DOWN((uintptr_t) THREAD->arch.uspace_window_buffer, PAGE_SIZE);
 		if (!overlaps(uw_buf, PAGE_SIZE, base, 1<<KERNEL_PAGE_WIDTH)) {
Index: kernel/arch/sparc64/src/sparc64.c
===================================================================
--- kernel/arch/sparc64/src/sparc64.c	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/sparc64.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -48,4 +48,17 @@
 
 bootinfo_t bootinfo;
+
+void arch_pre_main(void)
+{
+	/* Setup usermode */
+	init.cnt = bootinfo.taskmap.count;
+	
+	uint32_t i;
+
+	for (i = 0; i < bootinfo.taskmap.count; i++) {
+		init.tasks[i].addr = PA2KA(bootinfo.taskmap.tasks[i].addr);
+		init.tasks[i].size = bootinfo.taskmap.tasks[i].size;
+	}
+}
 
 void arch_pre_mm_init(void)
@@ -99,5 +112,6 @@
 	switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
 		((uintptr_t) kernel_uarg->uspace_stack) + STACK_SIZE
-		- (ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT) + STACK_BIAS));
+		- (ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT) + STACK_BIAS),
+		(uintptr_t) kernel_uarg->uspace_uarg);
 
 	for (;;)
Index: kernel/arch/sparc64/src/start.S
===================================================================
--- kernel/arch/sparc64/src/start.S	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/start.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -209,4 +209,7 @@
 	! set TL back to 0
 	wrpr %g0, 0, %tl
+
+	call arch_pre_main
+	nop
 	
 	call main_bsp
Index: kernel/arch/sparc64/src/trap/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/trap_table.S	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/arch/sparc64/src/trap/trap_table.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -219,4 +219,10 @@
 	SPILL_TO_USPACE_WINDOW_BUFFER
 
+/* TT = 0xa0, TL = 0, spill_0_other handler */
+.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
+.global spill_0_other
+spill_0_other:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
 /* TT = 0xc0, TL = 0, fill_0_normal handler */
 .org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
@@ -548,10 +554,10 @@
 
 	/*
-	 * Mark the CANSAVE windows as OTHER windows.
+	 * Mark the CANRESTORE windows as OTHER windows.
 	 * Set CLEANWIN to NWINDOW-1 so that clean_window traps do not occur.
 	 */
-	rdpr %cansave, %l0
+	rdpr %canrestore, %l0
 	wrpr %l0, %otherwin
-	wrpr %g0, %cansave
+	wrpr %g0, %canrestore
 	wrpr %g0, NWINDOW - 1, %cleanwin
 
@@ -642,6 +648,8 @@
 	/*
 	 * If OTHERWIN is zero, then all the userspace windows have been
-	 * spilled to kernel memory (i.e. register window buffer). If
-	 * OTHERWIN is non-zero, then some userspace windows are still
+	 * spilled to kernel memory (i.e. register window buffer). Moreover,
+	 * if the scheduler was called in the meantime, all valid windows
+	 * belonging to other threads were spilled by context_restore().
+	 * If OTHERWIN is non-zero, then some userspace windows are still
 	 * valid. Others might have been spilled. However, the CWP pointer
 	 * needs no fixing because the scheduler had not been called.
@@ -660,5 +668,5 @@
 	and %g1, TSTATE_CWP_MASK, %l0
 	inc %l0
-	and %l0, TSTATE_CWP_MASK, %l0	! %l0 mod NWINDOW
+	and %l0, NWINDOW - 1, %l0	! %l0 mod NWINDOW
 	rdpr %cwp, %l1
 	cmp %l0, %l1
@@ -668,11 +676,10 @@
 	/*
 	 * Fix CWP.
-	 * Just for reminder, the input registers in the current window
-	 * are the output registers of the window to which we want to
-	 * restore. Because the fill trap fills only input and local
+	 * In order to recapitulate, the input registers in the current
+	 * window are the output registers of the window to which we want
+	 * to restore. Because the fill trap fills only input and local
 	 * registers of a window, we need to preserve those output
 	 * registers manually.
 	 */
-	flushw
 	mov %sp, %g2
 	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
@@ -739,5 +746,6 @@
 	 */
 	clr %g4
-0:	andcc %g7, PAGE_WIDTH - 1, %g0		! PAGE_SIZE alignment check
+	set PAGE_SIZE - 1, %g5
+0:	andcc %g7, %g5, %g0			! PAGE_SIZE alignment check
 	bz 0f					! %g7 is page-aligned, no more windows to refill
 	nop
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ kernel/generic/src/proc/task.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -221,5 +221,5 @@
 	 * Create the main thread.
 	 */
-	t1 = thread_create(uinit, kernel_uarg, task, 0, "uinit");
+	t1 = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, "uinit");
 	ASSERT(t1);
 	
