Index: boot/arch/sparc64/loader/Makefile
===================================================================
--- boot/arch/sparc64/loader/Makefile	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ boot/arch/sparc64/loader/Makefile	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -58,5 +58,13 @@
 
 COMPONENTS = \
-	$(KERNELDIR)/kernel.bin
+	$(KERNELDIR)/kernel.bin \
+	$(USPACEDIR)/ns/ns \
+	$(USPACEDIR)/init/init \
+	$(USPACEDIR)/fb/fb \
+	$(USPACEDIR)/kbd/kbd \
+	$(USPACEDIR)/console/console \
+	$(USPACEDIR)/tetris/tetris \
+	$(USPACEDIR)/ipcc/ipcc \
+	$(USPACEDIR)/klog/klog
 
 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
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);
 	
Index: uspace/libc/arch/sparc64/_link.ld.in
===================================================================
--- uspace/libc/arch/sparc64/_link.ld.in	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/_link.ld.in	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -8,7 +8,7 @@
 
 SECTIONS {
-	. = 0x1000;
+	. = 0x2000;
 
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
+	.init ALIGN(0x2000) : SUBALIGN(0x2000) {
 		*(.init);
 	} :text
@@ -18,5 +18,9 @@
 	} :text
 	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
+	.got ALIGN(0x2000) : SUBALIGN(0x2000) {
+		 _gp = .;
+		 *(.got*);
+	} :data
+	.data ALIGN(0x2000) : SUBALIGN(0x2000) {
 		*(.data);
 		*(.sdata);
@@ -38,5 +42,5 @@
 	} :data
 
-	. = ALIGN(0x1000);
+	. = ALIGN(0x2000);
 	_heap = .;
 	
Index: uspace/libc/arch/sparc64/include/atomic.h
===================================================================
--- uspace/libc/arch/sparc64/include/atomic.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/atomic.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,4 @@
 /*
- * Copyright (C) 2005 Martin Decky
+ * Copyright (C) 2005 Jakub Jermar
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libcsparc64	
+/** @addtogroup libcsparc64
  * @{
  */
@@ -33,37 +33,66 @@
  */
 
-#ifndef __sparc64_ATOMIC_H__
-#define __sparc64_ATOMIC_H__
+#ifndef LIBC_sparc64_ATOMIC_H_
+#define LIBC_sparc64_ATOMIC_H_
+
+#include <types.h>
+
+/** Atomic add operation.
+ *
+ * Use atomic compare and swap operation to atomically add signed value.
+ *
+ * @param val Atomic variable.
+ * @param i Signed value to be added.
+ *
+ * @return Value of the atomic variable as it existed before addition.
+ */
+static inline long atomic_add(atomic_t *val, int i)
+{
+	uint64_t a, b;
+	volatile uint64_t x = (uint64_t) &val->count;
+
+	__asm__ volatile (
+		"0:\n"
+		"ldx %0, %1\n"
+		"add %1, %3, %2\n"
+		"casx %0, %1, %2\n"
+		"cmp %1, %2\n"
+		"bne 0b\n"		/* The operation failed and must be attempted again if a != b. */
+		"nop\n"
+		: "=m" (*((uint64_t *)x)), "=r" (a), "=r" (b)
+		: "r" (i)
+	);
+
+	return a;
+}
+
+static inline long atomic_preinc(atomic_t *val)
+{
+	return atomic_add(val, 1) + 1;
+}
+
+static inline long atomic_postinc(atomic_t *val)
+{
+	return atomic_add(val, 1);
+}
+
+static inline long atomic_predec(atomic_t *val)
+{
+	return atomic_add(val, -1) - 1;
+}
+
+static inline long atomic_postdec(atomic_t *val)
+{
+	return atomic_add(val, -1);
+}
 
 static inline void atomic_inc(atomic_t *val)
 {
+	(void) atomic_add(val, 1);
 }
 
 static inline void atomic_dec(atomic_t *val)
 {
-}
-
-static inline long atomic_postinc(atomic_t *val)
-{
-	atomic_inc(val);
-	return val->count - 1;
-}
-
-static inline long atomic_postdec(atomic_t *val)
-{
-	atomic_dec(val);
-	return val->count + 1;
-}
-
-static inline long atomic_preinc(atomic_t *val)
-{
-	atomic_inc(val);
-	return val->count;
-}
-
-static inline long atomic_predec(atomic_t *val)
-{
-	atomic_dec(val);
-	return val->count;
+	(void) atomic_add(val, -1);
 }
 
