Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/Makefile.inc	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -96,4 +96,5 @@
 	arch/$(ARCH)/src/proc/scheduler.c \
 	arch/$(ARCH)/src/proc/thread.c \
+	arch/$(ARCH)/src/trap/mmu.S \
 	arch/$(ARCH)/src/trap/trap_table.S \
 	arch/$(ARCH)/src/trap/trap.c \
Index: kernel/arch/sparc64/include/asm.h
===================================================================
--- kernel/arch/sparc64/include/asm.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/include/asm.h	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -322,4 +322,16 @@
 }
 
+/** Switch to nucleus by setting TL to 1. */
+static inline void nucleus_enter(void)
+{
+	__asm__ volatile ("wrpr %g0, 1, %tl\n");
+}
+
+/** Switch from nucleus by setting TL to 0. */
+static inline void nucleus_leave(void)
+{
+	__asm__ volatile ("wrpr %g0, %g0, %tl\n");
+}
+
 extern void cpu_halt(void);
 extern void cpu_sleep(void);
Index: kernel/arch/sparc64/include/trap/mmu.h
===================================================================
--- kernel/arch/sparc64/include/trap/mmu.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/include/trap/mmu.h	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -122,4 +122,9 @@
 .endm
 
+.macro MEM_ADDRESS_NOT_ALIGNED_HANDLER
+	ba mem_address_not_aligned_handler
+	nop
+.endm
+
 /*
  * Macro used to lower TL when a MMU trap is caused by
Index: kernel/arch/sparc64/src/asm.S
===================================================================
--- kernel/arch/sparc64/src/asm.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/src/asm.S	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -27,4 +27,5 @@
 #
 
+#include <arch/arch.h>
 #include <arch/stack.h>
 #include <arch/regdef.h>
@@ -33,17 +34,12 @@
 .text
 
+.register       %g2, #scratch
+.register       %g3, #scratch
+
+/*
+ * This is the assembly language version of our _memcpy() generated by gcc.
+ */
 .global memcpy
-.global memcpy_from_uspace
-.global memcpy_to_uspace
-.global memcpy_from_uspace_failover_address
-.global memcpy_to_uspace_failover_address
-.global memsetb
-
-
 memcpy:
-memcpy_from_uspace:
-memcpy_to_uspace:
-	.register       %g2, #scratch
-        .register       %g3, #scratch
 	add	%o1, 7, %g1
 	and	%g1, -8, %g1
@@ -100,4 +96,124 @@
 	mov	%o1, %o0
 
