diff options
Diffstat (limited to 'arch/powerpc/mm/pgtable_32.c')
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index c284bdac9947..bca560374927 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -183,8 +183,8 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) | |||
183 | * mem_init() sets high_memory so only do the check after that. | 183 | * mem_init() sets high_memory so only do the check after that. |
184 | */ | 184 | */ |
185 | if (mem_init_done && (p < virt_to_phys(high_memory))) { | 185 | if (mem_init_done && (p < virt_to_phys(high_memory))) { |
186 | printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p, | 186 | printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", |
187 | __builtin_return_address(0)); | 187 | (unsigned long long)p, __builtin_return_address(0)); |
188 | return NULL; | 188 | return NULL; |
189 | } | 189 | } |
190 | 190 | ||
@@ -266,9 +266,12 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) | |||
266 | pg = pte_alloc_kernel(pd, va); | 266 | pg = pte_alloc_kernel(pd, va); |
267 | if (pg != 0) { | 267 | if (pg != 0) { |
268 | err = 0; | 268 | err = 0; |
269 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); | 269 | /* The PTE should never be already set nor present in the |
270 | if (mem_init_done) | 270 | * hash table |
271 | flush_HPTE(0, va, pmd_val(*pd)); | 271 | */ |
272 | BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)); | ||
273 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, | ||
274 | __pgprot(flags))); | ||
272 | } | 275 | } |
273 | return err; | 276 | return err; |
274 | } | 277 | } |
@@ -279,16 +282,19 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) | |||
279 | void __init mapin_ram(void) | 282 | void __init mapin_ram(void) |
280 | { | 283 | { |
281 | unsigned long v, p, s, f; | 284 | unsigned long v, p, s, f; |
285 | int ktext; | ||
282 | 286 | ||
283 | s = mmu_mapin_ram(); | 287 | s = mmu_mapin_ram(); |
284 | v = KERNELBASE + s; | 288 | v = KERNELBASE + s; |
285 | p = PPC_MEMSTART + s; | 289 | p = PPC_MEMSTART + s; |
286 | for (; s < total_lowmem; s += PAGE_SIZE) { | 290 | for (; s < total_lowmem; s += PAGE_SIZE) { |
287 | if ((char *) v >= _stext && (char *) v < etext) | 291 | ktext = ((char *) v >= _stext && (char *) v < etext); |
288 | f = _PAGE_RAM_TEXT; | 292 | f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM; |
289 | else | ||
290 | f = _PAGE_RAM; | ||
291 | map_page(v, p, f); | 293 | map_page(v, p, f); |
294 | #ifdef CONFIG_PPC_STD_MMU_32 | ||
295 | if (ktext) | ||
296 | hash_preload(&init_mm, v, 0, 0x300); | ||
297 | #endif | ||
292 | v += PAGE_SIZE; | 298 | v += PAGE_SIZE; |
293 | p += PAGE_SIZE; | 299 | p += PAGE_SIZE; |
294 | } | 300 | } |
@@ -445,3 +451,55 @@ exit: | |||
445 | return ret; | 451 | return ret; |
446 | } | 452 | } |
447 | 453 | ||
454 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
455 | |||
456 | static int __change_page_attr(struct page *page, pgprot_t prot) | ||
457 | { | ||
458 | pte_t *kpte; | ||
459 | pmd_t *kpmd; | ||
460 | unsigned long address; | ||
461 | |||
462 | BUG_ON(PageHighMem(page)); | ||
463 | address = (unsigned long)page_address(page); | ||
464 | |||
465 | if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address)) | ||
466 | return 0; | ||
467 | if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) | ||
468 | return -EINVAL; | ||
469 | set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); | ||
470 | wmb(); | ||
471 | flush_HPTE(0, address, pmd_val(*kpmd)); | ||
472 | pte_unmap(kpte); | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * Change the page attributes of an page in the linear mapping. | ||
479 | * | ||
480 | * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY | ||
481 | */ | ||
482 | static int change_page_attr(struct page *page, int numpages, pgprot_t prot) | ||
483 | { | ||
484 | int i, err = 0; | ||
485 | unsigned long flags; | ||
486 | |||
487 | local_irq_save(flags); | ||
488 | for (i = 0; i < numpages; i++, page++) { | ||
489 | err = __change_page_attr(page, prot); | ||
490 | if (err) | ||
491 | break; | ||
492 | } | ||
493 | local_irq_restore(flags); | ||
494 | return err; | ||
495 | } | ||
496 | |||
497 | |||
498 | void kernel_map_pages(struct page *page, int numpages, int enable) | ||
499 | { | ||
500 | if (PageHighMem(page)) | ||
501 | return; | ||
502 | |||
503 | change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); | ||
504 | } | ||
505 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||