Index: kernel/arch/sparc64/include/mm/tlb.h
===================================================================
--- kernel/arch/sparc64/include/mm/tlb.h	(revision d0b1443fbd2d61bcae0c7f5c106302bbcd640792)
+++ kernel/arch/sparc64/include/mm/tlb.h	(revision 36f19c0f0dc80e99e7a2255fc75ddff351c22ac4)
@@ -429,7 +429,7 @@
 }
 
-extern void fast_instruction_access_mmu_miss(int n, istate_t *istate);
-extern void fast_data_access_mmu_miss(int n, istate_t *istate);
-extern void fast_data_access_protection(int n, istate_t *istate);
+extern void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate);
+extern void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate);
+extern void fast_data_access_protection(tlb_tag_access_reg_t tag , istate_t *istate);
 
 extern void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool locked, bool cacheable);
Index: kernel/arch/sparc64/include/trap/mmu.h
===================================================================
--- kernel/arch/sparc64/include/trap/mmu.h	(revision d0b1443fbd2d61bcae0c7f5c106302bbcd640792)
+++ kernel/arch/sparc64/include/trap/mmu.h	(revision 36f19c0f0dc80e99e7a2255fc75ddff351c22ac4)
@@ -130,5 +130,19 @@
 .endif
 
+	/*
+	 * Switch from the MM globals.
+	 */
 	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate
+
+	/*
+	 * Read the Tag Access register for the higher-level handler.
+	 * This is necessary to survive nested DTLB misses.
+	 */	
+	mov VA_DMMU_TAG_ACCESS, %g2
+	ldxa [%g2] ASI_DMMU, %g2
+
+	/*
+	 * g2 will be passed as an argument to fast_data_access_mmu_miss().
+	 */
 	PREEMPTIBLE_HANDLER fast_data_access_mmu_miss
 .endm
@@ -143,5 +157,19 @@
 .endif
 
+	/*
+	 * Switch from the MM globals.
+	 */
 	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_AG_BIT, %pstate
+
+	/*
+	 * Read the Tag Access register for the higher-level handler.
+	 * This is necessary to survive nested DTLB misses.
+	 */	
+	mov VA_DMMU_TAG_ACCESS, %g2
+	ldxa [%g2] ASI_DMMU, %g2
+
+	/*
+	 * g2 will be passed as an argument to fast_data_access_mmu_miss().
+	 */
 	PREEMPTIBLE_HANDLER fast_data_access_protection
 .endm
Index: kernel/arch/sparc64/src/mm/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tlb.c	(revision d0b1443fbd2d61bcae0c7f5c106302bbcd640792)
+++ kernel/arch/sparc64/src/mm/tlb.c	(revision 36f19c0f0dc80e99e7a2255fc75ddff351c22ac4)
@@ -199,5 +199,5 @@
 
 /** ITLB miss handler. */
-void fast_instruction_access_mmu_miss(int n, istate_t *istate)
+void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate)
 {
 	uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
@@ -235,13 +235,16 @@
  * Note that some faults (e.g. kernel faults) were already resolved by the
  * low-level, assembly language part of the fast_data_access_mmu_miss handler.
- */
-void fast_data_access_mmu_miss(int n, istate_t *istate)
-{
-	tlb_tag_access_reg_t tag;
+ *
+ * @param tag Content of the TLB Tag Access register as it existed when the
+ *    trap happened. This is to prevent confusion created by clobbered
+ *    Tag Access register during a nested DTLB miss.
+ * @param istate Interrupted state saved on the stack.
+ */
+void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate)
+{
 	uintptr_t va;
 	index_t index;
 	pte_t *t;
 
-	tag.value = dtlb_tag_access_read();
 	va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
 	index = tag.vpn % MMU_PAGES_PER_PAGE;
@@ -283,13 +286,17 @@
 }
 
-/** DTLB protection fault handler. */
-void fast_data_access_protection(int n, istate_t *istate)
-{
-	tlb_tag_access_reg_t tag;
+/** DTLB protection fault handler.
+ *
+ * @param tag Content of the TLB Tag Access register as it existed when the
+ *    trap happened. This is to prevent confusion created by clobbered
+ *    Tag Access register during a nested DTLB miss.
+ * @param istate Interrupted state saved on the stack.
+ */
+void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate)
+{
 	uintptr_t va;
 	index_t index;
 	pte_t *t;
 
-	tag.value = dtlb_tag_access_read();
 	va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
 	index = tag.vpn % MMU_PAGES_PER_PAGE;	/* 16K-page emulation */
@@ -372,7 +379,8 @@
 
 	va = tag.vpn << MMU_PAGE_WIDTH;
-
-	fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
-	    tag.context);
+	if (tag.context) {
+		fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
+		    tag.context);
+	}
 	dump_istate(istate);
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
@@ -387,6 +395,8 @@
 	va = tag.vpn << MMU_PAGE_WIDTH;
 
-	fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
-	    tag.context);
+	if (tag.context) {
+		fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
+		    tag.context);
+	}
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
 	dump_istate(istate);
