diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c0538f82c9a220cfafbb20d7d954eff6eff5053e..57ef2094af93ede71e6ad6283fd699160d21de5d 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -132,6 +132,7 @@ void native_play_dead(void); void play_dead_common(void); void wbinvd_on_cpu(int cpu); int wbinvd_on_all_cpus(void); +bool wakeup_cpu0(void); void native_smp_send_reschedule(int cpu); void native_send_call_func_ipi(const struct cpumask *mask); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c65642c10aaea0f7fb97e22885cda315b0fe791a..5ea5f964f0a974c809ea17ea85cfd7c25cdab5aa 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1655,7 +1655,7 @@ void play_dead_common(void) local_irq_disable(); } -static bool wakeup_cpu0(void) +bool wakeup_cpu0(void) { if (smp_processor_id() == 0 && enable_start_cpu0) return true; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f66236cff69b02ee6a8e3ac8014c35e49571a8a6..4e303964f7e7f5034a2a3d941885a5a8fd338b18 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -29,6 +29,7 @@ */ #ifdef CONFIG_X86 #include <asm/apic.h> +#include <asm/cpu.h> #endif #define ACPI_PROCESSOR_CLASS "processor" @@ -542,6 +543,12 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) wait_for_freeze(); } else return -ENODEV; + +#if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU) + /* If NMI wants to wake up CPU0, start CPU0. */ + if (wakeup_cpu0()) + start_cpu0(); +#endif } /* Never reached */