Index: kernel/arch/sparc32/include/arch/arch.h
===================================================================
--- kernel/arch/sparc32/include/arch/arch.h	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/include/arch/arch.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -41,4 +41,6 @@
 #include <typedefs.h>
 
+#define	NWINDOWS	8
+
 /* ASI assignments: */
 #define	ASI_CACHEMISS	0x01
@@ -63,5 +65,8 @@
 } bootinfo_t;
 
-void arch_pre_main(bootinfo_t *bootinfo);
+extern uintptr_t kernel_sp;
+extern uintptr_t uspace_wbuf;
+
+extern void arch_pre_main(void *unused, bootinfo_t *bootinfo);
 
 #endif
Index: kernel/arch/sparc32/include/arch/elf.h
===================================================================
--- kernel/arch/sparc32/include/arch/elf.h	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/include/arch/elf.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup abs32le
+/** @addtogroup sparc32
  * @{
  */
@@ -33,9 +33,9 @@
  */
 
-#ifndef KERN_abs32le_ELF_H_
-#define KERN_abs32le_ELF_H_
+#ifndef KERN_sparc32_ELF_H_
+#define KERN_sparc32_ELF_H_
 
-#define ELF_MACHINE        EM_NO
-#define ELF_DATA_ENCODING  ELFDATA2LSB
+#define ELF_MACHINE        EM_SPARC
+#define ELF_DATA_ENCODING  ELFDATA2MSB
 #define ELF_CLASS          ELFCLASS32
 
Index: kernel/arch/sparc32/include/arch/istate.h
===================================================================
--- kernel/arch/sparc32/include/arch/istate.h	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/include/arch/istate.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup abs32leinterrupt
+/** @addtogroup sparc32interrupt
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#ifndef KERN_abs32le_ISTATE_H_
-#define KERN_abs32le_ISTATE_H_
+#ifndef KERN_sparc32_ISTATE_H_
+#define KERN_sparc32_ISTATE_H_
 
 #include <trace.h>
@@ -54,6 +54,7 @@
  */
 typedef struct istate {
-	uintptr_t ip;
-	uintptr_t fp;
+	uintptr_t pstate;
+	uintptr_t pc;
+	uintptr_t npc;
 	uint32_t stack[];
 } istate_t;
@@ -64,6 +65,6 @@
 	/* On real hardware this checks whether the interrupted
 	   context originated from user space. */
-	
-	return !(istate->ip & UINT32_C(0x80000000));
+
+	return !(istate->pc & UINT32_C(0x80000000));
 }
 
@@ -74,5 +75,5 @@
 	/* On real hardware this sets the instruction pointer. */
 	
-	istate->ip = retaddr;
+	istate->pc = retaddr;
 }
 
@@ -82,5 +83,5 @@
 	/* On real hardware this returns the instruction pointer. */
 	
-	return istate->ip;
+	return istate->pc;
 }
 
@@ -90,5 +91,5 @@
 	/* On real hardware this returns the frame pointer. */
 	
-	return istate->fp;
+	return 0;//istate->fp;
 }
 
Index: kernel/arch/sparc32/include/arch/mm/tlb.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/tlb.h	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/include/arch/mm/tlb.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup abs32lemm
+/** @addtogroup sparc32mm
  * @{
  */
@@ -33,6 +33,12 @@
  */
 
-#ifndef KERN_abs32le_TLB_H_
-#define KERN_abs32le_TLB_H_
+#ifndef KERN_sparc32_TLB_H_
+#define KERN_sparc32_TLB_H_
+
+#define	MMU_CONTROL		0x000
+#define	MMU_CONTEXT_TABLE	0x100
+#define	MMU_CONTEXT		0x200
+#define	MMU_FAULT_STATUS	0x300
+#define	MMU_FAULT_ADDRESS	0x400
 
 #endif
Index: kernel/arch/sparc32/include/arch/proc/thread.h
===================================================================
--- kernel/arch/sparc32/include/arch/proc/thread.h	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/include/arch/proc/thread.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup abs32leproc
+/** @addtogroup sparc32proc
  * @{
  */
@@ -33,14 +33,13 @@
  */
 
-#ifndef KERN_abs32le_THREAD_H_
-#define KERN_abs32le_THREAD_H_
+#ifndef KERN_sparc32_THREAD_H_
+#define KERN_sparc32_THREAD_H_
 
 #include <typedefs.h>
 
 typedef struct {
+	/** Buffer for register windows with userspace content. */
+	uint8_t *uspace_window_buffer;
 } thread_arch_t;
-
-#define thr_constructor_arch(thr)
-#define thr_destructor_arch(thr)
 
 #endif
