diff options
Diffstat (limited to 'arch/s390/mm/vmem.c')
-rw-r--r-- | arch/s390/mm/vmem.c | 45 |
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 | */ |
80 | static int vmem_add_mem(unsigned long start, unsigned long size, int ro) | 80 | static 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; |
131 | out: | 132 | out: |
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 | */ |
140 | static void vmem_remove_range(unsigned long start, unsigned long size) | 141 | static 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) |