Commit 59ea746337c69f6a5f1bc4d5e8544b3cbf12f801

Authored by Jiri Slaby
Committed by Ingo Molnar
1 parent 952f4a0a9b

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
... ... @@ -66,7 +66,7 @@
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 };
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
... ... @@ -7,7 +7,7 @@
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  
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
... ... @@ -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
... ... @@ -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
... ... @@ -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)) {