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.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index c22abf900c9e..387c7c60b5b8 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -79,7 +79,8 @@ static pte_t __ref *vmem_pte_alloc(unsigned long address)
79 */ 79 */
80static int vmem_add_mem(unsigned long start, unsigned long size, int ro) 80static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
81{ 81{
82 unsigned long address; 82 unsigned long end = start + size;
83 unsigned long address = start;
83 pgd_t *pg_dir; 84 pgd_t *pg_dir;
84 pud_t *pu_dir; 85 pud_t *pu_dir;
85 pmd_t *pm_dir; 86 pmd_t *pm_dir;
@@ -87,7 +88,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
87 pte_t pte; 88 pte_t pte;
88 int ret = -ENOMEM; 89 int ret = -ENOMEM;
89 90
90 for (address = start; address < start + size; address += PAGE_SIZE) { 91 while (address < end) {
91 pg_dir = pgd_offset_k(address); 92 pg_dir = pgd_offset_k(address);
92 if (pgd_none(*pg_dir)) { 93 if (pgd_none(*pg_dir)) {
93 pu_dir = vmem_pud_alloc(); 94 pu_dir = vmem_pud_alloc();
@@ -108,12 +109,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
108 pm_dir = pmd_offset(pu_dir, address); 109 pm_dir = pmd_offset(pu_dir, address);
109 110
110#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) 111#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
111 if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && 112 if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
112 (address + HPAGE_SIZE <= start + size) && 113 !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
113 (address >= HPAGE_SIZE)) {
114 pte_val(pte) |= _SEGMENT_ENTRY_LARGE; 114 pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
115 pmd_val(*pm_dir) = pte_val(pte); 115 pmd_val(*pm_dir) = pte_val(pte);
116 address += HPAGE_SIZE - PAGE_SIZE; 116 address += PMD_SIZE;
117 continue; 117 continue;
118 } 118 }
119#endif 119#endif
@@ -126,10 +126,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
126 126
127 pt_dir = pte_offset_kernel(pm_dir, address); 127 pt_dir = pte_offset_kernel(pm_dir, address);
128 *pt_dir = pte; 128 *pt_dir = pte;
129 address += PAGE_SIZE;
129 } 130 }
130 ret = 0; 131 ret = 0;
131out: 132out:
132 flush_tlb_kernel_range(start, start + size); 133 flush_tlb_kernel_range(start, end);
133 return ret; 134 return ret;
134} 135}
135 136
@@ -139,7 +140,8 @@ out:
139 */ 140 */
140static void vmem_remove_range(unsigned long start, unsigned long size) 141static void vmem_remove_range(unsigned long start, unsigned long size)
141{ 142{
142 unsigned long address; 143 unsigned long end = start + size;
144 unsigned long address = start;
143 pgd_t *pg_dir; 145 pgd_t *pg_dir;
144 pud_t *pu_dir; 146 pud_t *pu_dir;
145 pmd_t *pm_dir; 147 pmd_t *pm_dir;
@@ -147,25 +149,32 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
147 pte_t pte; 149 pte_t pte;
148 150
149 pte_val(pte) = _PAGE_TYPE_EMPTY; 151 pte_val(pte) = _PAGE_TYPE_EMPTY;
150 for (address = start; address < start + size; address += PAGE_SIZE) { 152 while (address < end) {
151 pg_dir = pgd_offset_k(address); 153 pg_dir = pgd_offset_k(address);
154 if (pgd_none(*pg_dir)) {
155 address += PGDIR_SIZE;
156 continue;
157 }
152 pu_dir = pud_offset(pg_dir, address); 158 pu_dir = pud_offset(pg_dir, address);
153 if (pud_none(*pu_dir)) 159 if (pud_none(*pu_dir)) {
160 address += PUD_SIZE;
154 continue; 161 continue;
162 }
155 pm_dir = pmd_offset(pu_dir, address); 163 pm_dir = pmd_offset(pu_dir, address);
156 if (pmd_none(*pm_dir)) 164 if (pmd_none(*pm_dir)) {
165 address += PMD_SIZE;
157 continue; 166 continue;
158 167 }
159 if (pmd_huge(*pm_dir)) { 168 if (pmd_large(*pm_dir)) {
160 pmd_clear(pm_dir); 169 pmd_clear(pm_dir);
161 address += HPAGE_SIZE - PAGE_SIZE; 170 address += PMD_SIZE;
162 continue; 171 continue;
163 } 172 }
164
165 pt_dir = pte_offset_kernel(pm_dir, address); 173 pt_dir = pte_offset_kernel(pm_dir, address);
166 *pt_dir = pte; 174 *pt_dir = pte;
175 address += PAGE_SIZE;
167 } 176 }
168 flush_tlb_kernel_range(start, start + size); 177 flush_tlb_kernel_range(start, end);
169} 178}
170 179
171/* 180/*
@@ -330,8 +339,8 @@ void __init vmem_map_init(void)
330 unsigned long start, end; 339 unsigned long start, end;
331 int i; 340 int i;
332 341
333 ro_start = ((unsigned long)&_stext) & PAGE_MASK; 342 ro_start = PFN_ALIGN((unsigned long)&_stext);
334 ro_end = PFN_ALIGN((unsigned long)&_eshared); 343 ro_end = (unsigned long)&_eshared & PAGE_MASK;
335 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { 344 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
336 if (memory_chunk[i].type == CHUNK_CRASHK || 345 if (memory_chunk[i].type == CHUNK_CRASHK ||
337 memory_chunk[i].type == CHUNK_OLDMEM) 346 memory_chunk[i].type == CHUNK_OLDMEM)