ARM: pgtable: add pud-level code

Add pud_offset() et.al. between the pgd and pmd code in preparation of
using pgtable-nopud.h rather than 4level-fixup.h.

This incorporates a fix from Jamie Iles <jamie@jamieiles.com> for
uaccess_with_memcpy.c.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index ef0e24f..bc0e1d8 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -80,6 +80,7 @@
 			addr, (long long)pgd_val(*pgd));
 
 	do {
+		pud_t *pud;
 		pmd_t *pmd;
 		pte_t *pte;
 
@@ -91,7 +92,19 @@
 			break;
 		}
 
-		pmd = pmd_offset(pgd, addr);
+		pud = pud_offset(pgd, addr);
+		if (PTRS_PER_PUD != 1)
+			printk(", *pud=%08lx", pud_val(*pud));
+
+		if (pud_none(*pud))
+			break;
+
+		if (pud_bad(*pud)) {
+			printk("(bad)");
+			break;
+		}
+
+		pmd = pmd_offset(pud, addr);
 		if (PTRS_PER_PMD != 1)
 			printk(", *pmd=%08llx", (long long)pmd_val(*pmd));
 
@@ -390,6 +403,7 @@
 {
 	unsigned int index;
 	pgd_t *pgd, *pgd_k;
+	pud_t *pud, *pud_k;
 	pmd_t *pmd, *pmd_k;
 
 	if (addr < TASK_SIZE)
@@ -408,12 +422,19 @@
 
 	if (pgd_none(*pgd_k))
 		goto bad_area;
-
 	if (!pgd_present(*pgd))
 		set_pgd(pgd, *pgd_k);
 
-	pmd_k = pmd_offset(pgd_k, addr);
-	pmd   = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pud_k = pud_offset(pgd_k, addr);
+
+	if (pud_none(*pud_k))
+		goto bad_area;
+	if (!pud_present(*pud))
+		set_pud(pud, *pud_k);
+
+	pmd = pmd_offset(pud, addr);
+	pmd_k = pmd_offset(pud_k, addr);
 
 	/*
 	 * On ARM one Linux PGD entry contains two hardware entries (see page