Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/Makefile.inc	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -84,6 +84,5 @@
 	arch/$(ARCH)/src/dummy.s \
 	arch/$(ARCH)/src/mm/as.c \
-	arch/$(ARCH)/src/mm/cache.c \
-	arch/$(ARCH)/src/mm/cache_asm.S \
+	arch/$(ARCH)/src/mm/cache.S \
 	arch/$(ARCH)/src/mm/frame.c \
 	arch/$(ARCH)/src/mm/page.c \
Index: kernel/arch/sparc64/include/cpu.h
===================================================================
--- kernel/arch/sparc64/include/cpu.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/cpu.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -65,9 +65,4 @@
 					     generated when the TICK register
 					     matches this value. */
-#ifdef CONFIG_SMP
-	int dcache_active;
-	dcache_shootdown_msg_t dcache_messages[DCACHE_MSG_QUEUE_LEN];
-	count_t dcache_message_count;
-#endif
 } cpu_arch_t;
 	
Index: kernel/arch/sparc64/include/mm/as.h
===================================================================
--- kernel/arch/sparc64/include/mm/as.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/mm/as.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -82,8 +82,9 @@
 
 #ifdef CONFIG_TSB
-#	include <arch/mm/tsb.h>
-#	define as_invalidate_translation_cache(as, page, cnt)	tsb_invalidate(as, page, cnt)
+#include <arch/mm/tsb.h>
+#define as_invalidate_translation_cache(as, page, cnt) \
+	tsb_invalidate((as), (page), (cnt))
 #else
-#	define as_invalidate_translation_cache(as, page, cnt)
+#define as_invalidate_translation_cache(as, page, cnt)
 #endif
 
Index: kernel/arch/sparc64/include/mm/cache.h
===================================================================
--- kernel/arch/sparc64/include/mm/cache.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/mm/cache.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -44,41 +44,7 @@
 	dcache_flush_tag(PAGE_COLOR((p)), ADDR2PFN((f)));
 
-/**
- * Enumerations to differentiate among different scopes of D-Cache
- * invalidation.
- */
-typedef enum {
-	DCACHE_INVL_INVALID,
-	DCACHE_INVL_ALL,
-	DCACHE_INVL_COLOR,
-	DCACHE_INVL_FRAME
-} dcache_invalidate_type_t;
-
-/**
- * Number of messages that can be queued in the cpu_arch_t structure at a time.
- */
-#define DCACHE_MSG_QUEUE_LEN	10
-
-/** D-cache shootdown message type. */
-typedef struct {
-	dcache_invalidate_type_t type;
-	int color;
-	uintptr_t frame;
-} dcache_shootdown_msg_t;
-
 extern void dcache_flush(void);
 extern void dcache_flush_color(int c);
 extern void dcache_flush_tag(int c, pfn_t tag);
-
-#ifdef CONFIG_SMP
-extern void dcache_shootdown_start(dcache_invalidate_type_t type, int color,
-    uintptr_t frame);
-extern void dcache_shootdown_finalize(void);
-extern void dcache_shootdown_ipi_recv(void); 
-#else
-#define dcache_shootdown_start(t, c, f)
-#define dcache_shootdown_finalize()
-#define dcache_shootdown_ipi_recv()
-#endif /* CONFIG_SMP */
 
 #endif
Index: kernel/arch/sparc64/include/mm/frame.h
===================================================================
--- kernel/arch/sparc64/include/mm/frame.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/mm/frame.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -36,5 +36,18 @@
 #define KERN_sparc64_FRAME_H_
 
-#define FRAME_WIDTH		13	/* 8K */
+/*
+ * Page size supported by the MMU.
+ * For 8K there is the nasty illegal virtual aliasing problem.
+ * Therefore, the kernel uses 8K only internally on the TLB and TSB levels.
+ */
+#define MMU_FRAME_WIDTH		13	/* 8K */
+#define MMU_FRAME_SIZE		(1 << MMU_FRAME_WIDTH)
+
+/*
+ * Page size exported to the generic memory management subsystems.
+ * This page size is not directly supported by the MMU, but we can emulate
+ * each 16K page with a pair of adjacent 8K pages.
+ */
+#define FRAME_WIDTH		14	/* 16K */
 #define FRAME_SIZE		(1 << FRAME_WIDTH)
 
Index: kernel/arch/sparc64/include/mm/page.h
===================================================================
--- kernel/arch/sparc64/include/mm/page.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/mm/page.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -38,8 +38,24 @@
 #include <arch/mm/frame.h>
 
