Index: kernel/arch/sparc64/include/atomic.h
===================================================================
--- kernel/arch/sparc64/include/atomic.h	(revision f1d1f5d3d65116db3fe2744bb3cf38c85e99f14c)
+++ kernel/arch/sparc64/include/atomic.h	(revision 57da95c482edb0cea2f17139f72f308e960ddd0f)
@@ -57,5 +57,5 @@
 		a = *((uint64_t *) x);
 		b = a + i;
-		__asm__ volatile ("casx %0, %1, %2\n": "+m" (*((uint64_t *)x)), "+r" (a), "+r" (b));
+		__asm__ volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a));
 	} while (a != b);
 
Index: kernel/arch/sparc64/include/mm/tsb.h
===================================================================
--- kernel/arch/sparc64/include/mm/tsb.h	(revision f1d1f5d3d65116db3fe2744bb3cf38c85e99f14c)
+++ kernel/arch/sparc64/include/mm/tsb.h	(revision 57da95c482edb0cea2f17139f72f308e960ddd0f)
@@ -37,4 +37,5 @@
 
 #include <arch/mm/tte.h>
+#include <arch/mm/mmu.h>
 #include <arch/types.h>
 #include <typedefs.h>
@@ -47,6 +48,7 @@
  * in TLBs - only one TLB entry will do.
  */
-#define ITSB_ENTRY_COUNT		2048
-#define DTSB_ENTRY_COUNT		2048
+#define TSB_SIZE			2			/* when changing this, change as.c as well */
+#define ITSB_ENTRY_COUNT		(512*(1<<TSB_SIZE))
+#define DTSB_ENTRY_COUNT		(512*(1<<TSB_SIZE))
 
 struct tsb_entry {
@@ -54,6 +56,56 @@
 	tte_data_t data;
 } __attribute__ ((packed));
+typedef struct tsb_entry tsb_entry_t;
 
-typedef struct tsb_entry tsb_entry_t;
+/** TSB Base register. */
+union tsb_base_reg {
+	uint64_t value;
+	struct {
+		uint64_t base : 51;	/**< TSB base address, bits 63:13. */
+		unsigned split : 1;	/**< Split vs. common TSB for 8K and 64K pages.
+					  *  HelenOS uses only 8K pages for user mappings,
+					  *  so we always set this to 0.
+					  */
+		unsigned : 9;
+		unsigned size : 3;	/**< TSB size. Number of entries is 512*2^size. */
+	} __attribute__ ((packed));
+};
+typedef union tsb_base_reg tsb_base_reg_t;
+
+/** Read ITSB Base register.
+ *
+ * @return Content of the ITSB Base register.
+ */
+static inline uint64_t itsb_base_read(void)
+{
+	return asi_u64_read(ASI_IMMU, VA_IMMU_TSB_BASE);
+}
+
+/** Read DTSB Base register.
+ *
+ * @return Content of the DTSB Base register.
+ */
+static inline uint64_t dtsb_base_read(void)
+{
+	return asi_u64_read(ASI_DMMU, VA_DMMU_TSB_BASE);
+}
+
+/** Write ITSB Base register.
+ *
+ * @param v New content of the ITSB Base register.
+ */
+static inline void itsb_base_write(uint64_t v)
+{
+	asi_u64_write(ASI_IMMU, VA_IMMU_TSB_BASE, v);
+}
+
+/** Write DTSB Base register.
+ *
+ * @param v New content of the DTSB Base register.
+ */
+static inline void dtsb_base_write(uint64_t v)
+{
+	asi_u64_write(ASI_DMMU, VA_DMMU_TSB_BASE, v);
+}
 
 extern void tsb_invalidate(as_t *as, uintptr_t page, count_t pages);
