aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/pgtable_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/pgtable_32.c')
-rw-r--r--arch/powerpc/mm/pgtable_32.c76
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)
279void __init mapin_ram(void) 282void __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
456static 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 */
482static 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
498void 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 */