aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/domain.c
diff options
context:
space:
mode:
authorBen Guthro <ben@guthro.net>2012-09-25 08:38:14 +0200
committerBen Guthro <ben@guthro.net>2012-09-25 08:38:14 +0200
commitca71bdf62e7e96579415fce6b562f3a956d94cc9 (patch)
treee8f461d93e466a4d4935b14373642c4fb278ded2 /xen/arch/x86/domain.c
parent797b603c7e32459c782ec2738fa6a30b4fbbcb83 (diff)
downloadxen-ca71bdf62e7e96579415fce6b562f3a956d94cc9.tar.gz
xen-ca71bdf62e7e96579415fce6b562f3a956d94cc9.tar.bz2
xen-ca71bdf62e7e96579415fce6b562f3a956d94cc9.zip
x86/S3: add cache flush on secondary CPUs before going to sleep
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>
Diffstat (limited to 'xen/arch/x86/domain.c')
-rw-r--r--xen/arch/x86/domain.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 9f9bfd3af7..ec0d06f79f 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -45,6 +45,7 @@
#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>
@@ -64,7 +65,6 @@ DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
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;
@@ -82,8 +82,14 @@ static void default_idle(void)
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();
}