Index: uspace/libc/arch/sparc64/include/config.h
===================================================================
--- uspace/libc/arch/sparc64/include/config.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/config.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libsparc64
+/** @addtogroup libcsparc64
  * @{
  */
@@ -36,5 +36,5 @@
 #define LIBC_sparc64_CONFIG_H_
 
-#define PAGE_WIDTH	12
+#define PAGE_WIDTH	13
 #define PAGE_SIZE	(1<<PAGE_WIDTH)
 
Index: uspace/libc/arch/sparc64/include/context_offset.h
===================================================================
--- uspace/libc/arch/sparc64/include/context_offset.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/context_offset.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,22 @@
+/* This file is automatically generated by gencontext.c. */
 /* struct context */
+#define OFFSET_SP       0x0
+#define OFFSET_PC       0x8
+#define OFFSET_I0       0x10
+#define OFFSET_I1       0x18
+#define OFFSET_I2       0x20
+#define OFFSET_I3       0x28
+#define OFFSET_I4       0x30
+#define OFFSET_I5       0x38
+#define OFFSET_FP       0x40
+#define OFFSET_I7       0x48
+#define OFFSET_L0       0x50
+#define OFFSET_L1       0x58
+#define OFFSET_L2       0x60
+#define OFFSET_L3       0x68
+#define OFFSET_L4       0x70
+#define OFFSET_L5       0x78
+#define OFFSET_L6       0x80
+#define OFFSET_L7       0x88
+#define OFFSET_TP	0x90
 
-/** @}
- */
Index: uspace/libc/arch/sparc64/include/endian.h
===================================================================
--- uspace/libc/arch/sparc64/include/endian.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/endian.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup libcsparc64	
+/** @addtogroup libcsparc64	
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#ifndef __sparc64_ENDIAN_H__
-#define __sparc64_ENDIAN_H__
+#ifndef LIBC_sparc64_ENDIAN_H_
+#define LIBC_sparc64_ENDIAN_H_
 
 #ifndef __LIBC__ENDIAN_H__
@@ -44,5 +44,4 @@
 #endif
 
- /** @}
+/** @}
  */
-
Index: uspace/libc/arch/sparc64/include/limits.h
===================================================================
--- uspace/libc/arch/sparc64/include/limits.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/limits.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -33,6 +33,6 @@
  */
 
-#ifndef __sparc64__LIMITS_H__
-#define __sparc64__LIMITS_H__
+#ifndef LIBC_sparc64__LIMITS_H_
+#define LIBC_sparc64__LIMITS_H_
 
 #define LONG_MIN MIN_INT64
Index: uspace/libc/arch/sparc64/include/psthread.h
===================================================================
--- uspace/libc/arch/sparc64/include/psthread.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/psthread.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,4 @@
 /*
- * Copyright (C) 2006 Martin Decky
+ * Copyright (C) 2005 Jakub Jermar
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libcsparc64	
+/** @addtogroup libcsparc64
  * @{
  */
@@ -33,27 +33,48 @@
  */
 
-#ifndef __LIBC__sparc64__PSTHREAD_H__
-#define __LIBC__sparc64__PSTHREAD_H__
+#ifndef LIBC_sparc64_PSTHREAD_H_
+#define LIBC_sparc64_PSTHREAD_H_
 
+#include <libarch/stack.h>
 #include <types.h>
+#include <align.h>
 
