diff options
author | Takao Indoh <indou.takao@jp.fujitsu.com> | 2011-03-29 12:35:04 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-06-17 04:17:12 -0400 |
commit | d8ad7d1123a960cc9f276bd499f9325c6f5e1bd1 (patch) | |
tree | 0260df1b5b5b1601f56229c7dde54594d2dfebcb /include/linux/smp.h | |
parent | eb96c925152fc289311e5d7e956b919e9b60ab53 (diff) |
generic-ipi: Fix kexec boot crash by initializing call_single_queue before enabling interrupts
There is a problem that kdump(2nd kernel) sometimes hangs up due
to a pending IPI from 1st kernel. Kernel panic occurs because IPI
comes before call_single_queue is initialized.
To fix the crash, rename init_call_single_data() to call_function_init()
and call it in start_kernel() so that call_single_queue can be
initialized before enabling interrupts.
The details of the crash are:
(1) 2nd kernel boots up
(2) A pending IPI from 1st kernel comes when irqs are first enabled
in start_kernel().
(3) Kernel tries to handle the interrupt, but call_single_queue
is not initialized yet at this point. As a result, in the
generic_smp_call_function_single_interrupt(), NULL pointer
dereference occurs when list_replace_init() tries to access
&q->list.next.
Therefore this patch changes the name of init_call_single_data()
to call_function_init() and calls it before local_irq_enable()
in start_kernel().
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
Reviewed-by: WANG Cong <xiyou.wangcong@gmail.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Milton Miller <miltonm@bga.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: kexec@lists.infradead.org
Link: http://lkml.kernel.org/r/D6CBEE2F420741indou.takao@jp.fujitsu.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/smp.h')
-rw-r--r-- | include/linux/smp.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/smp.h b/include/linux/smp.h index 7ad824d510a2..8cc38d3bab0c 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
@@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask, | |||
85 | * Generic and arch helpers | 85 | * Generic and arch helpers |
86 | */ | 86 | */ |
87 | #ifdef CONFIG_USE_GENERIC_SMP_HELPERS | 87 | #ifdef CONFIG_USE_GENERIC_SMP_HELPERS |
88 | void __init call_function_init(void); | ||
88 | void generic_smp_call_function_single_interrupt(void); | 89 | void generic_smp_call_function_single_interrupt(void); |
89 | void generic_smp_call_function_interrupt(void); | 90 | void generic_smp_call_function_interrupt(void); |
90 | void ipi_call_lock(void); | 91 | void ipi_call_lock(void); |
91 | void ipi_call_unlock(void); | 92 | void ipi_call_unlock(void); |
92 | void ipi_call_lock_irq(void); | 93 | void ipi_call_lock_irq(void); |
93 | void ipi_call_unlock_irq(void); | 94 | void ipi_call_unlock_irq(void); |
95 | #else | ||
96 | static inline void call_function_init(void) { } | ||
94 | #endif | 97 | #endif |
95 | 98 | ||
96 | /* | 99 | /* |
@@ -134,7 +137,7 @@ static inline void smp_send_reschedule(int cpu) { } | |||
134 | #define smp_prepare_boot_cpu() do {} while (0) | 137 | #define smp_prepare_boot_cpu() do {} while (0) |
135 | #define smp_call_function_many(mask, func, info, wait) \ | 138 | #define smp_call_function_many(mask, func, info, wait) \ |
136 | (up_smp_call_function(func, info)) | 139 | (up_smp_call_function(func, info)) |
137 | static inline void init_call_single_data(void) { } | 140 | static inline void call_function_init(void) { } |
138 | 141 | ||
139 | static inline int | 142 | static inline int |
140 | smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, | 143 | smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, |