diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-04-12 15:30:22 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-04-13 04:09:39 +1000 |
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: return ret; } +#ifdef CONFIG_DEBUG_PAGEALLOC + +static int __change_page_attr(struct page *page, pgprot_t prot) +{ + pte_t *kpte; + pmd_t *kpmd; + unsigned long address; + + BUG_ON(PageHighMem(page)); + address = (unsigned long)page_address(page); + + if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address)) + return 0; + if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) + return -EINVAL; + set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); + wmb(); + flush_HPTE(0, address, pmd_val(*kpmd)); + pte_unmap(kpte); + + return 0; +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY + */ +static int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int i, err = 0; + unsigned long flags; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + err = __change_page_attr(page, prot); + if (err) + break; + } + local_irq_restore(flags); + return err; +} + + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (PageHighMem(page)) + return; + + change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ |