Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jiri Slaby and committed by
Ingo Molnar
59ea7463 952f4a0a

+62 -17
+1 -1
arch/x86/kernel/doublefault_32.c
··· 66 66 .ds = __USER_DS, 67 67 .fs = __KERNEL_PERCPU, 68 68 69 - .__cr3 = __pa(swapper_pg_dir) 69 + .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir) 70 70 } 71 71 };
+25 -8
arch/x86/mm/ioremap.c
··· 23 23 24 24 #ifdef CONFIG_X86_64 25 25 26 - unsigned long __phys_addr(unsigned long x) 27 - { 28 - if (x >= __START_KERNEL_map) 29 - return x - __START_KERNEL_map + phys_base; 30 - return x - PAGE_OFFSET; 31 - } 32 - EXPORT_SYMBOL(__phys_addr); 33 - 34 26 static inline int phys_addr_valid(unsigned long addr) 35 27 { 36 28 return addr < (1UL << boot_cpu_data.x86_phys_bits); 37 29 } 30 + 31 + unsigned long __phys_addr(unsigned long x) 32 + { 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; 44 + } 45 + EXPORT_SYMBOL(__phys_addr); 38 46 39 47 #else 40 48 ··· 50 42 { 51 43 return 1; 52 44 } 45 + 46 + unsigned long __phys_addr(unsigned long x) 47 + { 48 + /* VMALLOC_* aren't constants; not available at the boot time */ 49 + VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING && 50 + is_vmalloc_addr((void *)x))); 51 + return x - PAGE_OFFSET; 52 + } 53 + EXPORT_SYMBOL(__phys_addr); 53 54 54 55 #endif 55 56
+1 -1
include/asm-x86/mmzone_64.h
··· 7 7 8 8 #ifdef CONFIG_NUMA 9 9 10 - #define VIRTUAL_BUG_ON(x) 10 + #include <linux/mmdebug.h> 11 11 12 12 #include <asm/smp.h> 13 13
+2 -1
include/asm-x86/page_32.h
··· 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
+1 -6
include/linux/mm.h
··· 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> ··· 210 209 * files which need it (119 of them) 211 210 */ 212 211 #include <linux/page-flags.h> 213 - 214 - #ifdef CONFIG_DEBUG_VM 215 - #define VM_BUG_ON(cond) BUG_ON(cond) 216 - #else 217 - #define VM_BUG_ON(condition) do { } while(0) 218 - #endif 219 212 220 213 /* 221 214 * Methods to modify the page usage count.
+18
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
+9
lib/Kconfig.debug
··· 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
+5
mm/vmalloc.c
··· 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)) {