+/*
+ * Almost the same as memcpy() except the loads are from userspace.
+ */
+.global memcpy_from_uspace
+memcpy_from_uspace:
+	add	%o1, 7, %g1
+	and	%g1, -8, %g1
+	cmp	%o1, %g1
+	be,pn	%xcc, 3f
+	add	%o0, 7, %g1
+	mov	0, %g3
+0:
+	brz,pn	%o2, 2f
+	mov	0, %g2
+1:
+	lduba	[%g3 + %o1] ASI_AIUS, %g1
+	add	%g2, 1, %g2
+	cmp	%o2, %g2
+	stb	%g1, [%g3 + %o0]
+	bne,pt	%xcc, 1b
+	mov	%g2, %g3
+2:
+	jmp	%o7 + 8			! exit point
+	mov	%o1, %o0
+3:
+	and	%g1, -8, %g1
+	cmp	%o0, %g1
+	bne,pt	%xcc, 0b
+	mov	0, %g3
+	srlx	%o2, 3, %g4
+	brz,pn	%g4, 5f
+	mov	0, %g5
+4:
+	sllx	%g3, 3, %g2
+	add	%g5, 1, %g3
+	ldxa	[%o1 + %g2] ASI_AIUS, %g1
+	mov	%g3, %g5
+	cmp	%g4, %g3
+	bne,pt	%xcc, 4b
+	stx	%g1, [%o0 + %g2]
+5:
+	and	%o2, 7, %o2
+	brz,pn	%o2, 2b
+	sllx	%g4, 3, %g1
+	mov	0, %g2
+	add	%g1, %o0, %o0
+	add	%g1, %o1, %g4
+	mov	0, %g3
+6:
+	lduba	[%g2 + %g4] ASI_AIUS, %g1
+	stb	%g1, [%g2 + %o0]
+	add	%g3, 1, %g2
+	cmp	%o2, %g2
+	bne,pt	%xcc, 6b
+	mov	%g2, %g3
+
+	jmp	%o7 + 8			! exit point
+	mov	%o1, %o0
+
+/*
+ * Almost the same as memcpy() except the stores are to userspace.
+ */
+.global memcpy_to_uspace
+memcpy_to_uspace:
+	add	%o1, 7, %g1
+	and	%g1, -8, %g1
+	cmp	%o1, %g1
+	be,pn	%xcc, 3f
+	add	%o0, 7, %g1
+	mov	0, %g3
+0:
+	brz,pn	%o2, 2f
+	mov	0, %g2
+1:
+	ldub	[%g3 + %o1], %g1
+	add	%g2, 1, %g2
+	cmp	%o2, %g2
+	stba	%g1, [%g3 + %o0] ASI_AIUS
+	bne,pt	%xcc, 1b
+	mov	%g2, %g3
+2:
+	jmp	%o7 + 8			! exit point
+	mov	%o1, %o0
+3:
+	and	%g1, -8, %g1
+	cmp	%o0, %g1
+	bne,pt	%xcc, 0b
+	mov	0, %g3
+	srlx	%o2, 3, %g4
+	brz,pn	%g4, 5f
+	mov	0, %g5
+4:
+	sllx	%g3, 3, %g2
+	add	%g5, 1, %g3
+	ldx	[%o1 + %g2], %g1
+	mov	%g3, %g5
+	cmp	%g4, %g3
+	bne,pt	%xcc, 4b
+	stxa	%g1, [%o0 + %g2] ASI_AIUS
+5:
+	and	%o2, 7, %o2
+	brz,pn	%o2, 2b
+	sllx	%g4, 3, %g1
+	mov	0, %g2
+	add	%g1, %o0, %o0
+	add	%g1, %o1, %g4
+	mov	0, %g3
+6:
+	ldub	[%g2 + %g4], %g1
+	stba	%g1, [%g2 + %o0] ASI_AIUS
+	add	%g3, 1, %g2
+	cmp	%o2, %g2
+	bne,pt	%xcc, 6b
+	mov	%g2, %g3
+
+	jmp	%o7 + 8			! exit point
+	mov	%o1, %o0
+
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
 memcpy_from_uspace_failover_address:
 memcpy_to_uspace_failover_address:
@@ -105,4 +221,5 @@
 	mov	%g0, %o0		! return 0 on failure
 
+.global memsetb
 memsetb:
 	b _memsetb
@@ -155,7 +272,7 @@
 .global switch_to_userspace
 switch_to_userspace:
+	save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
 	flushw
 	wrpr %g0, 0, %cleanwin		! avoid information leak
-	save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
 
 	mov %i3, %o0			! uarg
Index: kernel/arch/sparc64/src/mm/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tlb.c	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/src/mm/tlb.c	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -53,7 +53,7 @@
 static void dtlb_pte_copy(pte_t *t, bool ro);
 static void itlb_pte_copy(pte_t *t);
-static void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str);
 static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char *str);
-static void do_fast_data_access_protection_fault(istate_t *istate, const char *str);
+static void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str);
+static void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str);
 
 char *context_encoding[] = {
@@ -214,11 +214,12 @@
 
 	tag.value = dtlb_tag_access_read();
-	va = tag.vpn * PAGE_SIZE;
+	va = tag.vpn << PAGE_WIDTH;
+
 	if (tag.context == ASID_KERNEL) {
 		if (!tag.vpn) {
 			/* NULL access in kernel */
-			do_fast_data_access_mmu_miss_fault(istate, __FUNCTION__);
-		}
-		do_fast_data_access_mmu_miss_fault(istate, "Unexpected kernel page fault.");
+			do_fast_data_access_mmu_miss_fault(istate, tag, __FUNCTION__);
+		}
+		do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected kernel page fault.");
 	}
 
