diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-03-17 00:20:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-18 04:40:35 -0400 |
commit | 30e1e6d1af2b67558bccf322af2b3e0676b209ae (patch) | |
tree | dae658631d0bb038c373cc2ba34ecf43f31ebd25 /arch | |
parent | 082edb7bf443eb8eda15b482d16ad9dd8137ad24 (diff) |
cpumask: fix CONFIG_CPUMASK_OFFSTACK=y cpu hotunplug crash
Impact: Fix cpu offline when CONFIG_MAXSMP=y
Changeset bc9b83dd1f66402b870301c3c7117b9c1484abb4 "cpumask: convert
c1e_mask in arch/x86/kernel/process.c to cpumask_var_t" contained a
bug: c1e_mask is manipulated even if C1E isn't detected (and hence
not allocated).
This is simply fixed by checking for NULL (which gcc optimizes out
anyway of CONFIG_CPUMASK_OFFSTACK=n, since it knows ce1_mask can never
be NULL).
In addition, fix a leak where select_idle_routine re-allocates
(and re-clears) c1e_mask on every cpu init.
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mike Travis <travis@sgi.com>
LKML-Reference: <200903171450.34549.rusty@rustcorp.com.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 14 |
3 files changed, 13 insertions, 3 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index d794d9483c56..9874dd98a29f 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -733,6 +733,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx) | |||
733 | extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); | 733 | extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); |
734 | 734 | ||
735 | extern void select_idle_routine(const struct cpuinfo_x86 *c); | 735 | extern void select_idle_routine(const struct cpuinfo_x86 *c); |
736 | extern void init_c1e_mask(void); | ||
736 | 737 | ||
737 | extern unsigned long boot_option_idle_override; | 738 | extern unsigned long boot_option_idle_override; |
738 | extern unsigned long idle_halt; | 739 | extern unsigned long idle_halt; |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 82f6cc045ad0..d7dd3c294e2a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -812,6 +812,7 @@ static void vgetcpu_set_mode(void) | |||
812 | void __init identify_boot_cpu(void) | 812 | void __init identify_boot_cpu(void) |
813 | { | 813 | { |
814 | identify_cpu(&boot_cpu_data); | 814 | identify_cpu(&boot_cpu_data); |
815 | init_c1e_mask(); | ||
815 | #ifdef CONFIG_X86_32 | 816 | #ifdef CONFIG_X86_32 |
816 | sysenter_setup(); | 817 | sysenter_setup(); |
817 | enable_sep_cpu(); | 818 | enable_sep_cpu(); |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 6638294cec8d..78533a519d8f 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -479,7 +479,8 @@ static int c1e_detected; | |||
479 | 479 | ||
480 | void c1e_remove_cpu(int cpu) | 480 | void c1e_remove_cpu(int cpu) |
481 | { | 481 | { |
482 | cpumask_clear_cpu(cpu, c1e_mask); | 482 | if (c1e_mask != NULL) |
483 | cpumask_clear_cpu(cpu, c1e_mask); | ||
483 | } | 484 | } |
484 | 485 | ||
485 | /* | 486 | /* |
@@ -556,13 +557,20 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | |||
556 | pm_idle = mwait_idle; | 557 | pm_idle = mwait_idle; |
557 | } else if (check_c1e_idle(c)) { | 558 | } else if (check_c1e_idle(c)) { |
558 | printk(KERN_INFO "using C1E aware idle routine\n"); | 559 | printk(KERN_INFO "using C1E aware idle routine\n"); |
559 | alloc_cpumask_var(&c1e_mask, GFP_KERNEL); | ||
560 | cpumask_clear(c1e_mask); | ||
561 | pm_idle = c1e_idle; | 560 | pm_idle = c1e_idle; |
562 | } else | 561 | } else |
563 | pm_idle = default_idle; | 562 | pm_idle = default_idle; |
564 | } | 563 | } |
565 | 564 | ||
565 | void __init init_c1e_mask(void) | ||
566 | { | ||
567 | /* If we're using c1e_idle, we need to allocate c1e_mask. */ | ||
568 | if (pm_idle == c1e_idle) { | ||
569 | alloc_cpumask_var(&c1e_mask, GFP_KERNEL); | ||
570 | cpumask_clear(c1e_mask); | ||
571 | } | ||
572 | } | ||
573 | |||
566 | static int __init idle_setup(char *str) | 574 | static int __init idle_setup(char *str) |
567 | { | 575 | { |
568 | if (!str) | 576 | if (!str) |