+/*
+ * On the TLB and TSB level, we still use 8K pages, which are supported by the
+ * MMU.
+ */
+#define MMU_PAGE_WIDTH	MMU_FRAME_WIDTH
+#define MMU_PAGE_SIZE	MMU_FRAME_SIZE
+
+/*
+ * On the page table level, we use 16K pages. 16K pages are not supported by
+ * the MMU but we emulate them with pairs of 8K pages.
+ */
 #define PAGE_WIDTH	FRAME_WIDTH
 #define PAGE_SIZE	FRAME_SIZE
 
-#define PAGE_COLOR_BITS	1	/**< 14 - 13; 2^14 == 16K == alias boundary. */
+#define MMU_PAGES_PER_PAGE	(1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
+
+/*
+ * With 16K pages, there is only one page color.
+ */
+#define PAGE_COLOR_BITS	0	/**< 14 - 14; 2^14 == 16K == alias boundary. */
 
 #ifdef KERNEL
Index: kernel/arch/sparc64/include/mm/tsb.h
===================================================================
--- kernel/arch/sparc64/include/mm/tsb.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/mm/tsb.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -113,6 +113,6 @@
 
 extern void tsb_invalidate(struct as *as, uintptr_t page, count_t pages);
-extern void itsb_pte_copy(struct pte *t);
-extern void dtsb_pte_copy(struct pte *t, bool ro);
+extern void itsb_pte_copy(struct pte *t, index_t index);
+extern void dtsb_pte_copy(struct pte *t, index_t index, bool ro);
 
 #endif /* !def __ASM__ */
Index: kernel/arch/sparc64/include/stack.h
===================================================================
--- kernel/arch/sparc64/include/stack.h	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/include/stack.h	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -44,5 +44,5 @@
  * 16-extended-word save area for %i[0-7] and %l[0-7] registers.
  */