Index: kernel/arch/sparc32/include/arch/regwin.h
===================================================================
--- kernel/arch/sparc32/include/arch/regwin.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
+++ kernel/arch/sparc32/include/arch/regwin.h	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup sparc32interrupt
+ * @{
+ */
+/**
+ * @file
+ * @brief This file contains register window trap handlers.
+ */
+
+#ifndef KERN_sparc32_REGWIN_H_
+#define KERN_sparc32_REGWIN_H_
+
+#include <arch/stack.h>
+#include <arch/arch.h>
+#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
+
+/* Window Save Area offsets. */
+#define L0_OFFSET	0
+#define L1_OFFSET	4
+#define L2_OFFSET	8
+#define L3_OFFSET	12
+#define L4_OFFSET	16
+#define L5_OFFSET	20
+#define L6_OFFSET	24
+#define L7_OFFSET	28
+#define I0_OFFSET	32
+#define I1_OFFSET	36
+#define I2_OFFSET	40
+#define I3_OFFSET	44
+#define I4_OFFSET	48
+#define I5_OFFSET	52
+#define I6_OFFSET	56
+#define I7_OFFSET	60
+
+/* Uspace Window Buffer constants. */
+#define UWB_SIZE	((NWINDOWS - 1) * STACK_WINDOW_SAVE_AREA_SIZE)
+#define UWB_ALIGNMENT	1024
+#define UWB_ASIZE	ALIGN_UP(UWB_SIZE, UWB_ALIGNMENT)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/sparc32/src/exception.c
===================================================================
--- kernel/arch/sparc32/src/exception.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/exception.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -48,6 +48,7 @@
 void instruction_access_exception(int n, istate_t *istate)
 {
-	fault_if_from_uspace(istate, "%s.", __func__);
-	panic_badtrap(istate, n, "%s.", __func__);
+	page_fault(n, istate);
+//	fault_if_from_uspace(istate, "%s.", __func__);
+//	panic_badtrap(istate, n, "%s.", __func__);
 }
 
@@ -104,6 +105,7 @@
 void data_access_exception(int n, istate_t *istate)
 {
-	fault_if_from_uspace(istate, "%s.", __func__);
-	panic_badtrap(istate, n, "%s.", __func__);
+	page_fault(n, istate);
+//	fault_if_from_uspace(istate, "%s.", __func__);
+//	panic_badtrap(istate, n, "%s.", __func__);
 }
 
@@ -111,6 +113,7 @@
 void data_access_error(int n, istate_t *istate)
 {
-	fault_if_from_uspace(istate, "%s.", __func__);
-	panic_badtrap(istate, n, "%s.", __func__);
+	page_fault(n, istate);
+//	fault_if_from_uspace(istate, "%s.", __func__);
+//	panic_badtrap(istate, n, "%s.", __func__);
 }
 
@@ -118,6 +121,7 @@
 void data_store_error(int n, istate_t *istate)
 {
-	fault_if_from_uspace(istate, "%s.", __func__);
-	panic_badtrap(istate, n, "%s.", __func__);
+	page_fault(n, istate);
+//	fault_if_from_uspace(istate, "%s.", __func__);
+//	panic_badtrap(istate, n, "%s.", __func__);
 }
 /** Handle data_access_error. (0x2c) */
Index: kernel/arch/sparc32/src/mm/frame.c
===================================================================
--- kernel/arch/sparc32/src/mm/frame.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/mm/frame.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -60,4 +60,6 @@
 		    BOOT_PT_START_FRAME + BOOT_PT_SIZE_FRAMES,
 		    ZONE_AVAILABLE | ZONE_LOWMEM);
+
+		printf("low_zone: %d frames\n", SIZE2FRAMES(size));
 	} else {
 		pfn_t conf = zone_external_conf_alloc(SIZE2FRAMES(size));
@@ -65,6 +67,9 @@
 			zone_create(ADDR2PFN(base), SIZE2FRAMES(size), conf,
 			    ZONE_AVAILABLE | ZONE_HIGHMEM);
+
+		printf("high zone: %d frames\n", SIZE2FRAMES(size));
 	}
-	
+
+	printf("free: %d\n", frame_total_free_get());
 }
 
@@ -81,4 +86,5 @@
 	/* blacklist boot page table */
 	frame_mark_unavailable(BOOT_PT_START_FRAME, BOOT_PT_SIZE_FRAMES);
+	printf("free: %d\n", frame_total_free_get());
 	//machine_frame_init();
 }
Index: kernel/arch/sparc32/src/mm/page.c
===================================================================
--- kernel/arch/sparc32/src/mm/page.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/mm/page.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -34,4 +34,6 @@
 
 #include <arch/mm/page.h>
