diff options
-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 | ||||
-rw-r--r-- | include/asm-powerpc/cacheflush.h | 6 |
5 files changed, 74 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 | ||
diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h index 08e93e789219..ba667a383b8c 100644 --- a/include/asm-powerpc/cacheflush.h +++ b/include/asm-powerpc/cacheflush.h | |||
@@ -64,6 +64,12 @@ extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); | |||
64 | memcpy(dst, src, len) | 64 | memcpy(dst, src, len) |
65 | 65 | ||
66 | 66 | ||
67 | |||
68 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
69 | /* internal debugging function */ | ||
70 | void kernel_map_pages(struct page *page, int numpages, int enable); | ||
71 | #endif | ||
72 | |||
67 | #endif /* __KERNEL__ */ | 73 | #endif /* __KERNEL__ */ |
68 | 74 | ||
69 | #endif /* _ASM_POWERPC_CACHEFLUSH_H */ | 75 | #endif /* _ASM_POWERPC_CACHEFLUSH_H */ |