sh: Move in the SH-5 TLB miss.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index 9ea3793..fc089c0 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -12,7 +12,7 @@
 endif
 
 mmu-y			:= tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU)	:= fault.o clear_page.o copy_page.o tlb-flush_32.o \
+mmu-$(CONFIG_MMU)	:= fault_32.o clear_page.o copy_page.o tlb-flush_32.o \
 			   ioremap_32.o
 
 obj-y			+= $(mmu-y)
diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64
index ec8deaa..82fe907 100644
--- a/arch/sh/mm/Makefile_64
+++ b/arch/sh/mm/Makefile_64
@@ -5,7 +5,7 @@
 obj-y			:= init.o extable_64.o consistent.o
 
 mmu-y			:= tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU)	:= ioremap_64.o tlb-flush_64.o
+mmu-$(CONFIG_MMU)	:= fault_64.o ioremap_64.o tlb-flush_64.o
 
 obj-y			+= $(mmu-y)
 
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault_32.c
similarity index 100%
rename from arch/sh/mm/fault.c
rename to arch/sh/mm/fault_32.c
diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh/mm/fault_64.c
similarity index 67%
rename from arch/sh64/mm/tlbmiss.c
rename to arch/sh/mm/fault_64.c
index b767d6c..1469aa7 100644
--- a/arch/sh64/mm/tlbmiss.c
+++ b/arch/sh/mm/fault_64.c
@@ -1,9 +1,5 @@
 /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * arch/sh64/mm/tlbmiss.c
+ * The SH64 TLB miss.
  *
  * Original code from fault.c
  * Copyright (C) 2000, 2001  Paolo Alberelli
@@ -12,16 +8,20 @@
  * Copyright (C) 2003 Richard.Curnow@superh.com
  *
  * IMPORTANT NOTES :
- * The do_fast_page_fault function is called from a context in entry.S where very few registers
- * have been saved.  In particular, the code in this file must be compiled not to use ANY
- * caller-save registers that are not part of the restricted save set.  Also, it means that
- * code in this file must not make calls to functions elsewhere in the kernel, or else the
- * excepting context will see corruption in its caller-save registers.  Plus, the entry.S save
- * area is non-reentrant, so this code has to run with SR.BL==1, i.e. no interrupts taken inside
- * it and panic on any exception.
+ * The do_fast_page_fault function is called from a context in entry.S
+ * where very few registers have been saved.  In particular, the code in
+ * this file must be compiled not to use ANY caller-save registers that
+ * are not part of the restricted save set.  Also, it means that code in
+ * this file must not make calls to functions elsewhere in the kernel, or
+ * else the excepting context will see corruption in its caller-save
+ * registers.  Plus, the entry.S save area is non-reentrant, so this code
+ * has to run with SR.BL==1, i.e. no interrupts taken inside it and panic
+ * on any exception.
  *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
-
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -33,14 +33,13 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-
 #include <asm/system.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
-#include <asm/registers.h>		/* required by inline asm statements */
+#include <asm/cpu/registers.h>
 
 /* Callable from fault.c, so not static */
 inline void __do_tlb_refill(unsigned long address,
@@ -88,48 +87,47 @@
 
 }
 
-static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long protection_flags,
+static int handle_vmalloc_fault(struct mm_struct *mm,
+				unsigned long protection_flags,
                                 unsigned long long textaccess,
 				unsigned long address)
 {
 	pgd_t *dir;
+	pud_t *pud;
 	pmd_t *pmd;
 	static pte_t *pte;
 	pte_t entry;
 
 	dir = pgd_offset_k(address);
-	pmd = pmd_offset(dir, address);
 
-	if (pmd_none(*pmd)) {
+	pud = pud_offset(dir, address);
+	if (pud_none_or_clear_bad(pud))
 		return 0;
-	}
 
-	if (pmd_bad(*pmd)) {
-		pmd_clear(pmd);
+	pmd = pmd_offset(pud, address);
+	if (pmd_none_or_clear_bad(pmd))
 		return 0;
-	}
 
 	pte = pte_offset_kernel(pmd, address);
 	entry = *pte;
 
-	if (pte_none(entry) || !pte_present(entry)) {
+	if (pte_none(entry) || !pte_present(entry))
 		return 0;
-	}
-
-	if ((pte_val(entry) & protection_flags) != protection_flags) {
+	if ((pte_val(entry) & protection_flags) != protection_flags)
 		return 0;
-	}
 
         __do_tlb_refill(address, textaccess, pte);
 
 	return 1;
 }
 
