Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 | 2 | /* |
1da177e4 | 3 | * S390 version |
a53c8fab | 4 | * Copyright IBM Corp. 1999, 2000 |
1da177e4 LT |
5 | * Author(s): Hartmut Penner (hp@de.ibm.com) |
6 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | |
7 | * | |
8 | * Derived from "include/asm-i386/pgalloc.h" | |
9 | * Copyright (C) 1994 Linus Torvalds | |
10 | */ | |
11 | ||
12 | #ifndef _S390_PGALLOC_H | |
13 | #define _S390_PGALLOC_H | |
14 | ||
1da177e4 | 15 | #include <linux/threads.h> |
41879ff6 | 16 | #include <linux/string.h> |
1da177e4 LT |
17 | #include <linux/gfp.h> |
18 | #include <linux/mm.h> | |
19 | ||
c67da7c7 HC |
20 | #define CRST_ALLOC_ORDER 2 |
21 | ||
043d0708 | 22 | unsigned long *crst_table_alloc(struct mm_struct *); |
146e4b3c | 23 | void crst_table_free(struct mm_struct *, unsigned long *); |
9282ed92 | 24 | |
527e30b4 | 25 | unsigned long *page_table_alloc(struct mm_struct *); |
57b77b75 | 26 | struct ptdesc *page_table_alloc_pgste(struct mm_struct *mm); |
146e4b3c | 27 | void page_table_free(struct mm_struct *, unsigned long *); |
57b77b75 | 28 | void page_table_free_pgste(struct ptdesc *ptdesc); |
1da177e4 | 29 | |
3610cce8 | 30 | static inline void crst_table_init(unsigned long *crst, unsigned long entry) |
1da177e4 | 31 | { |
41879ff6 | 32 | memset64((u64 *)crst, entry, _CRST_ENTRIES); |
1da177e4 LT |
33 | } |
34 | ||
1aea9b3f | 35 | int crst_table_upgrade(struct mm_struct *mm, unsigned long limit); |
6252d702 | 36 | |
712fa5f2 AG |
37 | static inline unsigned long check_asce_limit(struct mm_struct *mm, unsigned long addr, |
38 | unsigned long len) | |
39 | { | |
40 | int rc; | |
41 | ||
42 | if (addr + len > mm->context.asce_limit && | |
43 | addr + len <= TASK_SIZE) { | |
44 | rc = crst_table_upgrade(mm, addr + len); | |
45 | if (rc) | |
46 | return (unsigned long) rc; | |
47 | } | |
48 | return addr; | |
49 | } | |
50 | ||
1aea9b3f MS |
51 | static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address) |
52 | { | |
53 | unsigned long *table = crst_table_alloc(mm); | |
54 | ||
b7dcd539 QZ |
55 | if (!table) |
56 | return NULL; | |
57 | crst_table_init(table, _REGION2_ENTRY_EMPTY); | |
58 | pagetable_p4d_ctor(virt_to_ptdesc(table)); | |
59 | ||
1aea9b3f MS |
60 | return (p4d_t *) table; |
61 | } | |
2416cefc GS |
62 | |
63 | static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d) | |
64 | { | |
b7dcd539 QZ |
65 | if (mm_p4d_folded(mm)) |
66 | return; | |
67 | ||
db6b435d | 68 | pagetable_dtor(virt_to_ptdesc(p4d)); |
b7dcd539 | 69 | crst_table_free(mm, (unsigned long *) p4d); |
2416cefc | 70 | } |
1aea9b3f | 71 | |
5a216a20 MS |
72 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) |
73 | { | |
043d0708 | 74 | unsigned long *table = crst_table_alloc(mm); |
b7dcd539 QZ |
75 | |
76 | if (!table) | |
77 | return NULL; | |
78 | crst_table_init(table, _REGION3_ENTRY_EMPTY); | |
79 | pagetable_pud_ctor(virt_to_ptdesc(table)); | |
80 | ||
5a216a20 MS |
81 | return (pud_t *) table; |
82 | } | |
2416cefc GS |
83 | |
84 | static inline void pud_free(struct mm_struct *mm, pud_t *pud) | |
85 | { | |
b7dcd539 QZ |
86 | if (mm_pud_folded(mm)) |
87 | return; | |
88 | ||
db6b435d | 89 | pagetable_dtor(virt_to_ptdesc(pud)); |
b7dcd539 | 90 | crst_table_free(mm, (unsigned long *) pud); |
2416cefc | 91 | } |
190a1d72 | 92 | |
3610cce8 | 93 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) |
1da177e4 | 94 | { |
043d0708 | 95 | unsigned long *table = crst_table_alloc(mm); |
ec66ad66 MS |
96 | |
97 | if (!table) | |
98 | return NULL; | |
99 | crst_table_init(table, _SEGMENT_ENTRY_EMPTY); | |
d82d3bf4 | 100 | if (!pagetable_pmd_ctor(mm, virt_to_ptdesc(table))) { |
ec66ad66 MS |
101 | crst_table_free(mm, table); |
102 | return NULL; | |
103 | } | |
146e4b3c | 104 | return (pmd_t *) table; |
1da177e4 | 105 | } |
ec66ad66 MS |
106 | |
107 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | |
108 | { | |
2416cefc GS |
109 | if (mm_pmd_folded(mm)) |
110 | return; | |
db6b435d | 111 | pagetable_dtor(virt_to_ptdesc(pmd)); |
ec66ad66 MS |
112 | crst_table_free(mm, (unsigned long *) pmd); |
113 | } | |
1da177e4 | 114 | |
1aea9b3f MS |
115 | static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d) |
116 | { | |
b8e3b379 | 117 | set_pgd(pgd, __pgd(_REGION1_ENTRY | __pa(p4d))); |
1aea9b3f MS |
118 | } |
119 | ||
120 | static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud) | |
5a216a20 | 121 | { |
b8e3b379 | 122 | set_p4d(p4d, __p4d(_REGION2_ENTRY | __pa(pud))); |
1da177e4 LT |
123 | } |
124 | ||
190a1d72 | 125 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
c1821c2e | 126 | { |
b8e3b379 | 127 | set_pud(pud, __pud(_REGION3_ENTRY | __pa(pmd))); |
c1821c2e GS |
128 | } |
129 | ||
3610cce8 MS |
130 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
131 | { | |
d95936a2 KB |
132 | unsigned long *table = crst_table_alloc(mm); |
133 | ||
134 | if (!table) | |
135 | return NULL; | |
136 | pagetable_pgd_ctor(virt_to_ptdesc(table)); | |
137 | ||
138 | return (pgd_t *) table; | |
3446c13b MS |
139 | } |
140 | ||
141 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |
142 | { | |
d95936a2 | 143 | pagetable_dtor(virt_to_ptdesc(pgd)); |
3446c13b | 144 | crst_table_free(mm, (unsigned long *) pgd); |
3610cce8 | 145 | } |
3610cce8 | 146 | |
146e4b3c MS |
147 | static inline void pmd_populate(struct mm_struct *mm, |
148 | pmd_t *pmd, pgtable_t pte) | |
1da177e4 | 149 | { |
b8e3b379 | 150 | set_pmd(pmd, __pmd(_SEGMENT_ENTRY | __pa(pte))); |
1da177e4 | 151 | } |
146e4b3c | 152 | |
b2fa47e6 MS |
153 | #define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte) |
154 | ||
1da177e4 LT |
155 | /* |
156 | * page table entry allocation/free routines. | |
157 | */ | |
4cf58924 JFG |
158 | #define pte_alloc_one_kernel(mm) ((pte_t *)page_table_alloc(mm)) |
159 | #define pte_alloc_one(mm) ((pte_t *)page_table_alloc(mm)) | |
146e4b3c MS |
160 | |
161 | #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte) | |
162 | #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) | |
1da177e4 | 163 | |
8211dad6 HD |
164 | /* arch use pte_free_defer() implementation in arch/s390/mm/pgalloc.c */ |
165 | #define pte_free_defer pte_free_defer | |
166 | void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable); | |
167 | ||
a01ef308 HC |
168 | void vmem_map_init(void); |
169 | void *vmem_crst_alloc(unsigned long val); | |
170 | pte_t *vmem_pte_alloc(void); | |
171 | ||
1caf170d HC |
172 | unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages); |
173 | void base_asce_free(unsigned long asce); | |
174 | ||
1da177e4 | 175 | #endif /* _S390_PGALLOC_H */ |