mm: add a new command-line kmemcheck value
Subsystems (4)
PATCH v2 1/1 mm: add a new command-line kmemcheck value
If we want to debug the kernel memory, we should turn on CONFIG_KMEMCHECK and rebuild the kernel. This always takes a long time and sometimes impossible, e.g. users don't have the kernel source code or the code is different from "www.kernel.org" (private features may be added to the kernel, and usually users can not get the whole code).
This patch adds a new command-line "kmemcheck=3", then the kernel will run as the same as CONFIG_KMEMCHECK=off even CONFIG_KMEMCHECK is turn on. "kmemcheck=0/1/2" is the same as originally. This means we can always turn on CONFIG_KMEMCHECK, and use "kmemcheck=3" to control it on/off with out rebuild the kernel.
In another word, "kmemcheck=3" is equivalent:
1) turn off CONFIG_KMEMCHECK
2) rebuild the kernel
3) reboot
The different between kmemcheck=0 and 3 is the used memory and nr_cpus. Also kmemcheck=0 can used in runtime, and kmemcheck=3 is only used in boot.
boottime: kmemcheck=0/1/2/3 (command-line)
runtime: kmemcheck=0/1/2 (/proc/sys/kernel/kmemcheck)
--- arch/x86/mm/init.c | 11 ++++++ arch/x86/mm/kmemcheck/kmemcheck.c | 62 ++++++++++++++++++++++++++----------- arch/x86/mm/kmemcheck/shadow.c | 13 +++++--- include/linux/kmemcheck.h | 2 + mm/kmemcheck.c | 12 +++++-- mm/page_alloc.c | 2 + 6 files changed, 76 insertions(+), 26 deletions(-)
arch/x86/mm/init.c +11 -0
@@ -135,6 +135,15 @@ static void __init probe_page_size_mask(void) page_size_mask |=1 <<PG_LEVEL_2M ;#endif +#if defined(CONFIG_KMEMCHECK ) +if (!kmemcheck_on) { +if (direct_gbpages) + page_size_mask |=1 <<PG_LEVEL_1G ; +if (cpu_has_pse) + page_size_mask |=1 <<PG_LEVEL_2M ; + } +#endif +/* Enable PSE if available */ if (cpu_has_pse)set_in_cr4 (X86_CR4_PSE );
@@ -331,6 +340,8 @@ bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)return false; } +extern int kmemcheck_on; +/* * Setup the direct mapping of the physical memory at PAGE_OFFSET. * This runs before bootmem is initialized and gets pages directly from
arch/x86/mm/kmemcheck/kmemcheck.c +44 -18
120 lines not on this page · raw message
arch/x86/mm/kmemcheck/shadow.c +8 -5
@@ -90,7 +90,8 @@ void kmemcheck_mark_uninitialized(void *address, unsigned int n)*/ void kmemcheck_mark_initialized (void *address,unsigned int n) { -mark_shadow (address, n,KMEMCHECK_SHADOW_INITIALIZED ); +if (kmemcheck_on) +mark_shadow (address, n,KMEMCHECK_SHADOW_INITIALIZED ); }EXPORT_SYMBOL_GPL (kmemcheck_mark_initialized);
@@ -103,16 +104,18 @@ void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n) {unsigned int i; -for (i =0 ; i < n; ++i) -kmemcheck_mark_unallocated (page_address (&p[i]),PAGE_SIZE ); +if (kmemcheck_on) +for (i =0 ; i < n; ++i) +kmemcheck_mark_unallocated (page_address (&p[i]),PAGE_SIZE ); }void kmemcheck_mark_uninitialized_pages (struct page *p,unsigned int n) {unsigned int i; -for (i =0 ; i < n; ++i) -kmemcheck_mark_uninitialized (page_address (&p[i]),PAGE_SIZE ); +if (kmemcheck_on) +for (i =0 ; i < n; ++i) +kmemcheck_mark_uninitialized (page_address (&p[i]),PAGE_SIZE ); }void kmemcheck_mark_initialized_pages (struct page *p,unsigned int n)
include/linux/kmemcheck.h +2 -0
@@ -6,6 +6,7 @@#ifdef CONFIG_KMEMCHECK extern int kmemcheck_enabled; +extern int kmemcheck_on;/* The slab-related functions. */ void kmemcheck_alloc_shadow (struct page *page,int order,gfp_t flags,int node);
@@ -88,6 +89,7 @@ bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);#else #define kmemcheck_enabled 0 +#define kmemcheck_on 0static inline void kmemcheck_alloc_shadow (struct page *page,int order,gfp_t flags,int node)
mm/kmemcheck.c +9 -3
@@ -10,6 +10,9 @@ void kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node)int pages;int i; +if (!kmemcheck_on) +return ; + pages =1 << order;/*
@@ -41,6 +44,9 @@ void kmemcheck_free_shadow(struct page *page, int order)int pages;int i; +if (!kmemcheck_on) +return ; +if (!kmemcheck_page_is_tracked (page))return ;
@@ -63,7 +69,7 @@ void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,* Has already been memset(), which initializes the shadow for us * as well. */ -if (gfpflags & __GFP_ZERO) +if (!kmemcheck_on || gfpflags & __GFP_ZERO)return ;/* No need to initialize the shadow of a non-tracked slab. */
@@ -92,7 +98,7 @@ void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,void kmemcheck_slab_free (struct kmem_cache *s,void *object,size_t size) {/* TODO: RCU freeing is unsupported for now; hide false positives. */ -if (!s->ctor && !(s->flags &SLAB_DESTROY_BY_RCU )) +if (kmemcheck_on && !s->ctor && !(s->flags &SLAB_DESTROY_BY_RCU ))kmemcheck_mark_freed (object, size); }
@@ -101,7 +107,7 @@ void kmemcheck_pagealloc_alloc(struct page *page, unsigned int order, {int pages; -if (gfpflags & (__GFP_HIGHMEM | __GFP_NOTRACK)) +if (!kmemcheck_on || (gfpflags & (__GFP_HIGHMEM | __GFP_NOTRACK)))return ; pages =1 << order;
mm/page_alloc.c +2 -0
@@ -2716,6 +2716,8 @@ retry_cpuset: page =get_page_from_freelist (gfp_mask|__GFP_HARDWALL, nodemask, order, zonelist, high_zoneidx, alloc_flags, preferred_zone, migratetype); +if (kmemcheck_on && kmemcheck_enabled && page) +kmemcheck_pagealloc_alloc (page, order, gfp_mask);if (unlikely (!page)) {/* * Runtime PM, block IO and its error handling path
Signature · 1 line
1.7.1
Quoted 17 lines · Xishi Qiu
If we want to debug the kernel memory, we should turn on
CONFIG_KMEMCHECKand rebuild the kernel. This always takes a long time and sometimes impossible, e.g. users don't have the kernel source code or the code is different from "www.kernel.org" (private features may be added to the kernel, and usually users can not get the whole code).This patch adds a new command-line "kmemcheck=3", then the kernel will run as the same as
CONFIG_KMEMCHECK=offevenCONFIG_KMEMCHECKis turn on. "kmemcheck=0/1/2" is the same as originally. This means we can always turn onCONFIG_KMEMCHECK, and use "kmemcheck=3" to control it on/off with out rebuild the kernel.In another word, "kmemcheck=3" is equivalent:
1) turn offCONFIG_KMEMCHECK
2) rebuild the kernel
3) reboot
Quoted 4 lines
The different between kmemcheck=0 and 3 is the used memory and
nr_cpus. Also kmemcheck=0 can used in runtime, and kmemcheck=3 is only used in boot.
boottime: kmemcheck=0/1/2/3 (command-line)
runtime: kmemcheck=0/1/2 (/proc/sys/kernel/kmemcheck)
This is not the right way to do what you want.
The behaviour that we want is:
- CONFIG_KMEMCHECK=y + kmemcheck=0 (boot parameter) should have a
minimal runtime impact and not limit the number of CPUs
- CONFIG_KMEMCHECK=y + kmemcheck=1 should limit the number of CPUs during boot
- setting kmemcheck to 1 via /proc/sys/kernel/kmemcheck should
probably return an error if more than 1 CPU is online
Vegard
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 27 lines · Vegard Nossum
Quoted 17 lines · Xishi Qiu
If we want to debug the kernel memory, we should turn on
CONFIG_KMEMCHECKand rebuild the kernel. This always takes a long time and sometimes impossible, e.g. users don't have the kernel source code or the code is different from "www.kernel.org" (private features may be added to the kernel, and usually users can not get the whole code).This patch adds a new command-line "kmemcheck=3", then the kernel will run as the same as
CONFIG_KMEMCHECK=offevenCONFIG_KMEMCHECKis turn on. "kmemcheck=0/1/2" is the same as originally. This means we can always turn onCONFIG_KMEMCHECK, and use "kmemcheck=3" to control it on/off with out rebuild the kernel.In another word, "kmemcheck=3" is equivalent:
1) turn offCONFIG_KMEMCHECK
2) rebuild the kernel
3) rebootQuoted 4 lines
The different between kmemcheck=0 and 3 is the used memory and
nr_cpus. Also kmemcheck=0 can used in runtime, and kmemcheck=3 is only used in boot.
boottime: kmemcheck=0/1/2/3 (command-line)
runtime: kmemcheck=0/1/2 (/proc/sys/kernel/kmemcheck)This is not the right way to do what you want.
The behaviour that we want is:
Quoted 9 lines
-
CONFIG_KMEMCHECK=y+ kmemcheck=0 (boot parameter) should have a
minimal runtime impact and not limit the number of CPUs
-CONFIG_KMEMCHECK=y+ kmemcheck=1 should limit the number of CPUs during boot
- setting kmemcheck to 1 via/proc/sys/kernel/kmemcheckshould
probably return an error if more than 1 CPU is onlineVegard
Hi Vegard,
Thank you for your reply. If we only use "kmemcheck=0" to control, how about the used memory? Will it use about twice as much memory as normal?
Thanks,
Xishi Qiu
Quoted 2 lines
.
Quoted 6 lines · Xishi Qiu
arch/x86/mm/init.c +0
-0@@ -135,6 +135,15 @@ static void __init probe_page_size_mask(void) page_size_mask |=1 <<PG_LEVEL_2M ;
arch/x86/mm/init.c static void __init probe_page_size_mask(void) · line 145
Quoted 10 lines
arch/x86/mm/init.c +8
-0#endif +#if defined(CONFIG_KMEMCHECK ) +if (!kmemcheck_on) { +if (direct_gbpages) + page_size_mask |=1 <<PG_LEVEL_1G ; +if (cpu_has_pse) + page_size_mask |=1 <<PG_LEVEL_2M ; + } +#endif
This is a copy-n-paste from just above which is inside a:
#if !defined(CONFIG_DEBUG_PAGEALLOC) && !defined(CONFIG_KMEMCHECK)
This gets really confusing to figure out which one of these options will rule. Maybe it's just time to add a kmemcheck_active() function which gets #ifdef'd to 0 if the config option is off.
arch/x86/mm/init.c bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn) · line 343
Quoted 8 lines
arch/x86/mm/init.c +1
-0/* Enable PSE if available */ if (cpu_has_pse)set_in_cr4 (X86_CR4_PSE );@@ -331,6 +340,8 @@ bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)return false; } +extern int kmemcheck_on;
Didn't you _just_ reference this? Either it's unnecessary, or this code doesn't compile.
Quoted 8 lines
arch/x86/mm/init.c +0
-0/* * Setup the direct mapping of the physical memory at PAGE_OFFSET. * This runs before bootmem is initialized and gets pages directly from arch/x86/mm/kmemcheck/kmemcheck.c +0
-0
arch/x86/mm/kmemcheck/kmemcheck.c line 50
Quoted 8 lines
arch/x86/mm/kmemcheck/kmemcheck.c +3
-1@@ -44,30 +44,35 @@#ifdef CONFIG_KMEMCHECK_ONESHOT_BY_DEFAULT # define KMEMCHECK_ENABLED 2#endif +#define KMEMCHECK_CLOSED 3 -int kmemcheck_enabled =KMEMCHECK_ENABLED ; +int kmemcheck_enabled =KMEMCHECK_CLOSED ; +int kmemcheck_on =0 ;
This is pretty confusing. If I see "kmemcheck_on" and "kmemcheck_enabled" in the code, it's hard to figure out which one to trust and infer what they were _supposed_ to be doing.
Please add some documentation for these, at least. The commit message isn't enough.
I'd also suggest breaking this up in to at least two pieces: one which adds the functions to check at runtime if we want to use kmemcheck, and then a second one to actually add this tunable.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>