Index: kernel/arch/sparc64/src/mm/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/as.c	(revision f1d1f5d3d65116db3fe2744bb3cf38c85e99f14c)
+++ kernel/arch/sparc64/src/mm/as.c	(revision 57da95c482edb0cea2f17139f72f308e960ddd0f)
@@ -37,4 +37,9 @@
 #include <genarch/mm/as_ht.h>
 #include <genarch/mm/asid_fifo.h>
+#include <debug.h>
+
+#ifdef CONFIG_TSB
+#include <arch/mm/tsb.h>
+#endif
 
 /** Architecture dependent address space init. */
@@ -45,7 +50,20 @@
 }
 
+/** Perform sparc64-specific tasks when an address space becomes active on the processor.
+ *
+ * Install ASID and map TSBs.
+ *
+ * @param as Address space.
+ */
 void as_install_arch(as_t *as)
 {
 	tlb_context_reg_t ctx;
+	
+	/*
+	 * Note that we don't lock the address space.
+	 * That's correct - we can afford it here
+	 * because we only read members that are
+	 * currently read-only.
+	 */
 	
 	/*
@@ -59,4 +77,75 @@
 	ctx.context = as->asid;
 	mmu_secondary_context_write(ctx.v);
+
+#ifdef CONFIG_TSB	
+	if (as != AS_KERNEL) {
+		uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+		ASSERT(as->arch.itsb && as->arch.dtsb);
+
+		uintptr_t tsb = as->arch.itsb;
+		
+		if (!overlaps(tsb, 8*PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+			/*
+			 * TSBs were allocated from memory not covered
+			 * by the locked 4M kernel DTLB entry. We need
+			 * to map both TSBs explicitly.
+			 */
+			dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+			dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
+		}
+		
+		/*
+		 * Setup TSB Base registers.
+		 */
+		tsb_base_reg_t tsb_base;
+		
+		tsb_base.value = 0;
+		tsb_base.size = TSB_SIZE;
+		tsb_base.split = 0;
+
+		tsb_base.base = as->arch.itsb >> PAGE_WIDTH;
+		itsb_base_write(tsb_base.value);
+		tsb_base.base = as->arch.dtsb >> PAGE_WIDTH;
+		dtsb_base_write(tsb_base.value);
+	}
+#endif
+}
+
+/** Perform sparc64-specific tasks when an address space is removed from the processor.
+ *
+ * Demap TSBs.
+ *
+ * @param as Address space.
+ */
+void as_deinstall_arch(as_t *as)
+{
+
+	/*
+	 * Note that we don't lock the address space.
+	 * That's correct - we can afford it here
+	 * because we only read members that are
+	 * currently read-only.
+	 */
+
+#ifdef CONFIG_TSB
+	if (as != AS_KERNEL) {
+		uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+		ASSERT(as->arch.itsb && as->arch.dtsb);
+
+		uintptr_t tsb = as->arch.itsb;
+		
+		if (!overlaps(tsb, 8*PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+			/*
+			 * TSBs were allocated from memory not covered
+			 * by the locked 4M kernel DTLB entry. We need
+			 * to demap the entry installed by as_install_arch().
+			 */
+			dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+		}
+		
+	}
+#endif
 }
 
Index: kernel/arch/sparc64/src/proc/scheduler.c
===================================================================
--- kernel/arch/sparc64/src/proc/scheduler.c	(revision f1d1f5d3d65116db3fe2744bb3cf38c85e99f14c)
+++ kernel/arch/sparc64/src/proc/scheduler.c	(revision 57da95c482edb0cea2f17139f72f308e960ddd0f)
@@ -121,7 +121,6 @@
 	if ((THREAD->flags & THREAD_FLAG_USPACE)) {
 		/*
-		 * If this thread executes also in userspace, we have to force all
-		 * its still-active userspace windows into the userspace window buffer
-		 * and demap the buffer from DTLB.
+		 * If this thread executes also in userspace, we have to
+		 * demap the userspace window buffer from DTLB.
 		 */
 		ASSERT(THREAD->arch.uspace_window_buffer);