+#include <arch/mm/page_fault.h>
+#include <arch/mm/tlb.h>
 #include <genarch/mm/page_pt.h>
 #include <arch/mm/frame.h>
@@ -75,5 +77,5 @@
 
 	/* Switch MMU to new context table */
-	asi_u32_write(ASI_MMUREGS, 0x100, KA2PA(as_context_table) >> 4);
+	asi_u32_write(ASI_MMUREGS, MMU_CONTEXT_TABLE, KA2PA(as_context_table) >> 4);
 
 	//boot_page_table_free();
@@ -82,4 +84,19 @@
 void page_fault(unsigned int n __attribute__((unused)), istate_t *istate)
 {
+	uint32_t fault_status = asi_u32_read(ASI_MMUREGS, MMU_FAULT_STATUS);
+	uintptr_t fault_address = asi_u32_read(ASI_MMUREGS, MMU_FAULT_ADDRESS);
+	mmu_fault_status_t *fault = (mmu_fault_status_t *)&fault_status;
+	mmu_fault_type_t type = (mmu_fault_type_t)fault->ft;
+
+	printf("page fault on address 0x%08x, status 0x%08x\n", fault_address, fault_status);
+
+	if (type == FAULT_TYPE_LOAD_USER_DATA)	
+		as_page_fault(fault_address, PF_ACCESS_READ, istate);
+
+	if (type == FAULT_TYPE_EXECUTE_USER)
+		as_page_fault(fault_address, PF_ACCESS_EXEC, istate);
+
+	if (type == FAULT_TYPE_STORE_USER_DATA || type == FAULT_TYPE_STORE_USER_INSTRUCTION)
+		as_page_fault(fault_address, PF_ACCESS_WRITE, istate);
 }
 
Index: kernel/arch/sparc32/src/proc/scheduler.c
===================================================================
--- kernel/arch/sparc32/src/proc/scheduler.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/proc/scheduler.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Martin Decky
+ * Copyright (c) 2013 Jakub Klama
  * All rights reserved.
  *
@@ -34,4 +34,7 @@
 
 #include <proc/scheduler.h>
+#include <proc/thread.h>
+#include <arch.h>
+#include <arch/arch.h>
 
 void before_task_runs_arch(void)
@@ -41,4 +44,6 @@
 void before_thread_runs_arch(void)
 {
+	kernel_sp = (uintptr_t) THREAD->kstack + STACK_SIZE;
+	uspace_wbuf = (uintptr_t) THREAD->arch.uspace_window_buffer;
 }
 
Index: kernel/arch/sparc32/src/proc/thread.c
===================================================================
--- kernel/arch/sparc32/src/proc/thread.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/proc/thread.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -33,8 +33,43 @@
  */
 
+#include <arch/regwin.h>
 #include <proc/thread.h>
+
+void thr_constructor_arch(thread_t *t)
+{
+	t->arch.uspace_window_buffer = NULL;
+}
+
+void thr_destructor_arch(thread_t *t)
+{
+	if (t->arch.uspace_window_buffer) {
+		uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
+		/*
+		 * Mind the possible alignment of the userspace window buffer
+		 * belonging to a killed thread.
+		 */
+		free((uint8_t *) ALIGN_DOWN(uw_buf, UWB_ALIGNMENT));
+	}
+}
 
 void thread_create_arch(thread_t *t)
 {
+	if ((t->uspace) && (!t->arch.uspace_window_buffer))
+		{
+		/*
+		 * The thread needs userspace window buffer and the object
+		 * returned from the slab allocator doesn't have any.
+		 */
+		t->arch.uspace_window_buffer = malloc(UWB_ASIZE, 0);
+	} else {
+		uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
+
+		/*
+		 * Mind the possible alignment of the userspace window buffer
+		 * belonging to a killed thread.
+		 */
+		t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf,
+		    UWB_ASIZE);
+	}
 }
 
Index: kernel/arch/sparc32/src/sparc32.c
===================================================================
--- kernel/arch/sparc32/src/sparc32.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/sparc32.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -56,5 +56,5 @@
 char memcpy_to_uspace_failover_address;
 
