aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/vmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/vmem.c')
-rw-r--r--arch/s390/mm/vmem.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index fd594d5fe142..fb9c5a85aa56 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -73,31 +73,28 @@ 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
76static inline pmd_t *vmem_pmd_alloc(void) 78static inline pmd_t *vmem_pmd_alloc(void)
77{ 79{
78 pmd_t *pmd; 80 pmd_t *pmd = NULL;
79 int i;
80 81
81 pmd = vmem_alloc_pages(PMD_ALLOC_ORDER); 82#ifdef CONFIG_64BIT
83 pmd = vmem_alloc_pages(2);
82 if (!pmd) 84 if (!pmd)
83 return NULL; 85 return NULL;
84 for (i = 0; i < PTRS_PER_PMD; i++) 86 clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
85 pmd_clear_kernel(pmd + i); 87#endif
86 return pmd; 88 return pmd;
87} 89}
88 90
89static inline pte_t *vmem_pte_alloc(void) 91static inline pte_t *vmem_pte_alloc(void)
90{ 92{
91 pte_t *pte; 93 pte_t *pte = vmem_alloc_pages(0);
92 pte_t empty_pte;
93 int i;
94 94
95 pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
96 if (!pte) 95 if (!pte)
97 return NULL; 96 return NULL;
98 pte_val(empty_pte) = _PAGE_TYPE_EMPTY; 97 clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
99 for (i = 0; i < PTRS_PER_PTE; i++)
100 pte[i] = empty_pte;
101 return pte; 98 return pte;
102} 99}
103 100
@@ -108,6 +105,7 @@ static int vmem_add_range(unsigned long start, unsigned long size)
108{ 105{
109 unsigned long address; 106 unsigned long address;
110 pgd_t *pg_dir; 107 pgd_t *pg_dir;
108 pud_t *pu_dir;
111 pmd_t *pm_dir; 109 pmd_t *pm_dir;
112 pte_t *pt_dir; 110 pte_t *pt_dir;
113 pte_t pte; 111 pte_t pte;
@@ -116,13 +114,21 @@ static int vmem_add_range(unsigned long start, unsigned long size)
116 for (address = start; address < start + size; address += PAGE_SIZE) { 114 for (address = start; address < start + size; address += PAGE_SIZE) {
117 pg_dir = pgd_offset_k(address); 115 pg_dir = pgd_offset_k(address);
118 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)) {
119 pm_dir = vmem_pmd_alloc(); 125 pm_dir = vmem_pmd_alloc();
120 if (!pm_dir) 126 if (!pm_dir)
121 goto out; 127 goto out;
122 pgd_populate_kernel(&init_mm, pg_dir, pm_dir); 128 pud_populate_kernel(&init_mm, pu_dir, pm_dir);
123 } 129 }
124 130
125 pm_dir = pmd_offset(pg_dir, address); 131 pm_dir = pmd_offset(pu_dir, address);
126 if (pmd_none(*pm_dir)) { 132 if (pmd_none(*pm_dir)) {
127 pt_dir = vmem_pte_alloc(); 133 pt_dir = vmem_pte_alloc();
128 if (!pt_dir) 134 if (!pt_dir)
@@ -148,6 +154,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
148{ 154{
149 unsigned long address; 155 unsigned long address;
150 pgd_t *pg_dir; 156 pgd_t *pg_dir;
157 pud_t *pu_dir;
151 pmd_t *pm_dir; 158 pmd_t *pm_dir;
152 pte_t *pt_dir; 159 pte_t *pt_dir;
153 pte_t pte; 160 pte_t pte;
@@ -155,9 +162,10 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
155 pte_val(pte) = _PAGE_TYPE_EMPTY; 162 pte_val(pte) = _PAGE_TYPE_EMPTY;
156 for (address = start; address < start + size; address += PAGE_SIZE) { 163 for (address = start; address < start + size; address += PAGE_SIZE) {
157 pg_dir = pgd_offset_k(address); 164 pg_dir = pgd_offset_k(address);
158 if (pgd_none(*pg_dir)) 165 pu_dir = pud_offset(pg_dir, address);
166 if (pud_none(*pu_dir))
159 continue; 167 continue;
160 pm_dir = pmd_offset(pg_dir, address); 168 pm_dir = pmd_offset(pu_dir, address);
161 if (pmd_none(*pm_dir)) 169 if (pmd_none(*pm_dir))
162 continue; 170 continue;
163 pt_dir = pte_offset_kernel(pm_dir, address); 171 pt_dir = pte_offset_kernel(pm_dir, address);
@@ -174,6 +182,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
174 unsigned long address, start_addr, end_addr; 182 unsigned long address, start_addr, end_addr;
175 struct page *map_start, *map_end; 183 struct page *map_start, *map_end;
176 pgd_t *pg_dir; 184 pgd_t *pg_dir;
185 pud_t *pu_dir;
177 pmd_t *pm_dir; 186 pmd_t *pm_dir;
178 pte_t *pt_dir; 187 pte_t *pt_dir;
179 pte_t pte; 188 pte_t pte;
@@ -188,13 +197,21 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
188 for (address = start_addr; address < end_addr; address += PAGE_SIZE) { 197 for (address = start_addr; address < end_addr; address += PAGE_SIZE) {
189 pg_dir = pgd_offset_k(address); 198 pg_dir = pgd_offset_k(address);
190 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)) {
191 pm_dir = vmem_pmd_alloc(); 208 pm_dir = vmem_pmd_alloc();
192 if (!pm_dir) 209 if (!pm_dir)
193 goto out; 210 goto out;
194 pgd_populate_kernel(&init_mm, pg_dir, pm_dir); 211 pud_populate_kernel(&init_mm, pu_dir, pm_dir);
195 } 212 }
196 213
197 pm_dir = pmd_offset(pg_dir, address); 214 pm_dir = pmd_offset(pu_dir, address);
198 if (pmd_none(*pm_dir)) { 215 if (pmd_none(*pm_dir)) {
199 pt_dir = vmem_pte_alloc(); 216 pt_dir = vmem_pte_alloc();
200 if (!pt_dir) 217 if (!pt_dir)