Index: kernel/arch/sparc32/include/arch/arch.h
===================================================================
--- kernel/arch/sparc32/include/arch/arch.h	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/include/arch/arch.h	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -40,4 +40,5 @@
 
 #include <typedefs.h>
+#include <arch/istate.h>
 
 #define	NWINDOWS	8
@@ -76,4 +77,8 @@
 extern void arch_pre_main(void *unused, bootinfo_t *bootinfo);
 extern void write_to_invalid(uint32_t l0, uint32_t l1, uint32_t l2);
+extern void read_from_invalid(uint32_t *l0, uint32_t *l1, uint32_t *l2);
+extern void preemptible_save_uspace(uintptr_t sp, istate_t *istate);
+extern void preemptible_restore_uspace(uintptr_t sp, istate_t *istate);
+extern void flush_windows(void);
 
 #endif
Index: kernel/arch/sparc32/include/arch/asm.h
===================================================================
--- kernel/arch/sparc32/include/arch/asm.h	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/include/arch/asm.h	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -145,4 +145,16 @@
 }
 
+NO_TRACE static inline uint32_t wim_read()
+{
+	uint32_t v;
+
+	asm volatile (
+		"mov %%wim, %[v]\n"
+		: [v] "=r" (v)
+	);
+
+	return v;
+}
+
 NO_TRACE static inline uint32_t asi_u32_read(int asi, uintptr_t va)
 {
@@ -178,4 +190,12 @@
 }
 
