diff options
| -rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 12 | ||||
| -rw-r--r-- | include/linux/page-flags.h | 8 | ||||
| -rw-r--r-- | mm/debug.c | 46 | ||||
| -rw-r--r-- | mm/memblock.c | 5 | ||||
| -rw-r--r-- | mm/sparse.c | 4 |
5 files changed, 69 insertions, 6 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 8022d902e770..dcd082576e79 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
| @@ -4839,6 +4839,18 @@ | |||
| 4839 | This is actually a boot loader parameter; the value is | 4839 | This is actually a boot loader parameter; the value is |
| 4840 | passed to the kernel using a special protocol. | 4840 | passed to the kernel using a special protocol. |
| 4841 | 4841 | ||
| 4842 | vm_debug[=options] [KNL] Available with CONFIG_DEBUG_VM=y. | ||
| 4843 | May slow down system boot speed, especially when | ||
| 4844 | enabled on systems with a large amount of memory. | ||
| 4845 | All options are enabled by default, and this | ||
| 4846 | interface is meant to allow for selectively | ||
| 4847 | enabling or disabling specific virtual memory | ||
| 4848 | debugging features. | ||
| 4849 | |||
| 4850 | Available options are: | ||
| 4851 | P Enable page structure init time poisoning | ||
| 4852 | - Disable all of the above options | ||
| 4853 | |||
| 4842 | vmalloc=nn[KMG] [KNL,BOOT] Forces the vmalloc area to have an exact | 4854 | vmalloc=nn[KMG] [KNL,BOOT] Forces the vmalloc area to have an exact |
| 4843 | size of <nn>. This can be used to increase the | 4855 | size of <nn>. This can be used to increase the |
| 4844 | minimum size (128MB on x86). It can also be used to | 4856 | minimum size (128MB on x86). It can also be used to |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 4d99504f6496..934f91ef3f54 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
| @@ -163,6 +163,14 @@ static inline int PagePoisoned(const struct page *page) | |||
| 163 | return page->flags == PAGE_POISON_PATTERN; | 163 | return page->flags == PAGE_POISON_PATTERN; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | #ifdef CONFIG_DEBUG_VM | ||
| 167 | void page_init_poison(struct page *page, size_t size); | ||
| 168 | #else | ||
| 169 | static inline void page_init_poison(struct page *page, size_t size) | ||
| 170 | { | ||
| 171 | } | ||
| 172 | #endif | ||
| 173 | |||
| 166 | /* | 174 | /* |
| 167 | * Page flags policies wrt compound pages | 175 | * Page flags policies wrt compound pages |
| 168 | * | 176 | * |
diff --git a/mm/debug.c b/mm/debug.c index bd10aad8539a..cdacba12e09a 100644 --- a/mm/debug.c +++ b/mm/debug.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <trace/events/mmflags.h> | 13 | #include <trace/events/mmflags.h> |
| 14 | #include <linux/migrate.h> | 14 | #include <linux/migrate.h> |
| 15 | #include <linux/page_owner.h> | 15 | #include <linux/page_owner.h> |
| 16 | #include <linux/ctype.h> | ||
| 16 | 17 | ||
| 17 | #include "internal.h" | 18 | #include "internal.h" |
| 18 | 19 | ||
| @@ -175,4 +176,49 @@ void dump_mm(const struct mm_struct *mm) | |||
| 175 | ); | 176 | ); |
| 176 | } | 177 | } |
| 177 | 178 | ||
| 179 | static bool page_init_poisoning __read_mostly = true; | ||
| 180 | |||
| 181 | static int __init setup_vm_debug(char *str) | ||
| 182 | { | ||
| 183 | bool __page_init_poisoning = true; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Calling vm_debug with no arguments is equivalent to requesting | ||
| 187 | * to enable all debugging options we can control. | ||
| 188 | */ | ||
| 189 | if (*str++ != '=' || !*str) | ||
| 190 | goto out; | ||
| 191 | |||
| 192 | __page_init_poisoning = false; | ||
| 193 | if (*str == '-') | ||
| 194 | goto out; | ||
| 195 | |||
| 196 | while (*str) { | ||
| 197 | switch (tolower(*str)) { | ||
| 198 | case'p': | ||
| 199 | __page_init_poisoning = true; | ||
| 200 | break; | ||
| 201 | default: | ||
| 202 | pr_err("vm_debug option '%c' unknown. skipped\n", | ||
| 203 | *str); | ||
| 204 | } | ||
| 205 | |||
| 206 | str++; | ||
| 207 | } | ||
| 208 | out: | ||
| 209 | if (page_init_poisoning && !__page_init_poisoning) | ||
| 210 | pr_warn("Page struct poisoning disabled by kernel command line option 'vm_debug'\n"); | ||
| 211 | |||
| 212 | page_init_poisoning = __page_init_poisoning; | ||
| 213 | |||
| 214 | return 1; | ||
| 215 | } | ||
| 216 | __setup("vm_debug", setup_vm_debug); | ||
| 217 | |||
| 218 | void page_init_poison(struct page *page, size_t size) | ||
| 219 | { | ||
| 220 | if (page_init_poisoning) | ||
| 221 | memset(page, PAGE_POISON_PATTERN, size); | ||
| 222 | } | ||
| 223 | EXPORT_SYMBOL_GPL(page_init_poison); | ||
| 178 | #endif /* CONFIG_DEBUG_VM */ | 224 | #endif /* CONFIG_DEBUG_VM */ |
diff --git a/mm/memblock.c b/mm/memblock.c index 237944479d25..a85315083b5a 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
| @@ -1444,10 +1444,9 @@ void * __init memblock_virt_alloc_try_nid_raw( | |||
| 1444 | 1444 | ||
| 1445 | ptr = memblock_virt_alloc_internal(size, align, | 1445 | ptr = memblock_virt_alloc_internal(size, align, |
| 1446 | min_addr, max_addr, nid); | 1446 | min_addr, max_addr, nid); |
| 1447 | #ifdef CONFIG_DEBUG_VM | ||
| 1448 | if (ptr && size > 0) | 1447 | if (ptr && size > 0) |
| 1449 | memset(ptr, PAGE_POISON_PATTERN, size); | 1448 | page_init_poison(ptr, size); |
| 1450 | #endif | 1449 | |
| 1451 | return ptr; | 1450 | return ptr; |
| 1452 | } | 1451 | } |
| 1453 | 1452 | ||
diff --git a/mm/sparse.c b/mm/sparse.c index 10b07eea9a6e..67ad061f7fb8 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
| @@ -696,13 +696,11 @@ int __meminit sparse_add_one_section(struct pglist_data *pgdat, | |||
| 696 | goto out; | 696 | goto out; |
| 697 | } | 697 | } |
| 698 | 698 | ||
| 699 | #ifdef CONFIG_DEBUG_VM | ||
| 700 | /* | 699 | /* |
| 701 | * Poison uninitialized struct pages in order to catch invalid flags | 700 | * Poison uninitialized struct pages in order to catch invalid flags |
| 702 | * combinations. | 701 | * combinations. |
| 703 | */ | 702 | */ |
| 704 | memset(memmap, PAGE_POISON_PATTERN, sizeof(struct page) * PAGES_PER_SECTION); | 703 | page_init_poison(memmap, sizeof(struct page) * PAGES_PER_SECTION); |
| 705 | #endif | ||
| 706 | 704 | ||
| 707 | section_mark_present(ms); | 705 | section_mark_present(ms); |
| 708 | sparse_init_one_section(ms, section_nr, memmap, usemap); | 706 | sparse_init_one_section(ms, section_nr, memmap, usemap); |
