diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-04-12 01:30:22 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-04-12 14:09:39 -0400 |
commit | 88df6e90fa9782dbf44d936e44649afe271e4790 (patch) | |
tree | d0f4c46731e35e96a381dd3e3138f0276741ca57 /arch/powerpc/mm/pgtable_32.c | |
parent | ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4 (diff) |
[POWERPC] DEBUG_PAGEALLOC for 32-bit
Here's an implementation of DEBUG_PAGEALLOC for ppc32. It disables BAT
mapping and is only tested with Hash table based processor though it
shouldn't be too hard to adapt it to others.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/Kconfig.debug | 9 ++++++
arch/powerpc/mm/init_32.c | 4 +++
arch/powerpc/mm/pgtable_32.c | 52 +++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/ppc_mmu_32.c | 4 ++-
include/asm-powerpc/cacheflush.h | 6 ++++
5 files changed, 74 insertions(+), 1 deletion(-)
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/mm/pgtable_32.c')
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f75f2fc7bc7e..8a2fc16ee0a7 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -451,3 +451,55 @@ exit: | |||
451 | return ret; | 451 | return ret; |
452 | } | 452 | } |
453 | 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 */ | ||