diff options
author | Jan Beulich <jbeulich@novell.com> | 2009-05-06 08:06:47 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-08 00:51:34 -0400 |
commit | 498343967613183611ac37dccb2846496d954c06 (patch) | |
tree | f0a1f93acbe49e4fb72c5dd77a25dc7f3d970e42 | |
parent | 61438766514a2d7f191ce1b3cf6812eabbef4ef7 (diff) |
x86-64: finish cleanup_highmaps()'s job wrt. _brk_end
With the introduction of the .brk section, special care must be taken
that no unused page table entries remain if _brk_end and _end are
separated by a 2M page boundary. cleanup_highmap() runs very early and
hence cannot take care of that, hence potential entries needing to be
removed past _brk_end must be cleared once the brk allocator has done
its job.
[ Impact: avoids undesirable TLB aliases ]
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/mm/init.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index fd3da1dda1c9..ae4f7b5d7104 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <asm/page.h> | 7 | #include <asm/page.h> |
8 | #include <asm/page_types.h> | 8 | #include <asm/page_types.h> |
9 | #include <asm/sections.h> | 9 | #include <asm/sections.h> |
10 | #include <asm/setup.h> | ||
10 | #include <asm/system.h> | 11 | #include <asm/system.h> |
11 | #include <asm/tlbflush.h> | 12 | #include <asm/tlbflush.h> |
12 | 13 | ||
@@ -304,8 +305,23 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
304 | #endif | 305 | #endif |
305 | 306 | ||
306 | #ifdef CONFIG_X86_64 | 307 | #ifdef CONFIG_X86_64 |
307 | if (!after_bootmem) | 308 | if (!after_bootmem && !start) { |
309 | pud_t *pud; | ||
310 | pmd_t *pmd; | ||
311 | |||
308 | mmu_cr4_features = read_cr4(); | 312 | mmu_cr4_features = read_cr4(); |
313 | |||
314 | /* | ||
315 | * _brk_end cannot change anymore, but it and _end may be | ||
316 | * located on different 2M pages. cleanup_highmap(), however, | ||
317 | * can only consider _end when it runs, so destroy any | ||
318 | * mappings beyond _brk_end here. | ||
319 | */ | ||
320 | pud = pud_offset(pgd_offset_k(_brk_end), _brk_end); | ||
321 | pmd = pmd_offset(pud, _brk_end - 1); | ||
322 | while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1)) | ||
323 | pmd_clear(pmd); | ||
324 | } | ||
309 | #endif | 325 | #endif |
310 | __flush_tlb_all(); | 326 | __flush_tlb_all(); |
311 | 327 | ||