-#define STACK_WINDOW_SAVE_AREA_SIZE	(16*STACK_ITEM_SIZE)
+#define STACK_WINDOW_SAVE_AREA_SIZE	(16 * STACK_ITEM_SIZE)
 
 /**
Index: kernel/arch/sparc64/src/cpu/cpu.c
===================================================================
--- kernel/arch/sparc64/src/cpu/cpu.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/cpu/cpu.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -52,9 +52,4 @@
 	CPU->arch.mid = upa_config.mid;
 	
-#if (defined(CONFIG_SMP) && defined(CONFIG_VIRT_IDX_DCACHE))
-	CPU->arch.dcache_active = 1;
-	CPU->arch.dcache_message_count = 0;
-#endif
-
 	/*
 	 * Detect processor frequency.
Index: kernel/arch/sparc64/src/mm/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/as.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/mm/as.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -63,5 +63,5 @@
 #ifdef CONFIG_TSB
 	int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-		sizeof(tsb_entry_t)) >> FRAME_WIDTH);
+		sizeof(tsb_entry_t)) >> MMU_FRAME_WIDTH);
 	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
 
@@ -72,6 +72,6 @@
 	as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
 		sizeof(tsb_entry_t));
-	memsetb((uintptr_t) as->arch.itsb, (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT)
-		* sizeof(tsb_entry_t), 0);
+	memsetb((uintptr_t) as->arch.itsb,
+	    (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
 #endif
 	return 0;
@@ -82,5 +82,5 @@
 #ifdef CONFIG_TSB
 	count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-		sizeof(tsb_entry_t)) >> FRAME_WIDTH;
+		sizeof(tsb_entry_t)) >> MMU_FRAME_WIDTH;
 	frame_free(KA2PA((uintptr_t) as->arch.itsb));
 	return cnt;
@@ -140,5 +140,5 @@
 	uintptr_t tsb = (uintptr_t) as->arch.itsb;
 		
-	if (!overlaps(tsb, 8 * PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
 		/*
 		 * TSBs were allocated from memory not covered
@@ -159,7 +159,7 @@
 	tsb_base.split = 0;
 
-	tsb_base.base = ((uintptr_t) as->arch.itsb) >> PAGE_WIDTH;
+	tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH;
 	itsb_base_write(tsb_base.value);
-	tsb_base.base = ((uintptr_t) as->arch.dtsb) >> PAGE_WIDTH;
+	tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
 	dtsb_base_write(tsb_base.value);
 #endif
@@ -190,5 +190,5 @@
 	uintptr_t tsb = (uintptr_t) as->arch.itsb;
 		
-	if (!overlaps(tsb, 8 * PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
 		/*
 		 * TSBs were allocated from memory not covered
Index: kernel/arch/sparc64/src/mm/cache.S
===================================================================
--- kernel/arch/sparc64/src/mm/cache.S	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
+++ kernel/arch/sparc64/src/mm/cache.S	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include <arch/arch.h>
+
+#define DCACHE_SIZE		(16 * 1024)
+#define DCACHE_LINE_SIZE	32	
+
+#define DCACHE_TAG_SHIFT	2
+
+.register %g2, #scratch
+.register %g3, #scratch
+
+/** Flush the whole D-cache. */
+.global dcache_flush
+dcache_flush:
+	set (DCACHE_SIZE - DCACHE_LINE_SIZE), %g1
+	stxa %g0, [%g1] ASI_DCACHE_TAG
+0:	membar #Sync
+	subcc %g1, DCACHE_LINE_SIZE, %g1
+	bnz,pt %xcc, 0b
+	stxa %g0, [%g1] ASI_DCACHE_TAG
+	retl
+	membar #Sync
+
+/** Flush only D-cache lines of one virtual color.
+ *
+ * @param o0	Virtual color to be flushed.
+ */
+.global dcache_flush_color
+dcache_flush_color:
+	mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
+	set DCACHE_SIZE / 2, %g2
+	sllx %g2, %o0, %g2
+	sub %g2, DCACHE_LINE_SIZE, %g2
+0:	stxa %g0, [%g2] ASI_DCACHE_TAG
+	membar #Sync
+	subcc %g1, 1, %g1
+	bnz,pt %xcc, 0b
+	sub %g2, DCACHE_LINE_SIZE, %g2
+	retl
+	nop
+
+/** Flush only D-cache lines of one virtual color and one tag.
+ *
+ * @param o0	Virtual color to lookup the tag.
+ * @param o1	Tag of the cachelines to be flushed.
+ */
+.global dcache_flush_tag
+dcache_flush_tag:
+	mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
+	set DCACHE_SIZE / 2, %g2
+	sllx %g2, %o0, %g2
+	sub %g2, DCACHE_LINE_SIZE, %g2
+0:	ldxa [%g2] ASI_DCACHE_TAG, %g3
+	srlx %g3, DCACHE_TAG_SHIFT, %g3
+	cmp %g3, %o1
+	bnz 1f
+	nop
+	stxa %g0, [%g2] ASI_DCACHE_TAG
+	membar #Sync
+1:	subcc %g1, 1, %g1
+	bnz,pt %xcc, 0b
+	sub %g2, DCACHE_LINE_SIZE, %g2
+	retl
+	nop
Index: kernel/arch/sparc64/src/mm/cache.c
===================================================================
--- kernel/arch/sparc64/src/mm/cache.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ 	(revision )
@@ -1,157 +1,0 @@
-/*
- * 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.
- */
-
-/** @addtogroup sparc64mm	
- * @{
- */
-/**
- * @file
- * @brief	D-cache shootdown algorithm.
- */
-
-#include <arch/mm/cache.h>
-
-#ifdef CONFIG_SMP
-#ifdef CONFIG_VIRT_IDX_DCACHE
-
-#include <smp/ipi.h>
-#include <arch/interrupt.h>
-#include <synch/spinlock.h>
-#include <arch.h>
-#include <debug.h>
-
-/**
- * This spinlock is used by the processors to synchronize during the D-cache
- * shootdown.
- */
-SPINLOCK_INITIALIZE(dcachelock);
-
-/** Initialize the D-cache shootdown sequence.
- *
- * Start the shootdown sequence by sending out an IPI and wait until all
- * processors spin on the dcachelock spinlock.
- *
- * @param type 	Scope of the D-cache shootdown.
- * @param color	Color to be invalidated; applicable only for DCACHE_INVL_COLOR
- * 	  	and DCACHE_INVL_FRAME invalidation types.
- * @param frame	Frame to be invalidated; applicable only for DCACHE_INVL_FRAME
- * 	  	invalidation types.
- */
-void dcache_shootdown_start(dcache_invalidate_type_t type, int color,
-    uintptr_t frame)
-{
-	int i;
-
-	CPU->arch.dcache_active = 0;
-	spinlock_lock(&dcachelock);
-
-	for (i = 0; i < config.cpu_count; i++) {
-		cpu_t *cpu;
-
-		if (i == CPU->id)
-			continue;
-
-		cpu = &cpus[i];
-		spinlock_lock(&cpu->lock);
-		if (cpu->arch.dcache_message_count ==
-		    DCACHE_MSG_QUEUE_LEN) {
-			/*
-			 * The queue is full, flush the cache entirely.
-			 */
-			cpu->arch.dcache_message_count = 1;
-			cpu->arch.dcache_messages[0].type = DCACHE_INVL_ALL;
-			cpu->arch.dcache_messages[0].color = 0; /* ignored */
-			cpu->arch.dcache_messages[0].frame = 0; /* ignored */
-		} else {
-			index_t idx = cpu->arch.dcache_message_count++;
-			cpu->arch.dcache_messages[idx].type = type;
-			cpu->arch.dcache_messages[idx].color = color;
-			cpu->arch.dcache_messages[idx].frame = frame;
-		}
-		spinlock_unlock(&cpu->lock);
-	}
-
-	ipi_broadcast(IPI_DCACHE_SHOOTDOWN);	
-
-busy_wait:
-	for (i = 0; i < config.cpu_count; i++)
-		if (cpus[i].arch.dcache_active)
-			goto busy_wait;
-}
-
-/** Finish the D-cache shootdown sequence. */
-void dcache_shootdown_finalize(void)
-{
-	spinlock_unlock(&dcachelock);
-	CPU->arch.dcache_active = 1;
-}
-
-/** Process the D-cache shootdown IPI. */
-void dcache_shootdown_ipi_recv(void)
-{
-	int i;
-
-	ASSERT(CPU);
-
-	CPU->arch.dcache_active = 0;
-	spinlock_lock(&dcachelock);
-	spinlock_unlock(&dcachelock);
-	
-	spinlock_lock(&CPU->lock);
-	ASSERT(CPU->arch.dcache_message_count < DCACHE_MSG_QUEUE_LEN);
-	for (i = 0; i < CPU->arch.dcache_message_count; i++) {
-		switch (CPU->arch.dcache_messages[i].type) {
-		case DCACHE_INVL_ALL:
-			dcache_flush();
-			goto flushed;
-			break;
-		case DCACHE_INVL_COLOR:
-			dcache_flush_color(CPU->arch.dcache_messages[i].color);
-			break;
-		case DCACHE_INVL_FRAME:
-			dcache_flush_frame(CPU->arch.dcache_messages[i].color,
-			    CPU->arch.dcache_messages[i].frame);
-			break;
-		default:
-			panic("unknown type (%d)\n",
-			    CPU->arch.dcache_messages[i].type);
-		}
-	}
-flushed:
-	CPU->arch.dcache_message_count = 0;
-	spinlock_unlock(&CPU->lock);
-
-	CPU->arch.dcache_active = 1;
-}
-
-#endif /* CONFIG_VIRT_IDX_DCACHE */
-#endif /* CONFIG_SMP */
-
-/** @}
- */
-
Index: kernel/arch/sparc64/src/mm/cache_asm.S
===================================================================
--- kernel/arch/sparc64/src/mm/cache_asm.S	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ 	(revision )
@@ -1,91 +1,0 @@
-/*
- * 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.
- */
-
-#include <arch/arch.h>
-
-#define DCACHE_SIZE		(16 * 1024)
-#define DCACHE_LINE_SIZE	32	
-
-#define DCACHE_TAG_SHIFT	2
-
-.register %g2, #scratch
-.register %g3, #scratch
-
-/** Flush the whole D-cache. */
-.global dcache_flush
-dcache_flush:
-	set (DCACHE_SIZE - DCACHE_LINE_SIZE), %g1
-	stxa %g0, [%g1] ASI_DCACHE_TAG
-0:	membar #Sync
-	subcc %g1, DCACHE_LINE_SIZE, %g1
-	bnz,pt %xcc, 0b
-	stxa %g0, [%g1] ASI_DCACHE_TAG
-	retl
-	membar #Sync
-
-/** Flush only D-cache lines of one virtual color.
- *
- * @param o0	Virtual color to be flushed.
- */
-.global dcache_flush_color
-dcache_flush_color:
-	mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
-	set DCACHE_SIZE / 2, %g2
-	sllx %g2, %o0, %g2
-	sub %g2, DCACHE_LINE_SIZE, %g2
-0:	stxa %g0, [%g2] ASI_DCACHE_TAG
-	membar #Sync
-	subcc %g1, 1, %g1
-	bnz,pt %xcc, 0b
-	sub %g2, DCACHE_LINE_SIZE, %g2
-	retl
-	nop
-
-/** Flush only D-cache lines of one virtual color and one tag.
- *
- * @param o0	Virtual color to lookup the tag.
- * @param o1	Tag of the cachelines to be flushed.
- */
-.global dcache_flush_tag
-dcache_flush_tag:
-	mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1
-	set DCACHE_SIZE / 2, %g2
-	sllx %g2, %o0, %g2
-	sub %g2, DCACHE_LINE_SIZE, %g2
-0:	ldxa [%g2] ASI_DCACHE_TAG, %g3
-	srlx %g3, DCACHE_TAG_SHIFT, %g3
-	cmp %g3, %o1
-	bnz 1f
-	nop
-	stxa %g0, [%g2] ASI_DCACHE_TAG
-	membar #Sync
-1:	subcc %g1, 1, %g1
-	bnz,pt %xcc, 0b
-	sub %g2, DCACHE_LINE_SIZE, %g2
-	retl
-	nop
Index: kernel/arch/sparc64/src/mm/page.c
===================================================================
--- kernel/arch/sparc64/src/mm/page.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/mm/page.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -74,7 +74,7 @@
 		for (i = 0; i < bsp_locked_dtlb_entries; i++) {
 			dtlb_insert_mapping(bsp_locked_dtlb_entry[i].virt_page,
-				bsp_locked_dtlb_entry[i].phys_page,
-				bsp_locked_dtlb_entry[i].pagesize_code,	true,
-				false);
+			    bsp_locked_dtlb_entry[i].phys_page,
+			    bsp_locked_dtlb_entry[i].pagesize_code, true,
+			    false);
 		}
 #endif	