-/* We define our own context_set, because we need to set
- * the TLS pointer to the tcb+0x7000
- *
- * See tls_set in thread.h
+#define SP_DELTA	STACK_WINDOW_SAVE_AREA_SIZE
+
+#ifdef context_set
+#undef context_set
+#endif
+
+#define context_set(c, _pc, stack, size, ptls)								\
+	(c)->pc = ((uintptr_t) _pc) - 8;								\
+	(c)->sp = ((uintptr_t) stack) + ALIGN_UP((size), STACK_ALIGNMENT) - (STACK_BIAS + SP_DELTA);	\
+	(c)->fp = -STACK_BIAS;										\
+	(c)->tp = ptls
+	
+/*
+ * Only save registers that must be preserved across
+ * function calls.
  */
-#define context_set(c, _pc, stack, size, ptls) 			\
-	(c)->pc = (sysarg_t) (_pc);				\
-	(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; 	\
-	(c)->tls = ((sysarg_t) (ptls)) + 0x7000 + sizeof(tcb_t);
-
-#define SP_DELTA	16
-
 typedef struct {
-	uint64_t sp;
-	uint64_t pc;
-	
-	uint64_t tls;
-} __attribute__ ((packed)) context_t;
+	uintptr_t sp;		/* %o6 */
+	uintptr_t pc;		/* %o7 */
+	uint64_t i0;
+	uint64_t i1;
+	uint64_t i2;
+	uint64_t i3;
+	uint64_t i4;
+	uint64_t i5;
+	uintptr_t fp;		/* %i6 */
+	uintptr_t i7;
+	uint64_t l0;
+	uint64_t l1;
+	uint64_t l2;
+	uint64_t l3;
+	uint64_t l4;
+	uint64_t l5;
+	uint64_t l6;
+	uint64_t l7;
+	uint64_t tp;		/* %g7 */
+} context_t;
 
 #endif
Index: uspace/libc/arch/sparc64/include/stack.h
===================================================================
--- uspace/libc/arch/sparc64/include/stack.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ uspace/libc/arch/sparc64/include/stack.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -0,0 +1,56 @@
+/*
+ * 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 libcsparc64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_sparc64_STACK_H_
+#define LIBC_sparc64_STACK_H_
+
+#define STACK_ITEM_SIZE			8
+
+/** According to SPARC Compliance Definition, every stack frame is 16-byte aligned. */
+#define STACK_ALIGNMENT			16
+
+/**
+ * 16-extended-word save area for %i[0-7] and %l[0-7] registers.
+ */
+#define STACK_WINDOW_SAVE_AREA_SIZE	(16*STACK_ITEM_SIZE)
+
+/**
+ * By convention, the actual top of the stack is %sp + STACK_BIAS.
+ */
+#define STACK_BIAS            2047
+
+#endif
+
+/** @}
+ */
Index: uspace/libc/arch/sparc64/include/stackarg.h
===================================================================
--- uspace/libc/arch/sparc64/include/stackarg.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/stackarg.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -33,10 +33,9 @@
  */
 
-#ifndef __LIBC__STACKARG_H__
-#define __LIBC__STACKARG_H__
+#ifndef LIBC_sparc64_STACKARG_H_
+#define LIBC_sparc64_STACKARG_H_
 
 #endif
 
-
 /** @}
  */
Index: uspace/libc/arch/sparc64/include/syscall.h
===================================================================
--- uspace/libc/arch/sparc64/include/syscall.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/syscall.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libc
+/** @addtogroup libcsparc64
  * @{
  */
Index: uspace/libc/arch/sparc64/include/thread.h
===================================================================
--- uspace/libc/arch/sparc64/include/thread.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/thread.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,5 @@
 /*
- * Copyright (C) 2006 Martin Decky
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * Copyright (C) 2006 Jakub Jermar
  * All rights reserved.
  *
@@ -27,16 +28,21 @@
  */
 
-/** @addtogroup libcsparc64	
+/** @addtogroup libcsparc64
  * @{
  */
