1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2c6557e7fSMartin Schwidefsky /*
3c6557e7fSMartin Schwidefsky * S390 version
4a53c8fabSHeiko Carstens * Copyright IBM Corp. 1999, 2000
5c6557e7fSMartin Schwidefsky * Author(s): Hartmut Penner (hp@de.ibm.com)
6c6557e7fSMartin Schwidefsky * Martin Schwidefsky (schwidefsky@de.ibm.com)
7c6557e7fSMartin Schwidefsky *
8c6557e7fSMartin Schwidefsky * Derived from "include/asm-i386/pgalloc.h"
9c6557e7fSMartin Schwidefsky * Copyright (C) 1994 Linus Torvalds
10c6557e7fSMartin Schwidefsky */
11c6557e7fSMartin Schwidefsky
12c6557e7fSMartin Schwidefsky #ifndef _S390_PGALLOC_H
13c6557e7fSMartin Schwidefsky #define _S390_PGALLOC_H
14c6557e7fSMartin Schwidefsky
15c6557e7fSMartin Schwidefsky #include <linux/threads.h>
1641879ff6SHeiko Carstens #include <linux/string.h>
17c6557e7fSMartin Schwidefsky #include <linux/gfp.h>
18c6557e7fSMartin Schwidefsky #include <linux/mm.h>
19c6557e7fSMartin Schwidefsky
20c67da7c7SHeiko Carstens #define CRST_ALLOC_ORDER 2
21c67da7c7SHeiko Carstens
22043d0708SMartin Schwidefsky unsigned long *crst_table_alloc(struct mm_struct *);
23c6557e7fSMartin Schwidefsky void crst_table_free(struct mm_struct *, unsigned long *);
24c6557e7fSMartin Schwidefsky
25527e30b4SMartin Schwidefsky unsigned long *page_table_alloc(struct mm_struct *);
264be130a0SMartin Schwidefsky struct page *page_table_alloc_pgste(struct mm_struct *mm);
27c6557e7fSMartin Schwidefsky void page_table_free(struct mm_struct *, unsigned long *);
28527e30b4SMartin Schwidefsky void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
294be130a0SMartin Schwidefsky void page_table_free_pgste(struct page *page);
300b46e0a3SMartin Schwidefsky extern int page_table_allocate_pgste;
31c6557e7fSMartin Schwidefsky
crst_table_init(unsigned long * crst,unsigned long entry)32c6557e7fSMartin Schwidefsky static inline void crst_table_init(unsigned long *crst, unsigned long entry)
33c6557e7fSMartin Schwidefsky {
3441879ff6SHeiko Carstens memset64((u64 *)crst, entry, _CRST_ENTRIES);
35c6557e7fSMartin Schwidefsky }
36c6557e7fSMartin Schwidefsky
371aea9b3fSMartin Schwidefsky int crst_table_upgrade(struct mm_struct *mm, unsigned long limit);
38c6557e7fSMartin Schwidefsky
check_asce_limit(struct mm_struct * mm,unsigned long addr,unsigned long len)39712fa5f2SAlexander Gordeev static inline unsigned long check_asce_limit(struct mm_struct *mm, unsigned long addr,
40712fa5f2SAlexander Gordeev unsigned long len)
41712fa5f2SAlexander Gordeev {
42712fa5f2SAlexander Gordeev int rc;
43712fa5f2SAlexander Gordeev
44712fa5f2SAlexander Gordeev if (addr + len > mm->context.asce_limit &&
45712fa5f2SAlexander Gordeev addr + len <= TASK_SIZE) {
46712fa5f2SAlexander Gordeev rc = crst_table_upgrade(mm, addr + len);
47712fa5f2SAlexander Gordeev if (rc)
48712fa5f2SAlexander Gordeev return (unsigned long) rc;
49712fa5f2SAlexander Gordeev }
50712fa5f2SAlexander Gordeev return addr;
51712fa5f2SAlexander Gordeev }
52712fa5f2SAlexander Gordeev
p4d_alloc_one(struct mm_struct * mm,unsigned long address)531aea9b3fSMartin Schwidefsky static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address)
541aea9b3fSMartin Schwidefsky {
551aea9b3fSMartin Schwidefsky unsigned long *table = crst_table_alloc(mm);
561aea9b3fSMartin Schwidefsky
571aea9b3fSMartin Schwidefsky if (table)
581aea9b3fSMartin Schwidefsky crst_table_init(table, _REGION2_ENTRY_EMPTY);
591aea9b3fSMartin Schwidefsky return (p4d_t *) table;
601aea9b3fSMartin Schwidefsky }
612416cefcSGerald Schaefer
p4d_free(struct mm_struct * mm,p4d_t * p4d)622416cefcSGerald Schaefer static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
632416cefcSGerald Schaefer {
642416cefcSGerald Schaefer if (!mm_p4d_folded(mm))
652416cefcSGerald Schaefer crst_table_free(mm, (unsigned long *) p4d);
662416cefcSGerald Schaefer }
671aea9b3fSMartin Schwidefsky
pud_alloc_one(struct mm_struct * mm,unsigned long address)68c6557e7fSMartin Schwidefsky static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
69c6557e7fSMartin Schwidefsky {
70043d0708SMartin Schwidefsky unsigned long *table = crst_table_alloc(mm);
71c6557e7fSMartin Schwidefsky if (table)
72c6557e7fSMartin Schwidefsky crst_table_init(table, _REGION3_ENTRY_EMPTY);
73c6557e7fSMartin Schwidefsky return (pud_t *) table;
74c6557e7fSMartin Schwidefsky }
752416cefcSGerald Schaefer
pud_free(struct mm_struct * mm,pud_t * pud)762416cefcSGerald Schaefer static inline void pud_free(struct mm_struct *mm, pud_t *pud)
772416cefcSGerald Schaefer {
782416cefcSGerald Schaefer if (!mm_pud_folded(mm))
792416cefcSGerald Schaefer crst_table_free(mm, (unsigned long *) pud);
802416cefcSGerald Schaefer }
81c6557e7fSMartin Schwidefsky
pmd_alloc_one(struct mm_struct * mm,unsigned long vmaddr)82c6557e7fSMartin Schwidefsky static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
83c6557e7fSMartin Schwidefsky {
84043d0708SMartin Schwidefsky unsigned long *table = crst_table_alloc(mm);
85ec66ad66SMartin Schwidefsky
86ec66ad66SMartin Schwidefsky if (!table)
87ec66ad66SMartin Schwidefsky return NULL;
88c6557e7fSMartin Schwidefsky crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
89*6326c26cSVishal Moola (Oracle) if (!pagetable_pmd_ctor(virt_to_ptdesc(table))) {
90ec66ad66SMartin Schwidefsky crst_table_free(mm, table);
91ec66ad66SMartin Schwidefsky return NULL;
92ec66ad66SMartin Schwidefsky }
93c6557e7fSMartin Schwidefsky return (pmd_t *) table;
94c6557e7fSMartin Schwidefsky }
95ec66ad66SMartin Schwidefsky
pmd_free(struct mm_struct * mm,pmd_t * pmd)96ec66ad66SMartin Schwidefsky static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
97ec66ad66SMartin Schwidefsky {
982416cefcSGerald Schaefer if (mm_pmd_folded(mm))
992416cefcSGerald Schaefer return;
100*6326c26cSVishal Moola (Oracle) pagetable_pmd_dtor(virt_to_ptdesc(pmd));
101ec66ad66SMartin Schwidefsky crst_table_free(mm, (unsigned long *) pmd);
102ec66ad66SMartin Schwidefsky }
103c6557e7fSMartin Schwidefsky
pgd_populate(struct mm_struct * mm,pgd_t * pgd,p4d_t * p4d)1041aea9b3fSMartin Schwidefsky static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d)
105c6557e7fSMartin Schwidefsky {
106b8e3b379SHeiko Carstens set_pgd(pgd, __pgd(_REGION1_ENTRY | __pa(p4d)));
1071aea9b3fSMartin Schwidefsky }
1081aea9b3fSMartin Schwidefsky
p4d_populate(struct mm_struct * mm,p4d_t * p4d,pud_t * pud)1091aea9b3fSMartin Schwidefsky static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
1101aea9b3fSMartin Schwidefsky {
111b8e3b379SHeiko Carstens set_p4d(p4d, __p4d(_REGION2_ENTRY | __pa(pud)));
112c6557e7fSMartin Schwidefsky }
113c6557e7fSMartin Schwidefsky
pud_populate(struct mm_struct * mm,pud_t * pud,pmd_t * pmd)114c6557e7fSMartin Schwidefsky static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
115c6557e7fSMartin Schwidefsky {
116b8e3b379SHeiko Carstens set_pud(pud, __pud(_REGION3_ENTRY | __pa(pmd)));
117c6557e7fSMartin Schwidefsky }
118c6557e7fSMartin Schwidefsky
pgd_alloc(struct mm_struct * mm)119c6557e7fSMartin Schwidefsky static inline pgd_t *pgd_alloc(struct mm_struct *mm)
120c6557e7fSMartin Schwidefsky {
1216a3eb35eSAlexander Gordeev return (pgd_t *) crst_table_alloc(mm);
1223446c13bSMartin Schwidefsky }
1233446c13bSMartin Schwidefsky
pgd_free(struct mm_struct * mm,pgd_t * pgd)1243446c13bSMartin Schwidefsky static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
1253446c13bSMartin Schwidefsky {
1263446c13bSMartin Schwidefsky crst_table_free(mm, (unsigned long *) pgd);
1273446c13bSMartin Schwidefsky }
128c6557e7fSMartin Schwidefsky
pmd_populate(struct mm_struct * mm,pmd_t * pmd,pgtable_t pte)129b2fa47e6SMartin Schwidefsky static inline void pmd_populate(struct mm_struct *mm,
130b2fa47e6SMartin Schwidefsky pmd_t *pmd, pgtable_t pte)
131c6557e7fSMartin Schwidefsky {
132b8e3b379SHeiko Carstens set_pmd(pmd, __pmd(_SEGMENT_ENTRY | __pa(pte)));
133c6557e7fSMartin Schwidefsky }
134c6557e7fSMartin Schwidefsky
135b2fa47e6SMartin Schwidefsky #define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte)
136c6557e7fSMartin Schwidefsky
137c6557e7fSMartin Schwidefsky /*
138c6557e7fSMartin Schwidefsky * page table entry allocation/free routines.
139c6557e7fSMartin Schwidefsky */
1404cf58924SJoel Fernandes (Google) #define pte_alloc_one_kernel(mm) ((pte_t *)page_table_alloc(mm))
1414cf58924SJoel Fernandes (Google) #define pte_alloc_one(mm) ((pte_t *)page_table_alloc(mm))
142c6557e7fSMartin Schwidefsky
143c6557e7fSMartin Schwidefsky #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
144c6557e7fSMartin Schwidefsky #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
145c6557e7fSMartin Schwidefsky
1468211dad6SHugh Dickins /* arch use pte_free_defer() implementation in arch/s390/mm/pgalloc.c */
1478211dad6SHugh Dickins #define pte_free_defer pte_free_defer
1488211dad6SHugh Dickins void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable);
1498211dad6SHugh Dickins
150a01ef308SHeiko Carstens void vmem_map_init(void);
151a01ef308SHeiko Carstens void *vmem_crst_alloc(unsigned long val);
152a01ef308SHeiko Carstens pte_t *vmem_pte_alloc(void);
153a01ef308SHeiko Carstens
1541caf170dSHeiko Carstens unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages);
1551caf170dSHeiko Carstens void base_asce_free(unsigned long asce);
1561caf170dSHeiko Carstens
157c6557e7fSMartin Schwidefsky #endif /* _S390_PGALLOC_H */
158