summaryrefslogtreecommitdiff
path: root/include/asm-s390/pgalloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390/pgalloc.h')
-rw-r--r--include/asm-s390/pgalloc.h116
1 files changed, 65 insertions, 51 deletions
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 900d44807e10..f5b2bf3d7c1d 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)
{
@@ -72,23 +73,49 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
static inline unsigned long pgd_entry_type(struct mm_struct *mm)
{
- return _REGION3_ENTRY_EMPTY;
+ if (mm->context.asce_limit <= (1UL << 31))
+ return _SEGMENT_ENTRY_EMPTY;
+ if (mm->context.asce_limit <= (1UL << 42))
+ return _REGION3_ENTRY_EMPTY;
+ return _REGION2_ENTRY_EMPTY;
}
-#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
-#define pud_free(mm, x) do { } while (0)
+int crst_table_upgrade(struct mm_struct *, unsigned long limit);
+void crst_table_downgrade(struct mm_struct *, unsigned long limit);
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+ if (table)
+ crst_table_init(table, _REGION3_ENTRY_EMPTY);
+ return (pud_t *) table;
+}
+#define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
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()
+static inline void pgd_populate_kernel(struct mm_struct *mm,
+ pgd_t *pgd, pud_t *pud)
+{
+ pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+ pgd_populate_kernel(mm, pgd, pud);
+ if (mm->context.noexec) {
+ pgd = get_shadow_table(pgd);
+ pud = get_shadow_table(pud);
+ pgd_populate_kernel(mm, pgd, pud);
+ }
+}
static inline void pud_populate_kernel(struct mm_struct *mm,
pud_t *pud, pmd_t *pmd)
@@ -98,63 +125,50 @@ static inline void pud_populate_kernel(struct mm_struct *mm,
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);
- if (crst)
- crst_table_init(crst, pgd_entry_type(mm));
- return (pgd_t *) crst;
+ INIT_LIST_HEAD(&mm->context.crst_list);
+ INIT_LIST_HEAD(&mm->context.pgtable_list);
+ return (pgd_t *) crst_table_alloc(mm, s390_noexec);
}
-#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_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_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(mm, (unsigned long *) pte)
+#define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
#endif /* _S390_PGALLOC_H */