-void arch_pre_main(bootinfo_t *bootinfo)
+void arch_pre_main(void *unused, bootinfo_t *bootinfo)
 {
 	init.cnt = min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
Index: kernel/arch/sparc32/src/start.S
===================================================================
--- kernel/arch/sparc32/src/start.S	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/start.S	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -31,4 +31,6 @@
 .global kernel_image_start
 .global early_putchar
+.global kernel_sp
+.global uspace_wbuf
 
 kernel_image_start:
@@ -68,4 +70,10 @@
 	nop
 
+kernel_sp:
+.space 4
+
+uspace_wbuf:
+.space 4
+
 .align 16
 .space 4096
Index: kernel/arch/sparc32/src/trap_table.S
===================================================================
--- kernel/arch/sparc32/src/trap_table.S	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/trap_table.S	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -33,4 +33,5 @@
 .global trap_table
 .global reset_trap
+.global preemptible_trap
 .global window_overflow_trap
 .global window_underflow_trap
@@ -116,10 +117,50 @@
         rett %l2
 
-#define	TRAP(_vector, _handler) \
+preemptible_trap:
+	/* Enable traps */
+	mov %psr, %l0
+	or %l0, (1 << 5), %l0
+	mov %l0, %psr
+
+	/* Check whether previous mode was usermode */
+	and %l0, (1 << 6), %l0
+	cmp %l0, 0
+	bne 1f
+	nop
+
+	/* Set up stack */
+	set kernel_sp, %l4
+	ld [%l4], %sp
+	mov %sp, %fp
+1:	sub %sp, 112, %sp
+
+	/* Save trap data on stack */
+	st %l1, [%fp - 4]
+	st %l2, [%fp - 8]
+	st %l0, [%fp - 12]
+
+	/* Jump to actual subroutine */
+	mov 1, %o0
+	jmp %g1
+	sub %fp, 12, %o1
+
+	/* Return from handler */
+	ld [%fp - 4], %l1
+	ld [%fp - 8], %l2
+	jmp %l1
+	rett %l2
+
+#define	STRAP(_vector, _handler) \
 	.org trap_table + _vector * TRAP_ENTRY_SIZE; \
 	mov %psr, %l0 ; \
 	sethi %hi(_handler), %l4 ; \
-	jmp %l4 + %lo(_handler); \
-	mov _vector, %l3 ;
+	jmp %lo(_handler) + %l4 ; \
+	nop
+
+#define	TRAP(_vector, _handler) \
+	.org trap_table + _vector * TRAP_ENTRY_SIZE; \
+	sethi %hi(_handler), %g1 ; \
+	b preemptible_trap ; \
+	or %g1, %lo(_handler), %g1 ;
 
 #define	INTERRUPT(_vector, _priority) \
@@ -141,6 +182,6 @@
 	TRAP(0x3, privileged_instruction)
 	TRAP(0x4, fp_disabled)
-	TRAP(0x5, window_overflow_trap)
-	TRAP(0x6, window_underflow_trap)
+	STRAP(0x5, window_overflow_trap)
+	STRAP(0x6, window_underflow_trap)
 	TRAP(0x7, mem_address_not_aligned)
 	TRAP(0x8, fp_exception)
Index: kernel/arch/sparc32/src/userspace.c
===================================================================
--- kernel/arch/sparc32/src/userspace.c	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ kernel/arch/sparc32/src/userspace.c	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -36,4 +36,5 @@
 #include <typedefs.h>
 #include <arch.h>
+#include <arch/asm.h>
 #include <abi/proc/uarg.h>
 #include <mm/as.h>
@@ -41,7 +42,22 @@
 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);
 	/* On real hardware this switches the CPU to user
 	   space mode and jumps to kernel_uarg->uspace_entry. */
-	
+
+	uint32_t psr = psr_read();
+
+	psr &= ~(1 << 7);
+	psr &= ~(1 << 6);
+
+	asm volatile (
+		"mov %[stack], %%sp\n"
+		"mov %[psr], %%psr\n"
+		"nop\n"
+		"jmp %[entry]\n"
+		"nop\n" :: [entry] "r" (kernel_uarg->uspace_entry),
+			   [psr] "r" (psr),
+			   [stack] "r" (kernel_uarg->uspace_stack + kernel_uarg->uspace_stack_size));
+
 	while (true);
 }
Index: uspace/lib/c/arch/sparc32/src/entry.s
===================================================================
--- uspace/lib/c/arch/sparc32/src/entry.s	(revision 80d9d8391bc56eab2b15e4a28cb1562b86e17ea6)
+++ uspace/lib/c/arch/sparc32/src/entry.s	(revision 1f12fab8d2a64b3a84577b08af23f9f1f4bf9fc9)
@@ -44,5 +44,6 @@
 	save %sp, -176, %sp
 # XXX	flushw
-	add %g0, -0x7ff, %fp
+#	add %g0, -0x7ff, %fp
+	set 0x80000000, %fp
 	
 	# Pass pcb_ptr as the first argument to __main()