-static int handle_tlbmiss(struct mm_struct *mm, unsigned long long protection_flags,
-			unsigned long long textaccess,
-			unsigned long address)
+static int handle_tlbmiss(struct mm_struct *mm,
+			  unsigned long long protection_flags,
+			  unsigned long long textaccess,
+			  unsigned long address)
 {
 	pgd_t *dir;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
@@ -144,49 +142,49 @@
 
 	   See how mm->pgd is allocated and initialised in pgd_alloc to see why
 	   the next test is necessary.  - RPC */
-	if (address >= (unsigned long) TASK_SIZE) {
+	if (address >= (unsigned long) TASK_SIZE)
 		/* upper half - never has page table entries. */
 		return 0;
-	}
-	dir = pgd_offset(mm, address);
-	if (pgd_none(*dir)) {
-		return 0;
-	}
-	if (!pgd_present(*dir)) {
-		return 0;
-	}
 
-	pmd = pmd_offset(dir, address);
-	if (pmd_none(*pmd)) {
+	dir = pgd_offset(mm, address);
+	if (pgd_none(*dir) || !pgd_present(*dir))
 		return 0;
-	}
-	if (!pmd_present(*pmd)) {
+	if (!pgd_present(*dir))
 		return 0;
-	}
+
+	pud = pud_offset(dir, address);
+	if (pud_none(*pud) || !pud_present(*pud))
+		return 0;
+
+	pmd = pmd_offset(pud, address);
+	if (pmd_none(*pmd) || !pmd_present(*pmd))
+		return 0;
+
 	pte = pte_offset_kernel(pmd, address);
 	entry = *pte;
-	if (pte_none(entry)) {
-		return 0;
-	}
-	if (!pte_present(entry)) {
-		return 0;
-	}
 
-	/* If the page doesn't have sufficient protection bits set to service the
-	   kind of fault being handled, there's not much point doing the TLB refill.
-	   Punt the fault to the general handler. */
-	if ((pte_val(entry) & protection_flags) != protection_flags) {
+	if (pte_none(entry) || !pte_present(entry))
 		return 0;
-	}
+
+	/*
+	 * If the page doesn't have sufficient protection bits set to
+	 * service the kind of fault being handled, there's not much
+	 * point doing the TLB refill.  Punt the fault to the general
+	 * handler.
+	 */
+	if ((pte_val(entry) & protection_flags) != protection_flags)
+		return 0;
 
         __do_tlb_refill(address, textaccess, pte);
 
 	return 1;
 }
 
-/* Put all this information into one structure so that everything is just arithmetic
-   relative to a single base address.  This reduces the number of movi/shori pairs needed
-   just to load addresses of static data. */
+/*
+ * Put all this information into one structure so that everything is just
+ * arithmetic relative to a single base address.  This reduces the number
+ * of movi/shori pairs needed just to load addresses of static data.
+ */
 struct expevt_lookup {
 	unsigned short protection_flags[8];
 	unsigned char  is_text_access[8];
@@ -216,7 +214,8 @@
    general fault handling in fault.c which deals with mapping file-backed
    pages, stack growth, segmentation faults, swapping etc etc)
  */
-asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long expevt,
+asmlinkage int do_fast_page_fault(unsigned long long ssr_md,
+				  unsigned long long expevt,
 			          unsigned long address)
 {
 	struct task_struct *tsk;
@@ -226,17 +225,18 @@
 	unsigned long long index;
 	unsigned long long expevt4;
 
-	/* The next few lines implement a way of hashing EXPEVT into a small array index
-	   which can be used to lookup parameters specific to the type of TLBMISS being
-	   handled.  Note:
-	   ITLBMISS has EXPEVT==0xa40
-	   RTLBMISS has EXPEVT==0x040
-	   WTLBMISS has EXPEVT==0x060
-	*/
-
+	/* The next few lines implement a way of hashing EXPEVT into a
+	 * small array index which can be used to lookup parameters
+	 * specific to the type of TLBMISS being handled.
+	 *
+	 * Note:
+	 *	ITLBMISS has EXPEVT==0xa40
+	 *	RTLBMISS has EXPEVT==0x040
+	 *	WTLBMISS has EXPEVT==0x060
+	 */
 	expevt4 = (expevt >> 4);
-	/* TODO : xor ssr_md into this expression too.  Then we can check that PRU is set
-	   when it needs to be. */
+	/* TODO : xor ssr_md into this expression too. Then we can check
+	 * that PRU is set when it needs to be. */
 	index = expevt4 ^ (expevt4 >> 5);
 	index &= 7;
 	protection_flags = expevt_lookup_table.protection_flags[index];
@@ -262,18 +262,18 @@
 
 	if ((address >= VMALLOC_START && address < VMALLOC_END) ||
 	    (address >= IOBASE_VADDR  && address < IOBASE_END)) {
-		if (ssr_md) {
-			/* Process-contexts can never have this address range mapped */
-			if (handle_vmalloc_fault(mm, protection_flags, textaccess, address)) {
+		if (ssr_md)
+			/*
+			 * Process-contexts can never have this address
+			 * range mapped
+			 */
+			if (handle_vmalloc_fault(mm, protection_flags,
+						 textaccess, address))
 				return 1;
-			}
-		}
 	} else if (!in_interrupt() && mm) {
-		if (handle_tlbmiss(mm, protection_flags, textaccess, address)) {
+		if (handle_tlbmiss(mm, protection_flags, textaccess, address))
 			return 1;
-		}
 	}
 
 	return 0;
 }
-