@@ -108,24 +108,24 @@
 		count_t count;
 	} sizemap[] = {
-		{ PAGESIZE_8K, 0, 1 },			/* 8K */
-		{ PAGESIZE_8K, PAGE_SIZE, 2 },		/* 16K */
-		{ PAGESIZE_8K, PAGE_SIZE, 4 },		/* 32K */
-		{ PAGESIZE_64K, 0, 1},			/* 64K */
-		{ PAGESIZE_64K, 8 * PAGE_SIZE, 2 },	/* 128K */
-		{ PAGESIZE_64K, 8 * PAGE_SIZE, 4 },	/* 256K */
-		{ PAGESIZE_512K, 0, 1 },		/* 512K */
-		{ PAGESIZE_512K, 64 * PAGE_SIZE, 2 },	/* 1M */
-		{ PAGESIZE_512K, 64 * PAGE_SIZE, 4 },	/* 2M */
-		{ PAGESIZE_4M, 0, 1 },			/* 4M */
-		{ PAGESIZE_4M, 512 * PAGE_SIZE, 2 }	/* 8M */
+		{ PAGESIZE_8K, 0, 1 },				/* 8K */
+		{ PAGESIZE_8K, MMU_PAGE_SIZE, 2 },		/* 16K */
+		{ PAGESIZE_8K, MMU_PAGE_SIZE, 4 },		/* 32K */
+		{ PAGESIZE_64K, 0, 1},				/* 64K */
+		{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 2 },		/* 128K */
+		{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 4 },		/* 256K */
+		{ PAGESIZE_512K, 0, 1 },			/* 512K */
+		{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 2 },	/* 1M */
+		{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 4 },	/* 2M */
+		{ PAGESIZE_4M, 0, 1 },				/* 4M */
+		{ PAGESIZE_4M, 512 * MMU_PAGE_SIZE, 2 }		/* 8M */
 	};
 	
