Commit 59ea746337c69f6a5f1bc4d5e8544b3cbf12f801
Committed by
Ingo Molnar
1 parent
952f4a0a9b
Exists in
master
and in
4 other branches
MM: virtual address debug
Add some (configurable) expensive sanity checking to catch wrong address translations on x86. - create linux/mmdebug.h file to be able include this file in asm headers to not get unsolvable loops in header files - __phys_addr on x86_32 became a function in ioremap.c since PAGE_OFFSET, is_vmalloc_addr and VMALLOC_* non-constasts are undefined if declared in page_32.h - add __phys_addr_const for initializing doublefault_tss.__cr3 Tested on 386, 386pae, x86_64 and x86_64 numa=fake=2. Contains Andi's enable numa virtual address debug patch. Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 8 changed files with 61 additions and 16 deletions Side-by-side Diff
arch/x86/kernel/doublefault_32.c
arch/x86/mm/ioremap.c
... | ... | @@ -23,18 +23,26 @@ |
23 | 23 | |
24 | 24 | #ifdef CONFIG_X86_64 |
25 | 25 | |
26 | -unsigned long __phys_addr(unsigned long x) | |
26 | +static inline int phys_addr_valid(unsigned long addr) | |
27 | 27 | { |
28 | - if (x >= __START_KERNEL_map) | |
29 | - return x - __START_KERNEL_map + phys_base; | |
30 | - return x - PAGE_OFFSET; | |
28 | + return addr < (1UL << boot_cpu_data.x86_phys_bits); | |
31 | 29 | } |
32 | -EXPORT_SYMBOL(__phys_addr); | |
33 | 30 | |
34 | -static inline int phys_addr_valid(unsigned long addr) | |
31 | +unsigned long __phys_addr(unsigned long x) | |
35 | 32 | { |
36 | - return addr < (1UL << boot_cpu_data.x86_phys_bits); | |
33 | + if (x >= __START_KERNEL_map) { | |
34 | + x -= __START_KERNEL_map; | |
35 | + VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE); | |
36 | + x += phys_base; | |
37 | + } else { | |
38 | + VIRTUAL_BUG_ON(x < PAGE_OFFSET); | |
39 | + x -= PAGE_OFFSET; | |
40 | + VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM : | |
41 | + !phys_addr_valid(x)); | |
42 | + } | |
43 | + return x; | |
37 | 44 | } |
45 | +EXPORT_SYMBOL(__phys_addr); | |
38 | 46 | |
39 | 47 | #else |
40 | 48 | |
... | ... | @@ -42,6 +50,15 @@ |
42 | 50 | { |
43 | 51 | return 1; |
44 | 52 | } |
53 | + | |
54 | +unsigned long __phys_addr(unsigned long x) | |
55 | +{ | |
56 | + /* VMALLOC_* aren't constants; not available at the boot time */ | |
57 | + VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING && | |
58 | + is_vmalloc_addr((void *)x))); | |
59 | + return x - PAGE_OFFSET; | |
60 | +} | |
61 | +EXPORT_SYMBOL(__phys_addr); | |
45 | 62 | |
46 | 63 | #endif |
47 | 64 |
include/asm-x86/mmzone_64.h
include/asm-x86/page_32.h
... | ... | @@ -64,7 +64,8 @@ |
64 | 64 | #endif |
65 | 65 | |
66 | 66 | #ifndef __ASSEMBLY__ |
67 | -#define __phys_addr(x) ((x) - PAGE_OFFSET) | |
67 | +#define __phys_addr_const(x) ((x) - PAGE_OFFSET) | |
68 | +extern unsigned long __phys_addr(unsigned long); | |
68 | 69 | #define __phys_reloc_hide(x) RELOC_HIDE((x), 0) |
69 | 70 | |
70 | 71 | #ifdef CONFIG_FLATMEM |
include/linux/mm.h
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | |
8 | 8 | #include <linux/gfp.h> |
9 | 9 | #include <linux/list.h> |
10 | +#include <linux/mmdebug.h> | |
10 | 11 | #include <linux/mmzone.h> |
11 | 12 | #include <linux/rbtree.h> |
12 | 13 | #include <linux/prio_tree.h> |
... | ... | @@ -209,12 +210,6 @@ |
209 | 210 | * files which need it (119 of them) |
210 | 211 | */ |
211 | 212 | #include <linux/page-flags.h> |
212 | - | |
213 | -#ifdef CONFIG_DEBUG_VM | |
214 | -#define VM_BUG_ON(cond) BUG_ON(cond) | |
215 | -#else | |
216 | -#define VM_BUG_ON(condition) do { } while(0) | |
217 | -#endif | |
218 | 213 | |
219 | 214 | /* |
220 | 215 | * Methods to modify the page usage count. |
include/linux/mmdebug.h
1 | +#ifndef LINUX_MM_DEBUG_H | |
2 | +#define LINUX_MM_DEBUG_H 1 | |
3 | + | |
4 | +#include <linux/autoconf.h> | |
5 | + | |
6 | +#ifdef CONFIG_DEBUG_VM | |
7 | +#define VM_BUG_ON(cond) BUG_ON(cond) | |
8 | +#else | |
9 | +#define VM_BUG_ON(cond) do { } while(0) | |
10 | +#endif | |
11 | + | |
12 | +#ifdef CONFIG_DEBUG_VIRTUAL | |
13 | +#define VIRTUAL_BUG_ON(cond) BUG_ON(cond) | |
14 | +#else | |
15 | +#define VIRTUAL_BUG_ON(cond) do { } while(0) | |
16 | +#endif | |
17 | + | |
18 | +#endif |
lib/Kconfig.debug
... | ... | @@ -469,6 +469,15 @@ |
469 | 469 | |
470 | 470 | If unsure, say N. |
471 | 471 | |
472 | +config DEBUG_VIRTUAL | |
473 | + bool "Debug VM translations" | |
474 | + depends on DEBUG_KERNEL && X86 | |
475 | + help | |
476 | + Enable some costly sanity checks in virtual to page code. This can | |
477 | + catch mistakes with virt_to_page() and friends. | |
478 | + | |
479 | + If unsure, say N. | |
480 | + | |
472 | 481 | config DEBUG_WRITECOUNT |
473 | 482 | bool "Debug filesystem writers count" |
474 | 483 | depends on DEBUG_KERNEL |
mm/vmalloc.c
... | ... | @@ -180,6 +180,11 @@ |
180 | 180 | pmd_t *pmd; |
181 | 181 | pte_t *ptep, pte; |
182 | 182 | |
183 | + /* XXX we might need to change this if we add VIRTUAL_BUG_ON for | |
184 | + * architectures that do not vmalloc module space */ | |
185 | + VIRTUAL_BUG_ON(!is_vmalloc_addr(vmalloc_addr) && | |
186 | + !is_module_address(addr)); | |
187 | + | |
183 | 188 | if (!pgd_none(*pgd)) { |
184 | 189 | pud = pud_offset(pgd, addr); |
185 | 190 | if (!pud_none(*pud)) { |