-/** @file
+/**
+ * @file
+ * @brief	sparc64 TLS functions.
+ *
+ * The implementation is based on the IA-32 implementation which was also
+ * designed by Sun and is virtually the same, except the TCB is stored in
+ * %g7 (of the normal set).
  */
 
-#ifndef __LIBC__sparc64__THREAD_H__
-#define __LIBC__sparc64__THREAD_H__
-
-#define PPC_TP_OFFSET 0x7000
+#ifndef LIBC_sparc64_THREAD_H_
+#define LIBC_sparc64_THREAD_H_
 
 typedef struct {
+	void *self;
 	void *pst_data;
 } tcb_t;
@@ -44,11 +50,14 @@
 static inline void __tcb_set(tcb_t *tcb)
 {
-	void *tp = tcb;
-	tp += PPC_TP_OFFSET + sizeof(tcb_t);
+	__asm__ volatile ("mov %0, %%g7\n" : : "r" (tcb) : "g7");
 }
 
-static inline tcb_t *__tcb_get(void)
+static inline tcb_t * __tcb_get(void)
 {
-	return (tcb_t *)(PPC_TP_OFFSET - sizeof(tcb_t));
+	void *retval;
+
+	__asm__ volatile ("mov %%g7, %0\n" : "=r" (retval));
+
+	return retval;
 }
 
Index: uspace/libc/arch/sparc64/include/types.h
===================================================================
--- uspace/libc/arch/sparc64/include/types.h	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/include/types.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -36,10 +36,10 @@
 #define LIBC_sparc64_TYPES_H_
 
-typedef unsigned int sysarg_t;
-typedef unsigned int size_t;
-typedef signed int ssize_t;
+typedef unsigned long sysarg_t;
+typedef unsigned long size_t;
+typedef signed long ssize_t;
 typedef ssize_t off_t;
 
-typedef char int8_t;
+typedef signed char int8_t;
 typedef short int int16_t;
 typedef int int32_t;
Index: uspace/libc/arch/sparc64/src/entry.s
===================================================================
--- uspace/libc/arch/sparc64/src/entry.s	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/src/entry.s	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -38,4 +38,20 @@
 #
 __entry:
+	sethi %hi(_gp), %l7
+	call __main
+	or %l7, %lo(_gp), %l7
+	call __io_init
+	nop
+	call main
+	nop
+	call __exit
+	nop
 
 __entry_driver:
+	sethi %hi(_gp), %l7
+	call __main
+	or %l7, %lo(_gp), %l7
+	call main
+	nop
+	call __exit
+	nop
Index: uspace/libc/arch/sparc64/src/psthread.S
===================================================================
--- uspace/libc/arch/sparc64/src/psthread.S	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/src/psthread.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,4 @@
 #
-# Copyright (C) 2006 Martin Decky
+# Copyright (C) 2005 Jakub Jermar
 # All rights reserved.
 #
@@ -27,13 +27,79 @@
 #
 
-.text
+#include <libarch/context_offset.h>
+
+/**
+ * Both context_save_arch() and context_restore_arch() are
+ * leaf-optimized procedures. This kind of optimization
+ * is very important and prevents any implicit window
+ * spill/fill/clean traps in these very core kernel
+ * functions.
+ */
+	
+.text   
 
 .global context_save
 .global context_restore
 