-	ASSERT(ALIGN_UP(physaddr, PAGE_SIZE) == physaddr);
+	ASSERT(ALIGN_UP(physaddr, MMU_PAGE_SIZE) == physaddr);
 	ASSERT(size <= 8 * 1024 * 1024);
 	
-	if (size <= FRAME_SIZE)
+	if (size <= MMU_FRAME_SIZE)
 		order = 0;
 	else
-		order = (fnzb64(size - 1) + 1) - FRAME_WIDTH;
+		order = (fnzb64(size - 1) + 1) - MMU_FRAME_WIDTH;
 
 	/*
@@ -135,6 +135,8 @@
 	 */
 	ASSERT(PA2KA(last_frame));
-	uintptr_t virtaddr = ALIGN_UP(PA2KA(last_frame), 1 << (order + FRAME_WIDTH));
-	last_frame = ALIGN_UP(KA2PA(virtaddr) + size, 1 << (order + FRAME_WIDTH));
+	uintptr_t virtaddr = ALIGN_UP(PA2KA(last_frame),
+	    1 << (order + FRAME_WIDTH));
+	last_frame = ALIGN_UP(KA2PA(virtaddr) + size,
+	    1 << (order + FRAME_WIDTH));
 	
 	for (i = 0; i < sizemap[order].count; i++) {
@@ -143,6 +145,6 @@
 		 */
 		dtlb_insert_mapping(virtaddr + i * sizemap[order].increment,
-			physaddr + i * sizemap[order].increment,
-			sizemap[order].pagesize_code, true, false);
+		    physaddr + i * sizemap[order].increment,
+		    sizemap[order].pagesize_code, true, false);
 	
 #ifdef CONFIG_SMP	
@@ -151,9 +153,9 @@
 		 */
 		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].virt_page =
-			virtaddr + i * sizemap[order].increment;
+		    virtaddr + i * sizemap[order].increment;
 		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].phys_page =
-			physaddr + i * sizemap[order].increment;
+		    physaddr + i * sizemap[order].increment;
 		bsp_locked_dtlb_entry[bsp_locked_dtlb_entries].pagesize_code =
-			sizemap[order].pagesize_code;
+		    sizemap[order].pagesize_code;
 		bsp_locked_dtlb_entries++;
 #endif
