diff options
Diffstat (limited to 'arch/x86/mm/init_64.c')
-rw-r--r-- | arch/x86/mm/init_64.c | 109 |
1 files changed, 53 insertions, 56 deletions
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index b1352250096e..07f44d491df1 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -168,34 +168,51 @@ static __ref void *spp_getpage(void) | |||
168 | return ptr; | 168 | return ptr; |
169 | } | 169 | } |
170 | 170 | ||
171 | void | 171 | static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) |
172 | set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | ||
173 | { | 172 | { |
174 | pud_t *pud; | 173 | if (pgd_none(*pgd)) { |
175 | pmd_t *pmd; | 174 | pud_t *pud = (pud_t *)spp_getpage(); |
176 | pte_t *pte; | 175 | pgd_populate(&init_mm, pgd, pud); |
176 | if (pud != pud_offset(pgd, 0)) | ||
177 | printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", | ||
178 | pud, pud_offset(pgd, 0)); | ||
179 | } | ||
180 | return pud_offset(pgd, vaddr); | ||
181 | } | ||
177 | 182 | ||
178 | pud = pud_page + pud_index(vaddr); | 183 | static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) |
184 | { | ||
179 | if (pud_none(*pud)) { | 185 | if (pud_none(*pud)) { |
180 | pmd = (pmd_t *) spp_getpage(); | 186 | pmd_t *pmd = (pmd_t *) spp_getpage(); |
181 | pud_populate(&init_mm, pud, pmd); | 187 | pud_populate(&init_mm, pud, pmd); |
182 | if (pmd != pmd_offset(pud, 0)) { | 188 | if (pmd != pmd_offset(pud, 0)) |
183 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", | 189 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", |
184 | pmd, pmd_offset(pud, 0)); | 190 | pmd, pmd_offset(pud, 0)); |
185 | return; | ||
186 | } | ||
187 | } | 191 | } |
188 | pmd = pmd_offset(pud, vaddr); | 192 | return pmd_offset(pud, vaddr); |
193 | } | ||
194 | |||
195 | static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr) | ||
196 | { | ||
189 | if (pmd_none(*pmd)) { | 197 | if (pmd_none(*pmd)) { |
190 | pte = (pte_t *) spp_getpage(); | 198 | pte_t *pte = (pte_t *) spp_getpage(); |
191 | pmd_populate_kernel(&init_mm, pmd, pte); | 199 | pmd_populate_kernel(&init_mm, pmd, pte); |
192 | if (pte != pte_offset_kernel(pmd, 0)) { | 200 | if (pte != pte_offset_kernel(pmd, 0)) |
193 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); | 201 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); |
194 | return; | ||
195 | } | ||
196 | } | 202 | } |
203 | return pte_offset_kernel(pmd, vaddr); | ||
204 | } | ||
205 | |||
206 | void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | ||
207 | { | ||
208 | pud_t *pud; | ||
209 | pmd_t *pmd; | ||
210 | pte_t *pte; | ||
211 | |||
212 | pud = pud_page + pud_index(vaddr); | ||
213 | pmd = fill_pmd(pud, vaddr); | ||
214 | pte = fill_pte(pmd, vaddr); | ||
197 | 215 | ||
198 | pte = pte_offset_kernel(pmd, vaddr); | ||
199 | set_pte(pte, new_pte); | 216 | set_pte(pte, new_pte); |
200 | 217 | ||
201 | /* | 218 | /* |
@@ -205,8 +222,7 @@ set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | |||
205 | __flush_tlb_one(vaddr); | 222 | __flush_tlb_one(vaddr); |
206 | } | 223 | } |
207 | 224 | ||
208 | void | 225 | void set_pte_vaddr(unsigned long vaddr, pte_t pteval) |
209 | set_pte_vaddr(unsigned long vaddr, pte_t pteval) | ||
210 | { | 226 | { |
211 | pgd_t *pgd; | 227 | pgd_t *pgd; |
212 | pud_t *pud_page; | 228 | pud_t *pud_page; |
@@ -223,6 +239,24 @@ set_pte_vaddr(unsigned long vaddr, pte_t pteval) | |||
223 | set_pte_vaddr_pud(pud_page, vaddr, pteval); | 239 | set_pte_vaddr_pud(pud_page, vaddr, pteval); |
224 | } | 240 | } |
225 | 241 | ||
242 | pmd_t * __init populate_extra_pmd(unsigned long vaddr) | ||
243 | { | ||
244 | pgd_t *pgd; | ||
245 | pud_t *pud; | ||
246 | |||
247 | pgd = pgd_offset_k(vaddr); | ||
248 | pud = fill_pud(pgd, vaddr); | ||
249 | return fill_pmd(pud, vaddr); | ||
250 | } | ||
251 | |||
252 | pte_t * __init populate_extra_pte(unsigned long vaddr) | ||
253 | { | ||
254 | pmd_t *pmd; | ||
255 | |||
256 | pmd = populate_extra_pmd(vaddr); | ||
257 | return fill_pte(pmd, vaddr); | ||
258 | } | ||
259 | |||
226 | /* | 260 | /* |
227 | * Create large page table mappings for a range of physical addresses. | 261 | * Create large page table mappings for a range of physical addresses. |
228 | */ | 262 | */ |
@@ -947,43 +981,6 @@ void __init mem_init(void) | |||
947 | initsize >> 10); | 981 | initsize >> 10); |
948 | } | 982 | } |
949 | 983 | ||
950 | void free_init_pages(char *what, unsigned long begin, unsigned long end) | ||
951 | { | ||
952 | unsigned long addr = begin; | ||
953 | |||
954 | if (addr >= end) | ||
955 | return; | ||
956 | |||
957 | /* | ||
958 | * If debugging page accesses then do not free this memory but | ||
959 | * mark them not present - any buggy init-section access will | ||
960 | * create a kernel page fault: | ||
961 | */ | ||
962 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
963 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", | ||
964 | begin, PAGE_ALIGN(end)); | ||
965 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); | ||
966 | #else | ||
967 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); | ||
968 | |||
969 | for (; addr < end; addr += PAGE_SIZE) { | ||
970 | ClearPageReserved(virt_to_page(addr)); | ||
971 | init_page_count(virt_to_page(addr)); | ||
972 | memset((void *)(addr & ~(PAGE_SIZE-1)), | ||
973 | POISON_FREE_INITMEM, PAGE_SIZE); | ||
974 | free_page(addr); | ||
975 | totalram_pages++; | ||
976 | } | ||
977 | #endif | ||
978 | } | ||
979 | |||
980 | void free_initmem(void) | ||
981 | { | ||
982 | free_init_pages("unused kernel memory", | ||
983 | (unsigned long)(&__init_begin), | ||
984 | (unsigned long)(&__init_end)); | ||
985 | } | ||
986 | |||
987 | #ifdef CONFIG_DEBUG_RODATA | 984 | #ifdef CONFIG_DEBUG_RODATA |
988 | const int rodata_test_data = 0xC3; | 985 | const int rodata_test_data = 0xC3; |
989 | EXPORT_SYMBOL_GPL(rodata_test_data); | 986 | EXPORT_SYMBOL_GPL(rodata_test_data); |