diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index a4a9cccdd4f2..bb652f5a93fb 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -171,6 +171,33 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | |||
171 | __flush_tlb_one(vaddr); | 171 | __flush_tlb_one(vaddr); |
172 | } | 172 | } |
173 | 173 | ||
174 | /* | ||
175 | * The head.S code sets up the kernel high mapping from: | ||
176 | * __START_KERNEL_map to __START_KERNEL_map + KERNEL_TEXT_SIZE | ||
177 | * | ||
178 | * phys_addr holds the negative offset to the kernel, which is added | ||
179 | * to the compile time generated pmds. This results in invalid pmds up | ||
180 | * to the point where we hit the physaddr 0 mapping. | ||
181 | * | ||
182 | * We limit the mappings to the region from _text to _end. _end is | ||
183 | * rounded up to the 2MB boundary. This catches the invalid pmds as | ||
184 | * well, as they are located before _text: | ||
185 | */ | ||
186 | void __init cleanup_highmap(void) | ||
187 | { | ||
188 | unsigned long vaddr = __START_KERNEL_map; | ||
189 | unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; | ||
190 | pmd_t *pmd = level2_kernel_pgt; | ||
191 | pmd_t *last_pmd = pmd + PTRS_PER_PMD; | ||
192 | |||
193 | for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { | ||
194 | if (!pmd_present(*pmd)) | ||
195 | continue; | ||
196 | if (vaddr < (unsigned long) _text || vaddr > end) | ||
197 | set_pmd(pmd, __pmd(0)); | ||
198 | } | ||
199 | } | ||
200 | |||
174 | /* NOTE: this is meant to be run only at boot */ | 201 | /* NOTE: this is meant to be run only at boot */ |
175 | void __init | 202 | void __init |
176 | __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) | 203 | __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) |