@@ -239,5 +240,5 @@
 		page_table_unlock(AS, true);
 		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
-			do_fast_data_access_mmu_miss_fault(istate, __FUNCTION__);
+			do_fast_data_access_mmu_miss_fault(istate, tag, __FUNCTION__);
 		}
 	}
@@ -252,5 +253,5 @@
 
 	tag.value = dtlb_tag_access_read();
-	va = tag.vpn * PAGE_SIZE;
+	va = tag.vpn << PAGE_WIDTH;
 
 	page_table_lock(AS, true);
@@ -272,5 +273,5 @@
 		page_table_unlock(AS, true);
 		if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
-			do_fast_data_access_protection_fault(istate, __FUNCTION__);
+			do_fast_data_access_protection_fault(istate, tag, __FUNCTION__);
 		}
 	}
@@ -312,12 +313,10 @@
 }
 
-void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str)
-{
-	tlb_tag_access_reg_t tag;
+void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str)
+{
 	uintptr_t va;
 	char *tpc_str = get_symtab_entry(istate->tpc);
 
-	tag.value = dtlb_tag_access_read();
-	va = tag.vpn * PAGE_SIZE;
+	va = tag.vpn << PAGE_WIDTH;
 
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
@@ -326,12 +325,10 @@
 }
 
-void do_fast_data_access_protection_fault(istate_t *istate, const char *str)
-{
-	tlb_tag_access_reg_t tag;
+void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str)
+{
 	uintptr_t va;
 	char *tpc_str = get_symtab_entry(istate->tpc);
 
-	tag.value = dtlb_tag_access_read();
-	va = tag.vpn * PAGE_SIZE;
+	va = tag.vpn << PAGE_WIDTH;
 
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
@@ -375,14 +372,19 @@
 void tlb_invalidate_asid(asid_t asid)
 {
-	tlb_context_reg_t sc_save, ctx;
-	
-	ctx.v = sc_save.v = mmu_secondary_context_read();
+	tlb_context_reg_t pc_save, ctx;
+	
+	/* switch to nucleus because we are mapped by the primary context */
+	nucleus_enter();
+	
+	ctx.v = pc_save.v = mmu_primary_context_read();
 	ctx.context = asid;
-	mmu_secondary_context_write(ctx.v);
-	
-	itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_SECONDARY, 0);
-	dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_SECONDARY, 0);
-	
-	mmu_secondary_context_write(sc_save.v);
+	mmu_primary_context_write(ctx.v);
+	
+	itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_PRIMARY, 0);
+	dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_PRIMARY, 0);
+	
+	mmu_primary_context_write(pc_save.v);
+	
+	nucleus_leave();
 }
 
@@ -396,16 +398,21 @@
 {
 	int i;
-	tlb_context_reg_t sc_save, ctx;
-	
-	ctx.v = sc_save.v = mmu_secondary_context_read();
+	tlb_context_reg_t pc_save, ctx;
+	
+	/* switch to nucleus because we are mapped by the primary context */
+	nucleus_enter();
+	
+	ctx.v = pc_save.v = mmu_primary_context_read();
 	ctx.context = asid;
-	mmu_secondary_context_write(ctx.v);
+	mmu_primary_context_write(ctx.v);
 	
 	for (i = 0; i < cnt; i++) {
-		itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, page + i * PAGE_SIZE);
-		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, page + i * PAGE_SIZE);
-	}
-	
-	mmu_secondary_context_write(sc_save.v);
+		itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i * PAGE_SIZE);
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i * PAGE_SIZE);
+	}
+	
+	mmu_primary_context_write(pc_save.v);
+	
+	nucleus_leave();
 }
 
