diff options
Diffstat (limited to 'arch/s390/mm/vmem.c')
-rw-r--r-- | arch/s390/mm/vmem.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 1bd51d840484..fb9c5a85aa56 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c | |||
@@ -73,6 +73,8 @@ static void __init_refok *vmem_alloc_pages(unsigned int order) | |||
73 | return alloc_bootmem_pages((1 << order) * PAGE_SIZE); | 73 | return alloc_bootmem_pages((1 << order) * PAGE_SIZE); |
74 | } | 74 | } |
75 | 75 | ||
76 | #define vmem_pud_alloc() ({ BUG(); ((pud_t *) NULL); }) | ||
77 | |||
76 | static inline pmd_t *vmem_pmd_alloc(void) | 78 | static inline pmd_t *vmem_pmd_alloc(void) |
77 | { | 79 | { |
78 | pmd_t *pmd = NULL; | 80 | pmd_t *pmd = NULL; |
@@ -103,6 +105,7 @@ static int vmem_add_range(unsigned long start, unsigned long size) | |||
103 | { | 105 | { |
104 | unsigned long address; | 106 | unsigned long address; |
105 | pgd_t *pg_dir; | 107 | pgd_t *pg_dir; |
108 | pud_t *pu_dir; | ||
106 | pmd_t *pm_dir; | 109 | pmd_t *pm_dir; |
107 | pte_t *pt_dir; | 110 | pte_t *pt_dir; |
108 | pte_t pte; | 111 | pte_t pte; |
@@ -111,13 +114,21 @@ static int vmem_add_range(unsigned long start, unsigned long size) | |||
111 | for (address = start; address < start + size; address += PAGE_SIZE) { | 114 | for (address = start; address < start + size; address += PAGE_SIZE) { |
112 | pg_dir = pgd_offset_k(address); | 115 | pg_dir = pgd_offset_k(address); |
113 | if (pgd_none(*pg_dir)) { | 116 | if (pgd_none(*pg_dir)) { |
117 | pu_dir = vmem_pud_alloc(); | ||
118 | if (!pu_dir) | ||
119 | goto out; | ||
120 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | ||
121 | } | ||
122 | |||
123 | pu_dir = pud_offset(pg_dir, address); | ||
124 | if (pud_none(*pu_dir)) { | ||
114 | pm_dir = vmem_pmd_alloc(); | 125 | pm_dir = vmem_pmd_alloc(); |
115 | if (!pm_dir) | 126 | if (!pm_dir) |
116 | goto out; | 127 | goto out; |
117 | pgd_populate_kernel(&init_mm, pg_dir, pm_dir); | 128 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); |
118 | } | 129 | } |
119 | 130 | ||
120 | pm_dir = pmd_offset(pg_dir, address); | 131 | pm_dir = pmd_offset(pu_dir, address); |
121 | if (pmd_none(*pm_dir)) { | 132 | if (pmd_none(*pm_dir)) { |
122 | pt_dir = vmem_pte_alloc(); | 133 | pt_dir = vmem_pte_alloc(); |
123 | if (!pt_dir) | 134 | if (!pt_dir) |
@@ -143,6 +154,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size) | |||
143 | { | 154 | { |
144 | unsigned long address; | 155 | unsigned long address; |
145 | pgd_t *pg_dir; | 156 | pgd_t *pg_dir; |
157 | pud_t *pu_dir; | ||
146 | pmd_t *pm_dir; | 158 | pmd_t *pm_dir; |
147 | pte_t *pt_dir; | 159 | pte_t *pt_dir; |
148 | pte_t pte; | 160 | pte_t pte; |
@@ -150,9 +162,10 @@ static void vmem_remove_range(unsigned long start, unsigned long size) | |||
150 | pte_val(pte) = _PAGE_TYPE_EMPTY; | 162 | pte_val(pte) = _PAGE_TYPE_EMPTY; |
151 | for (address = start; address < start + size; address += PAGE_SIZE) { | 163 | for (address = start; address < start + size; address += PAGE_SIZE) { |
152 | pg_dir = pgd_offset_k(address); | 164 | pg_dir = pgd_offset_k(address); |
153 | if (pgd_none(*pg_dir)) | 165 | pu_dir = pud_offset(pg_dir, address); |
166 | if (pud_none(*pu_dir)) | ||
154 | continue; | 167 | continue; |
155 | pm_dir = pmd_offset(pg_dir, address); | 168 | pm_dir = pmd_offset(pu_dir, address); |
156 | if (pmd_none(*pm_dir)) | 169 | if (pmd_none(*pm_dir)) |
157 | continue; | 170 | continue; |
158 | pt_dir = pte_offset_kernel(pm_dir, address); | 171 | pt_dir = pte_offset_kernel(pm_dir, address); |
@@ -169,6 +182,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) | |||
169 | unsigned long address, start_addr, end_addr; | 182 | unsigned long address, start_addr, end_addr; |
170 | struct page *map_start, *map_end; | 183 | struct page *map_start, *map_end; |
171 | pgd_t *pg_dir; | 184 | pgd_t *pg_dir; |
185 | pud_t *pu_dir; | ||
172 | pmd_t *pm_dir; | 186 | pmd_t *pm_dir; |
173 | pte_t *pt_dir; | 187 | pte_t *pt_dir; |
174 | pte_t pte; | 188 | pte_t pte; |
@@ -183,13 +197,21 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) | |||
183 | for (address = start_addr; address < end_addr; address += PAGE_SIZE) { | 197 | for (address = start_addr; address < end_addr; address += PAGE_SIZE) { |
184 | pg_dir = pgd_offset_k(address); | 198 | pg_dir = pgd_offset_k(address); |
185 | if (pgd_none(*pg_dir)) { | 199 | if (pgd_none(*pg_dir)) { |
200 | pu_dir = vmem_pud_alloc(); | ||
201 | if (!pu_dir) | ||
202 | goto out; | ||
203 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | ||
204 | } | ||
205 | |||
206 | pu_dir = pud_offset(pg_dir, address); | ||
207 | if (pud_none(*pu_dir)) { | ||
186 | pm_dir = vmem_pmd_alloc(); | 208 | pm_dir = vmem_pmd_alloc(); |
187 | if (!pm_dir) | 209 | if (!pm_dir) |
188 | goto out; | 210 | goto out; |
189 | pgd_populate_kernel(&init_mm, pg_dir, pm_dir); | 211 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); |
190 | } | 212 | } |
191 | 213 | ||
192 | pm_dir = pmd_offset(pg_dir, address); | 214 | pm_dir = pmd_offset(pu_dir, address); |
193 | if (pmd_none(*pm_dir)) { | 215 | if (pmd_none(*pm_dir)) { |
194 | pt_dir = vmem_pte_alloc(); | 216 | pt_dir = vmem_pte_alloc(); |
195 | if (!pt_dir) | 217 | if (!pt_dir) |