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 | ||
