summaryrefslogtreecommitdiff
path: root/kernel/smp.c
diff options
context:
space:
mode:
authorTakao Indoh <indou.takao@jp.fujitsu.com>2011-03-29 12:35:04 -0400
committerIngo Molnar <mingo@elte.hu>2011-06-17 10:17:12 +0200
commitd8ad7d1123a960cc9f276bd499f9325c6f5e1bd1 (patch)
tree0260df1b5b5b1601f56229c7dde54594d2dfebcb /kernel/smp.c
parenteb96c925152fc289311e5d7e956b919e9b60ab53 (diff)
downloadlwn-d8ad7d1123a960cc9f276bd499f9325c6f5e1bd1.tar.gz
lwn-d8ad7d1123a960cc9f276bd499f9325c6f5e1bd1.zip
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 'kernel/smp.c')
-rw-r--r--kernel/smp.c5
1 files changed, 1 insertions, 4 deletions
diff --git a/kernel/smp.c b/kernel/smp.c
index 73a195193558..fb67dfa8394e 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
.notifier_call = hotplug_cfd,
};
-static int __cpuinit init_call_single_data(void)
+void __init call_function_init(void)
{
void *cpu = (void *)(long)smp_processor_id();
int i;
@@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void)
hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
register_cpu_notifier(&hotplug_cfd_notifier);
-
- return 0;
}
-early_initcall(init_call_single_data);
/*
* csd_lock/csd_unlock used to serialize access to per-cpu csd resources