Index: kernel/arch/sparc64/src/mm/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tlb.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/mm/tlb.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -55,12 +55,12 @@
 #endif
 
-static void dtlb_pte_copy(pte_t *t, bool ro);
-static void itlb_pte_copy(pte_t *t);
-static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const
-	char *str);
+static void dtlb_pte_copy(pte_t *t, index_t index, bool ro);
+static void itlb_pte_copy(pte_t *t, index_t index);
+static void do_fast_instruction_access_mmu_miss_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);
+    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);
+    tlb_tag_access_reg_t tag, const char *str);
 
 char *context_encoding[] = {
@@ -93,6 +93,6 @@
  * @param cacheable True if the mapping is cacheable, false otherwise.
  */
-void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool
-	locked, bool cacheable)
+void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize,
+    bool locked, bool cacheable)
 {
 	tlb_tag_access_reg_t tag;
@@ -127,9 +127,10 @@
 /** Copy PTE to TLB.
  *
- * @param t Page Table Entry to be copied.
- * @param ro If true, the entry will be created read-only, regardless of its w
- * 	field.
- */
-void dtlb_pte_copy(pte_t *t, bool ro)
+ * @param t 	Page Table Entry to be copied.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K-subpage.
+ * @param ro 	If true, the entry will be created read-only, regardless of its
+ * 		w field.
+ */
+void dtlb_pte_copy(pte_t *t, index_t index, bool ro)
 {
 	tlb_tag_access_reg_t tag;
@@ -138,13 +139,13 @@
 	frame_address_t fr;
 
-	pg.address = t->page;
-	fr.address = t->frame;
+	pg.address = t->page + (index << MMU_PAGE_WIDTH);
+	fr.address = t->frame + (index << MMU_PAGE_WIDTH);
 
 	tag.value = 0;
 	tag.context = t->as->asid;
 	tag.vpn = pg.vpn;
-	
+
 	dtlb_tag_access_write(tag.value);
-	
+
 	data.value = 0;
 	data.v = true;
@@ -159,5 +160,5 @@
 	data.w = ro ? false : t->w;
 	data.g = t->g;
-	
+
 	dtlb_data_in_write(data.value);
 }
@@ -165,7 +166,8 @@
 /** Copy PTE to ITLB.
  *
- * @param t Page Table Entry to be copied.
- */
-void itlb_pte_copy(pte_t *t)
+ * @param t 	Page Table Entry to be copied.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K-subpage.
+ */
+void itlb_pte_copy(pte_t *t, index_t index)
 {
 	tlb_tag_access_reg_t tag;
@@ -174,6 +176,6 @@
 	frame_address_t fr;
 
-	pg.address = t->page;
-	fr.address = t->frame;
+	pg.address = t->page + (index << MMU_PAGE_WIDTH);
+	fr.address = t->frame + (index << MMU_PAGE_WIDTH);
 
 	tag.value = 0;
@@ -200,4 +202,5 @@
 {
 	uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
+	index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
 	pte_t *t;
 
@@ -210,7 +213,7 @@
 		 */
 		t->a = true;
-		itlb_pte_copy(t);
+		itlb_pte_copy(t, index);
 #ifdef CONFIG_TSB
-		itsb_pte_copy(t);
+		itsb_pte_copy(t, index);
 #endif
 		page_table_unlock(AS, true);
@@ -223,5 +226,5 @@
 		if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
 			do_fast_instruction_access_mmu_miss_fault(istate,
-				__FUNCTION__);
+			    __FUNCTION__);
 		}
 	}
@@ -237,8 +240,10 @@
 	tlb_tag_access_reg_t tag;
 	uintptr_t va;
+	index_t index;
 	pte_t *t;
 
 	tag.value = dtlb_tag_access_read();
-	va = tag.vpn << PAGE_WIDTH;
+	va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
+	index = tag.vpn % MMU_PAGES_PER_PAGE;
 
 	if (tag.context == ASID_KERNEL) {
@@ -246,8 +251,8 @@
 			/* NULL access in kernel */
 			do_fast_data_access_mmu_miss_fault(istate, tag,
-				__FUNCTION__);
+			    __FUNCTION__);
 		}
 		do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected "
-			"kernel page fault.");
+		    "kernel page fault.");
 	}
 
@@ -260,17 +265,18 @@
 		 */
 		t->a = true;
-		dtlb_pte_copy(t, true);
+		dtlb_pte_copy(t, index, true);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, true);
+		dtsb_pte_copy(t, index, true);
 #endif
 		page_table_unlock(AS, true);
 	} else {
 		/*
-		 * Forward the page fault to the address space page fault handler.
+		 * Forward the page fault to the address space page fault
+		 * handler.
 		 */		
 		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, tag,
-				__FUNCTION__);
+			    __FUNCTION__);
 		}
 	}
@@ -282,8 +288,10 @@
 	tlb_tag_access_reg_t tag;
 	uintptr_t va;
+	index_t index;
 	pte_t *t;
 
 	tag.value = dtlb_tag_access_read();
-	va = tag.vpn << PAGE_WIDTH;
+	va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
+	index = tag.vpn % MMU_PAGES_PER_PAGE;	/* 16K-page emulation */
 
 	page_table_lock(AS, true);
@@ -297,8 +305,9 @@
 		t->a = true;
 		t->d = true;
-		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, va);
-		dtlb_pte_copy(t, false);
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY,
+		    va + index * MMU_PAGE_SIZE);
+		dtlb_pte_copy(t, index, false);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, false);
+		dtsb_pte_copy(t, index, false);
 #endif
 		page_table_unlock(AS, true);
@@ -311,5 +320,5 @@
 		if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
 			do_fast_data_access_protection_fault(istate, tag,
-				__FUNCTION__);
+			    __FUNCTION__);
 		}
 	}
@@ -329,8 +338,8 @@
 
 		printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
-			"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
-			"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
-			t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
-			d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
+		    "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
+		    "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
+		    t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
+		    d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
 	}
 
@@ -341,14 +350,14 @@
 		
 		printf("%d: vpn=%#llx, context=%d, v=%d, size=%d, nfo=%d, "
-			"ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
-			"cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
-			t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
-			d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
-	}
-
-}
-
-void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char
-	*str)
+		    "ie=%d, soft2=%#x, diag=%#x, pfn=%#x, soft=%#x, l=%d, "
+		    "cp=%d, cv=%d, e=%d, p=%d, w=%d, g=%d\n", i, t.vpn,
+		    t.context, d.v, d.size, d.nfo, d.ie, d.soft2, d.diag,
+		    d.pfn, d.soft, d.l, d.cp, d.cv, d.e, d.p, d.w, d.g);
+	}
+
+}
+
+void do_fast_instruction_access_mmu_miss_fault(istate_t *istate,
+    const char *str)
 {
 	fault_if_from_uspace(istate, "%s\n", str);
@@ -357,13 +366,13 @@
 }
 
-void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t
-	tag, const char *str)
+void do_fast_data_access_mmu_miss_fault(istate_t *istate,
+    tlb_tag_access_reg_t tag, const char *str)
 {
 	uintptr_t va;
 
-	va = tag.vpn << PAGE_WIDTH;
+	va = tag.vpn << MMU_PAGE_WIDTH;
 
 	fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
-		tag.context);
+	    tag.context);
 	dump_istate(istate);
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
@@ -371,13 +380,13 @@
 }
 
-void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t
-	tag, const char *str)
+void do_fast_data_access_protection_fault(istate_t *istate,
+    tlb_tag_access_reg_t tag, const char *str)
 {
 	uintptr_t va;
 
-	va = tag.vpn << PAGE_WIDTH;
+	va = tag.vpn << MMU_PAGE_WIDTH;
 
 	fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va,
-		tag.context);
+	    tag.context);
 	printf("Faulting page: %p, ASID=%d\n", va, tag.context);
 	dump_istate(istate);
@@ -394,6 +403,6 @@
 	
 	printf("DTLB SFSR: asi=%#x, ft=%#x, e=%d, ct=%d, pr=%d, w=%d, ow=%d, "
-		"fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w,
-		sfsr.ow, sfsr.fv);
+	    "fv=%d\n", sfsr.asi, sfsr.ft, sfsr.e, sfsr.ct, sfsr.pr, sfsr.w,
+	    sfsr.ow, sfsr.fv);
 	printf("DTLB SFAR: address=%p\n", sfar);
 	
@@ -482,9 +491,9 @@
 	mmu_primary_context_write(ctx.v);
 	
-	for (i = 0; i < cnt; i++) {
+	for (i = 0; i < cnt * MMU_PAGES_PER_PAGE; i++) {
 		itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY,
-		    page + i * PAGE_SIZE);
+		    page + i * MMU_PAGE_SIZE);
 		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY,
-		    page + i * PAGE_SIZE);
+		    page + i * MMU_PAGE_SIZE);
 	}
 	
Index: kernel/arch/sparc64/src/mm/tsb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tsb.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/mm/tsb.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -35,4 +35,5 @@
 #include <arch/mm/tsb.h>
 #include <arch/mm/tlb.h>
+#include <arch/mm/page.h>
 #include <arch/barrier.h>
 #include <mm/as.h>
@@ -41,5 +42,5 @@
 #include <debug.h>
 
