Index: linux-2.6.9/include/asm-sh/pgtable.h
===================================================================
--- linux-2.6.9.orig/include/asm-sh/pgtable.h	2004-10-21 12:01:24.000000000 -0700
+++ linux-2.6.9/include/asm-sh/pgtable.h	2004-10-25 15:05:33.000000000 -0700
@@ -249,6 +249,8 @@
 struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
+extern void huge_update_mmu_cache(struct vm_area_struct * vma,
+			     unsigned long address, pte_t pte);
 
 /* Encode and de-code a swap entry */
 /*
Index: linux-2.6.9/arch/sh/mm/cache-sh4.c
===================================================================
--- linux-2.6.9.orig/arch/sh/mm/cache-sh4.c	2004-10-21 12:01:21.000000000 -0700
+++ linux-2.6.9/arch/sh/mm/cache-sh4.c	2004-10-25 15:18:53.000000000 -0700
@@ -206,13 +206,25 @@
 void flush_dcache_page(struct page *page)
 {
 	if (test_bit(PG_mapped, &page->flags)) {
-		unsigned long phys = PHYSADDR(page_address(page));
+		unsigned long phys;
+		int nr = 1;
 
-		/* Loop all the D-cache */
-		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
-		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
-		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
-		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+		if (CompoundPage(page)) {
+			page = page->private;
+			nr = 1 << page[1].index;
+		}
+
+		phys = PHYSADDR(page_address(page));
+
+		while (nr-- > 0) {
+			/* Loop all the D-cache */
+			flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
+			flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
+			flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
+			flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+
+			phys += PAGE_SIZE;
+		}
 	}
 }
 
Index: linux-2.6.9/arch/sh/mm/tlb-nommu.c
===================================================================
--- linux-2.6.9.orig/arch/sh/mm/tlb-nommu.c	2004-10-18 14:54:27.000000000 -0700
+++ linux-2.6.9/arch/sh/mm/tlb-nommu.c	2004-10-25 15:06:56.000000000 -0700
@@ -55,4 +55,9 @@
 {
 	BUG();
 }
+void huge_update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	BUG();
+}
 
Index: linux-2.6.9/arch/sh/mm/cache-sh7705.c
===================================================================
--- linux-2.6.9.orig/arch/sh/mm/cache-sh7705.c	2004-10-21 12:01:21.000000000 -0700
+++ linux-2.6.9/arch/sh/mm/cache-sh7705.c	2004-10-25 15:23:46.000000000 -0700
@@ -135,8 +135,22 @@
  */
 void flush_dcache_page(struct page *page)
 {
-	if (test_bit(PG_mapped, &page->flags))
-		__flush_dcache_page(PHYSADDR(page_address(page)));
+	if (test_bit(PG_mapped, &page->flags)) {
+		if (!CompoundPage(page))
+			__flush_dcache_page(PHYSADDR(page_address(page)));
+		else {
+			int nr;
+			unsigned long phy = PHYSADDR(page_address(page));
+
+			page = page->private;
+			nr = 1 << page[1].index;
+
+			while (nr-- >0) {
+				__flush_dcache_page(phys);
+				phys += PAGE_SIZE;
+			}
+		}
+	}	
 }
 
 void flush_cache_all(void)
Index: linux-2.6.9/arch/sh/mm/tlb-sh3.c
===================================================================
--- linux-2.6.9.orig/arch/sh/mm/tlb-sh3.c	2004-10-21 12:01:21.000000000 -0700
+++ linux-2.6.9/arch/sh/mm/tlb-sh3.c	2004-10-25 15:13:00.000000000 -0700
@@ -67,6 +67,48 @@
 	local_irq_restore(flags);
 }
 
+void huge_update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+#if defined(CONFIG_SH7705_CACHE_32KB)
+	struct page *page;
+	page = pte_page(pte);
+	if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) {
+		unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+		__flush_wback_region((void *)P1SEGADDR(phys), HPAGE_SIZE);
+		__set_bit(PG_mapped, &page->flags);
+	}
+#endif
+
+	local_irq_save(flags);
+
+	/* FIXME: What exactly does the code below do? pte mapping ? */
+
+	/* Set PTEH register */
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
+
+	pteval = pte_val(pte);
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+	/* conveniently, we want all the software flags to be 0 anyway */
+	ctrl_outl(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
+
+
 void __flush_tlb_page(unsigned long asid, unsigned long page)
 {
 	unsigned long addr, data;
Index: linux-2.6.9/arch/sh/mm/tlb-sh4.c
===================================================================
--- linux-2.6.9.orig/arch/sh/mm/tlb-sh4.c	2004-10-18 14:54:38.000000000 -0700
+++ linux-2.6.9/arch/sh/mm/tlb-sh4.c	2004-10-25 15:14:46.000000000 -0700
@@ -28,6 +28,56 @@
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
+void huge_update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long pteval;
+	unsigned long vpn;
+	struct page *page;
+	unsigned long pfn;
+	unsigned long ptea;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+	pfn = pte_pfn(pte);
+	if (pfn_valid(pfn)) {
+		page = pfn_to_page(pfn);
+		if (!test_bit(PG_mapped, &page->flags)) {
+			unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+			__flush_wback_region((void *)P1SEGADDR(phys), HPAGE_SIZE);
+			__set_bit(PG_mapped, &page->flags);
+		}
+	}
+
+	/* FIXME: code below likely needs to be fixed up for huge pages */
+	local_irq_save(flags);
+
+	/* Set PTEH register */
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
+
+	pteval = pte_val(pte);
+	/* Set PTEA register */
+	/* TODO: make this look less hacky */
+	ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
+	ctrl_outl(ptea, MMU_PTEA);
+
+	/* Set PTEL register */
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+#ifdef CONFIG_SH_WRITETHROUGH
+	pteval |= _PAGE_WT;
+#endif
+	/* conveniently, we want all the software flags to be 0 anyway */
+	ctrl_outl(pteval, MMU_PTEL);
+
+	/* Load the TLB */
+	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
+	local_irq_restore(flags);
+}
+
 void update_mmu_cache(struct vm_area_struct * vma,
 		      unsigned long address, pte_t pte)
 {