diff options
Diffstat (limited to 'arch/powerpc/mm/init_64.c')
-rw-r--r-- | arch/powerpc/mm/init_64.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 68a821add28d..31582329cd67 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -205,6 +205,47 @@ static int __meminit vmemmap_populated(unsigned long start, int page_size) | |||
205 | return 0; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | /* On hash-based CPUs, the vmemmap is bolted in the hash table. | ||
209 | * | ||
210 | * On Book3E CPUs, the vmemmap is currently mapped in the top half of | ||
211 | * the vmalloc space using normal page tables, though the size of | ||
212 | * pages encoded in the PTEs can be different | ||
213 | */ | ||
214 | |||
215 | #ifdef CONFIG_PPC_BOOK3E | ||
216 | static void __meminit vmemmap_create_mapping(unsigned long start, | ||
217 | unsigned long page_size, | ||
218 | unsigned long phys) | ||
219 | { | ||
220 | /* Create a PTE encoding without page size */ | ||
221 | unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED | | ||
222 | _PAGE_KERNEL_RW; | ||
223 | |||
224 | /* PTEs only contain page size encodings up to 32M */ | ||
225 | BUG_ON(mmu_psize_defs[mmu_vmemmap_psize].enc > 0xf); | ||
226 | |||
227 | /* Encode the size in the PTE */ | ||
228 | flags |= mmu_psize_defs[mmu_vmemmap_psize].enc << 8; | ||
229 | |||
230 | /* For each PTE for that area, map things. Note that we don't | ||
231 | * increment phys because all PTEs are of the large size and | ||
232 | * thus must have the low bits clear | ||
233 | */ | ||
234 | for (i = 0; i < page_size; i += PAGE_SIZE) | ||
235 | BUG_ON(map_kernel_page(start + i, phys, flags)); | ||
236 | } | ||
237 | #else /* CONFIG_PPC_BOOK3E */ | ||
238 | static void __meminit vmemmap_create_mapping(unsigned long start, | ||
239 | unsigned long page_size, | ||
240 | unsigned long phys) | ||
241 | { | ||
242 | int mapped = htab_bolt_mapping(start, start + page_size, phys, | ||
243 | PAGE_KERNEL, mmu_vmemmap_psize, | ||
244 | mmu_kernel_ssize); | ||
245 | BUG_ON(mapped < 0); | ||
246 | } | ||
247 | #endif /* CONFIG_PPC_BOOK3E */ | ||
248 | |||
208 | int __meminit vmemmap_populate(struct page *start_page, | 249 | int __meminit vmemmap_populate(struct page *start_page, |
209 | unsigned long nr_pages, int node) | 250 | unsigned long nr_pages, int node) |
210 | { | 251 | { |
@@ -215,8 +256,11 @@ int __meminit vmemmap_populate(struct page *start_page, | |||
215 | /* Align to the page size of the linear mapping. */ | 256 | /* Align to the page size of the linear mapping. */ |
216 | start = _ALIGN_DOWN(start, page_size); | 257 | start = _ALIGN_DOWN(start, page_size); |
217 | 258 | ||
259 | pr_debug("vmemmap_populate page %p, %ld pages, node %d\n", | ||
260 | start_page, nr_pages, node); | ||
261 | pr_debug(" -> map %lx..%lx\n", start, end); | ||
262 | |||
218 | for (; start < end; start += page_size) { | 263 | for (; start < end; start += page_size) { |
219 | int mapped; | ||
220 | void *p; | 264 | void *p; |
221 | 265 | ||
222 | if (vmemmap_populated(start, page_size)) | 266 | if (vmemmap_populated(start, page_size)) |
@@ -226,13 +270,10 @@ int __meminit vmemmap_populate(struct page *start_page, | |||
226 | if (!p) | 270 | if (!p) |
227 | return -ENOMEM; | 271 | return -ENOMEM; |
228 | 272 | ||
229 | pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n", | 273 | pr_debug(" * %016lx..%016lx allocated at %p\n", |
230 | start, p, __pa(p)); | 274 | start, start + page_size, p); |
231 | 275 | ||
232 | mapped = htab_bolt_mapping(start, start + page_size, __pa(p), | 276 | vmemmap_create_mapping(start, page_size, __pa(p)); |
233 | pgprot_val(PAGE_KERNEL), | ||
234 | mmu_vmemmap_psize, mmu_kernel_ssize); | ||
235 | BUG_ON(mapped < 0); | ||
236 | } | 277 | } |
237 | 278 | ||
238 | return 0; | 279 | return 0; |