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 | |
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')
-rw-r--r-- | arch/powerpc/Kconfig.debug | 9 | ||||
-rw-r--r-- | arch/powerpc/mm/init_32.c | 4 | ||||
-rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 52 | ||||
-rw-r--r-- | arch/powerpc/mm/ppc_mmu_32.c | 4 |
4 files changed, 68 insertions, 1 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 50f48f0c5630..0f8bb86995b4 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE | |||
18 | 18 | ||
19 | This option will slow down process creation somewhat. | 19 | This option will slow down process creation somewhat. |
20 | 20 | ||
21 | config DEBUG_PAGEALLOC | ||
22 | bool "Debug page memory allocations" | ||
23 | depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND && PPC32 | ||
24 | help | ||
25 | Unmap pages from the kernel linear mapping after free_pages(). | ||
26 | This results in a large slowdown, but helps to find certain types | ||
27 | of memory corruptions. | ||
28 | |||
29 | |||
21 | config HCALL_STATS | 30 | config HCALL_STATS |
22 | bool "Hypervisor call instrumentation" | 31 | bool "Hypervisor call instrumentation" |
23 | depends on PPC_PSERIES && DEBUG_FS | 32 | depends on PPC_PSERIES && DEBUG_FS |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 0e53ca8f02fb..5fce6ccecb8d 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -115,6 +115,10 @@ void MMU_setup(void) | |||
115 | if (strstr(cmd_line, "noltlbs")) { | 115 | if (strstr(cmd_line, "noltlbs")) { |
116 | __map_without_ltlbs = 1; | 116 | __map_without_ltlbs = 1; |
117 | } | 117 | } |
118 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
119 | __map_without_bats = 1; | ||
120 | __map_without_ltlbs = 1; | ||
121 | #endif | ||
118 | } | 122 | } |
119 | 123 | ||
120 | /* | 124 | /* |
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 */ | ||
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 7cceb2c44cb9..05066674a7a0 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -85,8 +85,10 @@ unsigned long __init mmu_mapin_ram(void) | |||
85 | unsigned long max_size = (256<<20); | 85 | unsigned long max_size = (256<<20); |
86 | unsigned long align; | 86 | unsigned long align; |
87 | 87 | ||
88 | if (__map_without_bats) | 88 | if (__map_without_bats) { |
89 | printk(KERN_DEBUG "RAM mapped without BATs\n"); | ||
89 | return 0; | 90 | return 0; |
91 | } | ||
90 | 92 | ||
91 | /* Set up BAT2 and if necessary BAT3 to cover RAM. */ | 93 | /* Set up BAT2 and if necessary BAT3 to cover RAM. */ |
92 | 94 | ||