-#include <libarch/context_offset.h>
+.macro CONTEXT_STORE r
+	stx %sp, [\r + OFFSET_SP]
+	stx %o7, [\r + OFFSET_PC]
+	stx %i0, [\r + OFFSET_I0]
+	stx %i1, [\r + OFFSET_I1]
+	stx %i2, [\r + OFFSET_I2]
+	stx %i3, [\r + OFFSET_I3]
+	stx %i4, [\r + OFFSET_I4]
+	stx %i5, [\r + OFFSET_I5]
+	stx %fp, [\r + OFFSET_FP]
+	stx %i7, [\r + OFFSET_I7]
+	stx %l0, [\r + OFFSET_L0]
+	stx %l1, [\r + OFFSET_L1]
+	stx %l2, [\r + OFFSET_L2]
+	stx %l3, [\r + OFFSET_L3]
+	stx %l4, [\r + OFFSET_L4]
+	stx %l5, [\r + OFFSET_L5]
+	stx %l6, [\r + OFFSET_L6]
+	stx %l7, [\r + OFFSET_L7]
+	stx %g7, [\r + OFFSET_TP]
+.endm
+
+.macro CONTEXT_LOAD r
+	ldx [\r + OFFSET_SP], %sp
+	ldx [\r + OFFSET_PC], %o7
+	ldx [\r + OFFSET_I0], %i0
+	ldx [\r + OFFSET_I1], %i1
+	ldx [\r + OFFSET_I2], %i2
+	ldx [\r + OFFSET_I3], %i3
+	ldx [\r + OFFSET_I4], %i4
+	ldx [\r + OFFSET_I5], %i5
+	ldx [\r + OFFSET_FP], %fp
+	ldx [\r + OFFSET_I7], %i7
+	ldx [\r + OFFSET_L0], %l0
+	ldx [\r + OFFSET_L1], %l1
+	ldx [\r + OFFSET_L2], %l2
+	ldx [\r + OFFSET_L3], %l3
+	ldx [\r + OFFSET_L4], %l4
+	ldx [\r + OFFSET_L5], %l5
+	ldx [\r + OFFSET_L6], %l6
+	ldx [\r + OFFSET_L7], %l7
+	ldx [\r + OFFSET_TP], %g7
+.endm
 
 context_save:
-
+	CONTEXT_STORE %o0
+	retl
+	mov 1, %o0		! context_save_arch returns 1
 
 context_restore:
+	#
+	# Flush all active windows.
+	# This is essential, because CONTEXT_LOAD overwrites
+	# %sp of CWP - 1 with the value written to %fp of CWP.
+	# Flushing all active windows mitigates this problem
+	# as CWP - 1 becomes the overlap window.
+	#		
+	flushw
+	
+	CONTEXT_LOAD %o0
+	retl
+	xor %o0, %o0, %o0	! context_restore_arch returns 0
Index: uspace/libc/arch/sparc64/src/thread.c
===================================================================
--- uspace/libc/arch/sparc64/src/thread.c	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/src/thread.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -27,8 +27,10 @@
  */
 
-/** @addtogroup libcsparc64	
+/** @addtogroup libcsparc64 sparc64
+ * @ingroup lc
  * @{
  */
 /** @file
+ *
  */
 
@@ -40,18 +42,21 @@
  * @param data Start of data section
  * @return pointer to tcb_t structure
- *
  */
 tcb_t * __alloc_tls(void **data, size_t size)
 {
-	tcb_t *result;
+	tcb_t *tcb;
+	
+	*data = malloc(sizeof(tcb_t) + size);
 
-	result = malloc(sizeof(tcb_t) + size);
-	*data = ((void *)result) + sizeof(tcb_t);
-	return result;
+	tcb = (tcb_t *) (*data + size);
+	tcb->self = tcb;
+
+	return tcb;
 }
 
 void __free_tls_arch(tcb_t *tcb, size_t size)
 {
-	free(tcb);
+	void *start = ((void *)tcb) - size;
+	free(start);
 }
 
Index: uspace/libc/arch/sparc64/src/thread_entry.s
===================================================================
--- uspace/libc/arch/sparc64/src/thread_entry.s	(revision 002e6136848b41de207a590bc212ce31cce81d12)
+++ uspace/libc/arch/sparc64/src/thread_entry.s	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
@@ -1,4 +1,4 @@
 #
-# Copyright (C) 2006 Martin Decky
+# Copyright (C) 2006 Jakub Jermar
 # All rights reserved.
 #
@@ -35,4 +35,9 @@
 #
 __thread_entry:
-
+	sethi %hi(_gp), %l7	
+	call __thread_main		! %o0 contains address of uarg
+	or %l7, %lo(_gp), %l7
+	
+	! not reached
+	
 .end __thread_entry