+NO_TRACE static inline void wim_write(uint32_t wim)
+{
+	asm volatile (
+		"mov %[v], %%wim\n"
+		:: [v] "r" (wim)
+	);
+}
+
 NO_TRACE static inline ipl_t interrupts_enable(void)
 {
Index: kernel/arch/sparc32/include/arch/context.h
===================================================================
--- kernel/arch/sparc32/include/arch/context.h	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/include/arch/context.h	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -45,5 +45,5 @@
 #define context_set(c, _pc, stack, size) \
 	do { \
-		(c)->pc = ((uintptr_t) _pc) - 4; \
+		(c)->pc = ((uintptr_t) _pc) - 8; \
 		(c)->sp = ((uintptr_t) stack) + ALIGN_UP((size), \
 		    STACK_ALIGNMENT) - (SP_DELTA); \
Index: kernel/arch/sparc32/include/arch/faddr.h
===================================================================
--- kernel/arch/sparc32/include/arch/faddr.h	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/include/arch/faddr.h	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -33,6 +33,6 @@
  */
 
-#ifndef KERN_abs32le_FADDR_H_
-#define KERN_abs32le_FADDR_H_
+#ifndef KERN_sparc32_FADDR_H_
+#define KERN_sparc32_FADDR_H_
 
 #include <typedefs.h>
Index: kernel/arch/sparc32/include/arch/regwin.h
===================================================================
--- kernel/arch/sparc32/include/arch/regwin.h	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/include/arch/regwin.h	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -42,7 +42,5 @@
 #include <align.h>
 
-#define CLEAN_WINDOW_HANDLER_SIZE	REGWIN_HANDLER_SIZE
-#define SPILL_HANDLER_SIZE		REGWIN_HANDLER_SIZE
-#define FILL_HANDLER_SIZE		REGWIN_HANDLER_SIZE
+#define	UWB_ALIGNMENT	1024
 
 /* Window Save Area offsets. */
Index: kernel/arch/sparc32/src/exception.c
===================================================================
--- kernel/arch/sparc32/src/exception.c	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/src/exception.c	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -39,7 +39,12 @@
 #include <arch/istate.h>
 #include <arch/exception.h>
+#include <arch/regwin.h>
 #include <syscall/syscall.h>
 #include <interrupt.h>
 #include <arch/asm.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <mm/as.h>
+#include <memstr.h>
 #include <debug.h>
 #include <print.h>
@@ -142,7 +147,22 @@
 sysarg_t syscall(sysarg_t a1, sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5, sysarg_t a6, sysarg_t id)
 {
-	printf("syscall %d\n", id);
-	printf("args: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", a1, a2, a3, a4, a5, a6);
+//	printf("syscall %d\n", id);
+//	printf("args: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", a1, a2, a3, a4, a5, a6);
+        if (id == 0x4f) {
+            flush_windows();
+            return 0;
+        }
+    
 	return syscall_handler(a1, a2, a3, a4, a5, a6, id);
+}
+
+void preemptible_save_uspace(uintptr_t sp, istate_t *istate)
+{
+	as_page_fault(sp, PF_ACCESS_WRITE, istate);
+}
+
+void preemptible_restore_uspace(uintptr_t sp, istate_t *istate)
+{
+	as_page_fault(sp, PF_ACCESS_WRITE, istate);
 }
 
Index: kernel/arch/sparc32/src/trap_table.S
===================================================================
--- kernel/arch/sparc32/src/trap_table.S	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/src/trap_table.S	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -28,4 +28,5 @@
 
 #include <arch/trap.h>
+#include <arch/regwin.h>
 
 .text
@@ -39,4 +40,6 @@
 .global window_underflow_trap
 .global write_to_invalid
+.global read_from_invalid
+.global flush_windows
 
 .macro get_wim_number reg
@@ -231,4 +234,23 @@
 	nop
 
+read_from_invalid:
+	! Read value 1
+	mov %o0, %g7
+	switch_to_invalid %g3, %g4
+	st %l5, [%g7]
+	switch_back %g3, %g4
+	! Write value 2
+	mov %o1, %g7
+	switch_to_invalid %g3, %g4
+	st %l6, [%g7]
+	switch_back %g3, %g4
+	! Write value 3
+	mov %o2, %g7
+	switch_to_invalid %g3, %g4
+	st %l7, [%g7]
+	switch_back %g3, %g4
+	retl
+	nop
+
 reset_trap:
 	set 0x80000100, %l0
@@ -240,5 +262,35 @@
 	mov %g7, %l0
 
-	/* rotate WIM on bit right, we have 8 windows */
+	/* Check whether previous mode was usermode */
+	mov %psr, %l4
+	and %l4, (1 << 6), %l4
+	cmp %l4, 0
+	bne 1f
+	nop
+
+	/* userspace: */
+	/* time to check whether desired stack page is mapped
+	 * on the MMU. if so, process with saving window directly.
+	 * if not, go to preemptible trap handler */
+	mov %wim, %g5
+	mov %g0, %wim
+	save
+	mov %sp, %g4
+	restore
+	mov %g5, %wim
+	and %g4, 0xfffff000, %l4
+	lda [%l4] 0x18, %l4
+	cmp %l4, 0
+	bne 1f
+	nop
+
+	/* prepare args for preemptible handler */
+	mov %g4, %o0
+	set preemptible_save_uspace, %o2
+	b preemptible_trap
+	nop
+
+	/* kernel: */
+1:	/* rotate WIM on bit right, we have 8 windows */
 	mov %wim, %l3
 	sll %l3, 7, %l4
@@ -256,12 +308,5 @@
 	mov %l7, %g7
 
-	/* Check whether previous mode was usermode */
-	mov %psr, %l4
-	and %l4, (1 << 6), %l4
-	cmp %l4, 0
-	beq 1f
-	nop
-
-	/* kernel: */
+
 	/* we should check whether window needs to be saved
 	 * to kernel stack or uwb
@@ -284,10 +329,5 @@
 	nop
 
-1:	/* uspace: */
-	/* set uspace window mark */
-	mov %psr, %g7
-	and %g7, 0x7, %g7
-	or %g7, 0x10, %g7
-
+	/* dump registers to uwb */
 2:	save
 	std %l0, [%g6 +  0]
@@ -330,6 +370,37 @@
 	mov %g7, %l0
 
+	/* Check whether previous mode was usermode */
+	mov %psr, %l4
+	and %l4, (1 << 6), %l4
+	cmp %l4, 0
+	bne 1f
+	nop
+
+	/* userspace: */
+	/* time to check whether desired stack page is mapped
+	 * on the MMU. if so, process with saving window directly.
+	 * if not, go to preemptible trap handler */
+	mov %wim, %g5
+	mov %g0, %wim
+	restore
+	restore
+	mov %sp, %g4
+	save
+	save
+	mov %g5, %wim
+	and %sp, 0xfffff000, %l4
+	lda [%l4] 0x18, %l4
+	cmp %l4, 0
+	bne 1f
+	nop
+
+	/* prepare args for preemptible handler */
+	mov %g4, %o0
+	set preemptible_restore_uspace, %o2
+	b preemptible_trap
+	nop
+
         /* rotate WIM on bit LEFT, we have 8 windows */ 
-        mov %wim,%l3
+1:      mov %wim,%l3
         srl %l3,7,%l4
         sll %l3,1,%l3
@@ -341,11 +412,5 @@
         nop; nop; nop
 
-	/* Check whether previous mode was usermode */
-	mov %psr, %l4
-	and %l4, (1 << 6), %l4
-	cmp %l4, 0
-	beq 1f
-	nop
-
+	/* kernel: */
 	restore
 	restore
@@ -365,19 +430,4 @@
 	nop
 
-1:	restore
-	restore
-	mov %l5, %g5		! kernel stack pointer
-	mov %l6, %g6		! kernel wbuf
-	mov %l7, %g7
-	sub %g6, 64, %g6
-        ldd [%g6 +  0], %l0
-        ldd [%g6 +  8], %l2
-        ldd [%g6 + 16], %l4
-        ldd [%g6 + 24], %l6
-        ldd [%g6 + 32], %i0
-        ldd [%g6 + 40], %i2
-        ldd [%g6 + 48], %i4
-        ldd [%g6 + 56], %i6
-
 2:	/* Restore invalid window data */
 	restore
@@ -397,4 +447,18 @@
         jmp %l1
         rett %l2
+
+flush_windows:
+        mov 7, %g1
+1:	subcc %g1, 1, %g1
+ 	bg 1b
+        save %sp, -64, %sp
+
+	mov 7, %g1
+1:	subcc %g1, 1, %g1
+ 	bg 1b
+        restore
+
+        retl
+        nop
 
 preemptible_trap:
@@ -470,5 +534,5 @@
 	/* Jump to actual subroutine */
 	call %o2
-	sub %fp, 12, %o1
+	add %sp, 128, %o1
 
 	/* Return from handler */
@@ -487,7 +551,46 @@
 	switch_to_invalid %g5, %g6
 	clr %l7
+	mov %l5, %g2
 	mov %l6, %g7
 	switch_back %g5, %g6
 	mov %g7, %g1
+
+	/* If trap originated from uspace, restore all windows from UWB */
+	/* UWB pointer is at %g1 */
+0:	mov %g0, %wim
+	clr %g5
+	andcc %g1, UWB_ALIGNMENT - 1, %g0
+	bz 0f
+	nop
+
+	restore
+	sub %g1, 64, %g1
+	ldd [%g1 +  0], %l0
+	ldd [%g1 +  8], %l2
+	ldd [%g1 + 16], %l4
+	ldd [%g1 + 24], %l6
+	ldd [%g1 + 32], %i0
+	ldd [%g1 + 40], %i2
+	ldd [%g1 + 48], %i4
+	ldd [%g1 + 56], %i6
+	inc %g5
+	and %g5, 0x7, %g5
+	ba 0b
+	nop
+
+	/* We've restored all uspace windows. Now time to
+	 * fix CWP and WIM
+	 */
+0:	restore
+	get_cwp %g7
+	clr %g5
+	inc %g5
+	sll %g5, %g7, %g5
+
+	/* Write values to invalid window and switch back */
+	mov %g2, %l5
+	mov %g1, %l6
+	clr %l7
+	switch_back %g5, %g6
 
 	/* If next window is invalid, do inline restore */
@@ -679,4 +782,8 @@
 	ld [%sp + 100], %l0
 	mov %o0, %i0
+	mov %psr, %l1
+	and %l1, 0xf, %l1
+	and %l0, 0xfffffff0, %l0
+	or %l0, %l1, %l0
 	mov %l0, %psr
 	nop
@@ -690,7 +797,46 @@
 	switch_to_invalid %g5, %g6
 	clr %l7
+	mov %l5, %g2
 	mov %l6, %g7
 	switch_back %g5, %g6
 	mov %g7, %g1
+
+	/* If trap originated from uspace, restore all windows from UWB */
+	/* UWB pointer is at %g1 */
+0:	mov %g0, %wim
+	clr %g5
+	andcc %g1, UWB_ALIGNMENT - 1, %g0
+	bz 0f
+	nop
+
+	restore
+	sub %g1, 64, %g1
+	ldd [%g1 +  0], %l0
+	ldd [%g1 +  8], %l2
+	ldd [%g1 + 16], %l4
+	ldd [%g1 + 24], %l6
+	ldd [%g1 + 32], %i0
+	ldd [%g1 + 40], %i2
+	ldd [%g1 + 48], %i4
+	ldd [%g1 + 56], %i6
+	inc %g5
+	and %g5, 0x7, %g5
+	ba 0b
+	nop
+
+	/* We've restored all uspace windows. Now time to
+	 * fix CWP and WIM
+	 */
+0:	restore
+	get_cwp %g7
+	clr %g5
+	inc %g5
+	sll %g5, %g7, %g5
+
+	/* Write values to invalid window and switch back */
+	mov %g2, %l5
+	mov %g1, %l6
+	clr %l7
+	switch_back %g5, %g6
 
 	/* If next window is invalid, do inline restore */
@@ -929,2 +1075,34 @@
 	SYSCALL(0xae)
 	SYSCALL(0xaf)
+        SYSCALL(0xb0)
+        SYSCALL(0xb1)
+        SYSCALL(0xb2)
+        SYSCALL(0xb3)
+        SYSCALL(0xb4)
+        SYSCALL(0xb5)
+        SYSCALL(0xb6)
+        SYSCALL(0xb7)
+        SYSCALL(0xb8)
+        SYSCALL(0xb9)
+        SYSCALL(0xba)
+        SYSCALL(0xbb)
+        SYSCALL(0xbc)
+        SYSCALL(0xbd)
+        SYSCALL(0xbe)
+        SYSCALL(0xbf)
+        SYSCALL(0xc0)
+        SYSCALL(0xc1)
+        SYSCALL(0xc2)
+        SYSCALL(0xc3)
+        SYSCALL(0xc4)
+        SYSCALL(0xc5)
+        SYSCALL(0xc6)
+        SYSCALL(0xc7)
+        SYSCALL(0xc8)
+        SYSCALL(0xc9)
+        SYSCALL(0xca)
+        SYSCALL(0xcb)
+        SYSCALL(0xcc)
+        SYSCALL(0xcd)
+        SYSCALL(0xce)
+        SYSCALL(0xcf)
Index: kernel/arch/sparc32/src/userspace.c
===================================================================
--- kernel/arch/sparc32/src/userspace.c	(revision a3b034b7b291db132fe044e8c59b9a7b6bfd5277)
+++ kernel/arch/sparc32/src/userspace.c	(revision 2955bb9354df3f00667b00860d6fd3f3bf41ae3f)
@@ -42,22 +42,41 @@
 void userspace(uspace_arg_t *kernel_uarg)
 {
-	printf("userspace(): entry=%p, stack=%p, stacksize=%d\n", kernel_uarg->uspace_entry, kernel_uarg->uspace_stack, kernel_uarg->uspace_stack_size);
+//	printf("userspace(): entry=%p, stack=%p, stacksize=%d\n", kernel_uarg->uspace_entry, kernel_uarg->uspace_stack, kernel_uarg->uspace_stack_size);
 	/* On real hardware this switches the CPU to user
 	   space mode and jumps to kernel_uarg->uspace_entry. */
 
+	uint32_t l0, l1, l2;
 	uint32_t psr = psr_read();
+	uint8_t wim;
 
 	psr &= ~(1 << 7);
 	psr &= ~(1 << 6);
 
+	/* Read invalid window variables */
+	read_from_invalid(&l0, &l1, &l2);
+
+	/* Make current window invalid */
+	wim = (psr & 0x7) + 1;
+	wim = (1 << wim) | (1 >> (8 - wim));
+
 	asm volatile (
 		"flush\n"
 		"mov %[stack], %%sp\n"
-		"mov %[arg], %%o1\n"
+		"mov %[wim], %%wim\n"
+		"ld %[v0], %%o0\n"
+		"ld %[v1], %%o1\n"
+		"ld %[v2], %%o2\n"
+		"call write_to_invalid\n"
+		"nop\n"
+		"ld %[arg], %%o1\n"
 		"jmp %[entry]\n"
 		"mov %[psr], %%psr\n" :: [entry] "r" (kernel_uarg->uspace_entry),
-			   [arg] "r" (kernel_uarg->uspace_uarg),
+			   [arg] "m" (kernel_uarg->uspace_uarg),
 			   [psr] "r" (psr),
-			   [stack] "r" (kernel_uarg->uspace_stack + kernel_uarg->uspace_stack_size));
+			   [wim] "r" ((uint32_t)wim),	
+			   [v0] "m" (l0),
+			   [v1] "m" (l1),
+			   [v2] "m" (l2),
+			   [stack] "r" (kernel_uarg->uspace_stack + kernel_uarg->uspace_stack_size - 64) : "%g3", "%g4");
 
 	while (true);
