[S390] 1K/2K page table pages.

This patch implements 1K/2K page table pages for s390.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 900d448..af4aee8 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -20,10 +20,11 @@
 #define check_pgt_cache()	do {} while (0)
 
 unsigned long *crst_table_alloc(struct mm_struct *, int);
-void crst_table_free(unsigned long *);
+void crst_table_free(struct mm_struct *, unsigned long *);
 
-unsigned long *page_table_alloc(int);
-void page_table_free(unsigned long *);
+unsigned long *page_table_alloc(struct mm_struct *);
+void page_table_free(struct mm_struct *, unsigned long *);
+void disable_noexec(struct mm_struct *, struct task_struct *);
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
@@ -80,12 +81,12 @@
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
-	unsigned long *crst = crst_table_alloc(mm, s390_noexec);
-	if (crst)
-		crst_table_init(crst, _SEGMENT_ENTRY_EMPTY);
-	return (pmd_t *) crst;
+	unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+	if (table)
+		crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+	return (pmd_t *) table;
 }
-#define pmd_free(mm, pmd) crst_table_free((unsigned long *)pmd)
+#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
 
 #define pgd_populate(mm, pgd, pud)		BUG()
 #define pgd_populate_kernel(mm, pgd, pud)	BUG()
@@ -98,63 +99,55 @@
 
 static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 {
-	pud_t *shadow_pud = get_shadow_table(pud);
-	pmd_t *shadow_pmd = get_shadow_table(pmd);
-
-	if (shadow_pud && shadow_pmd)
-		pud_populate_kernel(mm, shadow_pud, shadow_pmd);
 	pud_populate_kernel(mm, pud, pmd);
+	if (mm->context.noexec) {
+		pud = get_shadow_table(pud);
+		pmd = get_shadow_table(pmd);
+		pud_populate_kernel(mm, pud, pmd);
+	}
 }
 
 #endif /* __s390x__ */
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-	unsigned long *crst = crst_table_alloc(mm, s390_noexec);
+	unsigned long *crst;
+
+	INIT_LIST_HEAD(&mm->context.crst_list);
+	INIT_LIST_HEAD(&mm->context.pgtable_list);
+	crst = crst_table_alloc(mm, s390_noexec);
 	if (crst)
 		crst_table_init(crst, pgd_entry_type(mm));
 	return (pgd_t *) crst;
 }
-#define pgd_free(mm, pgd) crst_table_free((unsigned long *) pgd)
+#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
 
-static inline void 
-pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
+static inline void pmd_populate_kernel(struct mm_struct *mm,
+				       pmd_t *pmd, pte_t *pte)
 {
-#ifndef __s390x__
-	pmd_val(pmd[0]) = _SEGMENT_ENTRY + __pa(pte);
-	pmd_val(pmd[1]) = _SEGMENT_ENTRY + __pa(pte+256);
-	pmd_val(pmd[2]) = _SEGMENT_ENTRY + __pa(pte+512);
-	pmd_val(pmd[3]) = _SEGMENT_ENTRY + __pa(pte+768);
-#else /* __s390x__ */
 	pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
-	pmd_val1(*pmd) = _SEGMENT_ENTRY + __pa(pte+256);
-#endif /* __s390x__ */
 }
 
-static inline void
-pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
+static inline void pmd_populate(struct mm_struct *mm,
+				pmd_t *pmd, pgtable_t pte)
 {
-	pte_t *pte = (pte_t *)page_to_phys(page);
-	pmd_t *shadow_pmd = get_shadow_table(pmd);
-	pte_t *shadow_pte = get_shadow_pte(pte);
-
 	pmd_populate_kernel(mm, pmd, pte);
-	if (shadow_pmd && shadow_pte)
-		pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
+	if (mm->context.noexec) {
+		pmd = get_shadow_table(pmd);
+		pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE);
+	}
 }
-#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#define pmd_pgtable(pmd) \
+	(pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)
 
 /*
  * page table entry allocation/free routines.
  */
-#define pte_alloc_one_kernel(mm, vmaddr) \
-	((pte_t *) page_table_alloc(s390_noexec))
-#define pte_alloc_one(mm, vmaddr) \
-	virt_to_page(page_table_alloc(s390_noexec))
+#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
 
-#define pte_free_kernel(mm, pte) \
-	page_table_free((unsigned long *) pte)
-#define pte_free(mm, pte) \
-	page_table_free((unsigned long *) page_to_phys((struct page *) pte))
+#define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
+#define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
 
 #endif /* _S390_PGALLOC_H */