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); |