aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 854bd90eeca1..6bad4c4064e7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -190,7 +190,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
190 * 190 *
191 * Must be called with pagetable lock held. 191 * Must be called with pagetable lock held.
192 */ 192 */
193static inline void free_pgd_range(struct mmu_gather *tlb, 193void free_pgd_range(struct mmu_gather **tlb,
194 unsigned long addr, unsigned long end, 194 unsigned long addr, unsigned long end,
195 unsigned long floor, unsigned long ceiling) 195 unsigned long floor, unsigned long ceiling)
196{ 196{
@@ -241,37 +241,47 @@ static inline void free_pgd_range(struct mmu_gather *tlb,
241 return; 241 return;
242 242
243 start = addr; 243 start = addr;
244 pgd = pgd_offset(tlb->mm, addr); 244 pgd = pgd_offset((*tlb)->mm, addr);
245 do { 245 do {
246 next = pgd_addr_end(addr, end); 246 next = pgd_addr_end(addr, end);
247 if (pgd_none_or_clear_bad(pgd)) 247 if (pgd_none_or_clear_bad(pgd))
248 continue; 248 continue;
249 free_pud_range(tlb, pgd, addr, next, floor, ceiling); 249 free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
250 } while (pgd++, addr = next, addr != end); 250 } while (pgd++, addr = next, addr != end);
251 251
252 if (!tlb_is_full_mm(tlb)) 252 if (!tlb_is_full_mm(*tlb))
253 flush_tlb_pgtables(tlb->mm, start, end); 253 flush_tlb_pgtables((*tlb)->mm, start, end);
254} 254}
255 255
256void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma, 256void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
257 unsigned long floor, unsigned long ceiling) 257 unsigned long floor, unsigned long ceiling)
258{ 258{
259 while (vma) { 259 while (vma) {
260 struct vm_area_struct *next = vma->vm_next; 260 struct vm_area_struct *next = vma->vm_next;
261 unsigned long addr = vma->vm_start; 261 unsigned long addr = vma->vm_start;
262 262
263 /* Optimization: gather nearby vmas into a single call down */ 263 if (is_hugepage_only_range(vma->vm_mm, addr, HPAGE_SIZE)) {
264 while (next && next->vm_start <= vma->vm_end + PMD_SIZE) { 264 hugetlb_free_pgd_range(tlb, addr, vma->vm_end,
265 vma = next; 265 floor, next? next->vm_start: ceiling);
266 next = vma->vm_next; 266 } else {
267 } 267 /*
268 free_pgd_range(*tlb, addr, vma->vm_end, 268 * Optimization: gather nearby vmas into one call down
269 */
270 while (next && next->vm_start <= vma->vm_end + PMD_SIZE
271 && !is_hugepage_only_range(vma->vm_mm, next->vm_start,
272 HPAGE_SIZE)) {
273 vma = next;
274 next = vma->vm_next;
275 }
276 free_pgd_range(tlb, addr, vma->vm_end,
269 floor, next? next->vm_start: ceiling); 277 floor, next? next->vm_start: ceiling);
278 }
270 vma = next; 279 vma = next;
271 } 280 }
272} 281}
273 282
274pte_t fastcall * pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address) 283pte_t fastcall *pte_alloc_map(struct mm_struct *mm, pmd_t *pmd,
284 unsigned long address)
275{ 285{
276 if (!pmd_present(*pmd)) { 286 if (!pmd_present(*pmd)) {
277 struct page *new; 287 struct page *new;