Index: kernel/arch/sparc64/src/trap/mmu.S
===================================================================
--- kernel/arch/sparc64/src/trap/mmu.S	(revision 2def78824559e9a326693314a605af8e1e7e690a)
+++ kernel/arch/sparc64/src/trap/mmu.S	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2006 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.
+#
+
+/**
+ * @file
+ * @brief	MMU trap handlers that do not fit into the trap table.
+ */
+
+.register %g2, #scratch
+.register %g3, #scratch
+
+.text
+
+#include <arch/trap/mmu.h>
+#include <arch/trap/trap_table.h>
+#include <arch/regdef.h>
+
+.global mem_address_not_aligned_handler
+mem_address_not_aligned_handler:
+	HANDLE_MMU_TRAPS_FROM_SPILL_OR_FILL
+	PREEMPTIBLE_HANDLER do_mem_address_not_aligned
Index: kernel/arch/sparc64/src/trap/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/trap_table.S	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/arch/sparc64/src/trap/trap_table.S	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -28,5 +28,6 @@
 
 /**
- * This file contains kernel trap table.
+ * @file
+ * @brief This file contains kernel trap table.
  */
 
@@ -85,5 +86,5 @@
 .global mem_address_not_aligned
 mem_address_not_aligned:
-	PREEMPTIBLE_HANDLER do_mem_address_not_aligned
+	MEM_ADDRESS_NOT_ALIGNED_HANDLER
 
 /* TT = 0x41, TL = 0, interrupt_level_1 handler */
@@ -461,5 +462,5 @@
 .global mem_address_not_aligned_high
 mem_address_not_aligned_high:
-	PREEMPTIBLE_HANDLER do_mem_address_not_aligned
+	MEM_ADDRESS_NOT_ALIGNED_HANDLER
 
 /* TT = 0x64, TL > 0, fast_instruction_access_MMU_miss */
@@ -525,4 +526,15 @@
  */
 .macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
+	/*
+	 * ASSERT(%tl == 1)
+	 */
+	rdpr %tl, %g3
+	cmp %g3, 1
+	be 1f
+	nop
+0:	ba 0b					! this for debugging, if we ever get here
+	nop					! it will be easy to find
+
+1:
 .if NOT(\is_syscall)
 	rdpr %tstate, %g3
@@ -536,4 +548,6 @@
 	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
 
+	wrpr %g0, NWINDOW - 1, %cleanwin	! prevent unnecessary clean_window exceptions
+
 	/*
 	 * Switch to kernel stack. The old stack is
@@ -555,10 +569,8 @@
 	/*
 	 * Mark the CANRESTORE windows as OTHER windows.
-	 * Set CLEANWIN to NWINDOW-1 so that clean_window traps do not occur.
 	 */
 	rdpr %canrestore, %l0
 	wrpr %l0, %otherwin
 	wrpr %g0, %canrestore
-	wrpr %g0, NWINDOW - 1, %cleanwin
 
 	/*
@@ -727,5 +739,6 @@
 	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
 	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
-	flush %o7
+	rd %pc, %g1
+	flush %g1
 	
 	rdpr %cwp, %g1
Index: kernel/generic/include/adt/hash_table.h
===================================================================
--- kernel/generic/include/adt/hash_table.h	(revision cfa70adda5479cb3ac144ad8b0e43184319bd909)
+++ kernel/generic/include/adt/hash_table.h	(revision 2def78824559e9a326693314a605af8e1e7e690a)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup genericadt
+/** @addtogroup genericadt
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#ifndef __HASH_TABLE_H__
-#define __HASH_TABLE_H__
+#ifndef KERN_HASH_TABLE_H_
+#define KERN_HASH_TABLE_H_
 
 #include <adt/list.h>
@@ -82,5 +82,4 @@
 #endif
 
- /** @}
+/** @}
  */
-