-#define TSB_INDEX_MASK		((1 << (21 + 1 + TSB_SIZE - PAGE_WIDTH)) - 1)
+#define TSB_INDEX_MASK	((1 << (21 + 1 + TSB_SIZE - MMU_PAGE_WIDTH)) - 1)
 
 /** Invalidate portion of TSB.
@@ -60,12 +61,12 @@
 	ASSERT(as->arch.itsb && as->arch.dtsb);
 	
-	i0 = (page >> PAGE_WIDTH) & TSB_INDEX_MASK;
-	cnt = min(pages, ITSB_ENTRY_COUNT);
+	i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK;
+	cnt = min(pages * MMU_PAGES_PER_PAGE, ITSB_ENTRY_COUNT);
 	
 	for (i = 0; i < cnt; i++) {
 		as->arch.itsb[(i0 + i) & (ITSB_ENTRY_COUNT - 1)].tag.invalid =
-			true;
+		    true;
 		as->arch.dtsb[(i0 + i) & (DTSB_ENTRY_COUNT - 1)].tag.invalid =
-			true;
+		    true;
 	}
 }
@@ -73,13 +74,16 @@
 /** Copy software PTE to ITSB.
  *
- * @param t Software PTE.
+ * @param t 	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K subpage.
  */
-void itsb_pte_copy(pte_t *t)
+void itsb_pte_copy(pte_t *t, index_t index)
 {
 	as_t *as;
 	tsb_entry_t *tsb;
+	index_t entry;
 	
 	as = t->as;
-	tsb = &as->arch.itsb[(t->page >> PAGE_WIDTH) & TSB_INDEX_MASK];
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; 
+	tsb = &as->arch.itsb[entry];
 
 	/*
@@ -96,8 +100,9 @@
 
 	tsb->tag.context = as->asid;
-	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >>
+	    VA_TAG_PAGE_SHIFT;
 	tsb->data.value = 0;
 	tsb->data.size = PAGESIZE_8K;
-	tsb->data.pfn = t->frame >> FRAME_WIDTH;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
 	tsb->data.cp = t->c;
 	tsb->data.p = t->k;		/* p as privileged */
@@ -111,14 +116,17 @@
 /** Copy software PTE to DTSB.
  *
- * @param t Software PTE.
- * @param ro If true, the mapping is copied read-only.
+ * @param t	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K-subpage.
+ * @param ro	If true, the mapping is copied read-only.
  */
-void dtsb_pte_copy(pte_t *t, bool ro)
+void dtsb_pte_copy(pte_t *t, index_t index, bool ro)
 {
 	as_t *as;
 	tsb_entry_t *tsb;
+	index_t entry;
 	
 	as = t->as;
-	tsb = &as->arch.dtsb[(t->page >> PAGE_WIDTH) & TSB_INDEX_MASK];
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK;
+	tsb = &as->arch.dtsb[entry];
 
 	/*
@@ -135,8 +143,9 @@
 
 	tsb->tag.context = as->asid;
-	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >>
+	    VA_TAG_PAGE_SHIFT;
 	tsb->data.value = 0;
 	tsb->data.size = PAGESIZE_8K;
-	tsb->data.pfn = t->frame >> FRAME_WIDTH;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
 	tsb->data.cp = t->c;
 #ifdef CONFIG_VIRT_IDX_DCACHE
Index: kernel/arch/sparc64/src/smp/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/ipi.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/smp/ipi.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -40,5 +40,4 @@
 #include <config.h>
 #include <mm/tlb.h>
-#include <arch/mm/cache.h>
 #include <arch/interrupt.h>
 #include <arch/trap/interrupt.h>
@@ -126,9 +125,4 @@
 		func = tlb_shootdown_ipi_recv;
 		break;
-#if (defined(CONFIG_SMP) && (defined(CONFIG_VIRT_IDX_DCACHE)))
-	case IPI_DCACHE_SHOOTDOWN:
-		func = dcache_shootdown_ipi_recv;
-		break;
-#endif
 	default:
 		panic("Unknown IPI (%d).\n", ipi);
Index: kernel/arch/sparc64/src/trap/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/interrupt.c	(revision 454f1da77de2349b52f4bfe6ec9378202f3cdbda)
+++ kernel/arch/sparc64/src/trap/interrupt.c	(revision 2057572a989f56acc5c906946caebf6b2e039bda)
@@ -45,5 +45,4 @@
 #include <arch.h>
 #include <mm/tlb.h>
-#include <arch/mm/cache.h>
 #include <config.h>
 #include <synch/spinlock.h>
@@ -92,8 +91,4 @@
 		if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
 			tlb_shootdown_ipi_recv();
-#ifdef CONFIG_VIRT_IDX_DCACHE
-		} else if (data0 == (uintptr_t) dcache_shootdown_ipi_recv) {
-			dcache_shootdown_ipi_recv();
-#endif
 		}
 #endif
