Secondary CPUs, between doing their final memory writes (particularly
updating cpu_initialized) and getting a subsequent INIT, may not write
back all modified data. The INIT itself then causes those modifications
to be lost, so in the cpu_initialized case the CPU would find itself
already initialized, (intentionally) entering an infinite loop instead
of actually coming online.
Signed-off-by: Ben Guthro <ben@guthro.net>
Make acpi_dead_idle() call default_dead_idle() rather than duplicating
the logic there.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Committed-by: Jan Beulich <jbeulich@suse.com>
}
default_halt:
- for ( ; ; )
- halt();
+ default_dead_idle();
}
int cpuidle_init_cpu(unsigned int cpu)
#include <asm/desc.h>
#include <asm/i387.h>
#include <asm/xstate.h>
+#include <asm/cpuidle.h>
#include <asm/mpspec.h>
#include <asm/ldt.h>
#include <asm/fixmap.h>
DEFINE_PER_CPU(unsigned long, cr4);
static void default_idle(void);
-static void default_dead_idle(void);
void (*pm_idle) (void) __read_mostly = default_idle;
void (*dead_idle) (void) __read_mostly = default_dead_idle;
local_irq_enable();
}
-static void default_dead_idle(void)
+void default_dead_idle(void)
{
+ /*
+ * When going into S3, without flushing caches modified data may be
+ * held by the CPUs spinning here indefinitely, and get discarded by
+ * a subsequent INIT.
+ */
+ wbinvd();
for ( ; ; )
halt();
}
int mwait_idle_init(struct notifier_block *);
int cpuidle_init_cpu(unsigned int cpu);
+void default_dead_idle(void);
void acpi_dead_idle(void);
void trace_exit_reason(u32 *irq_traced);
void update_idle_stats(struct acpi_processor_power *,