diff options
author | Ben Guthro <ben@guthro.net> | 2012-09-25 08:38:14 +0200 |
---|---|---|
committer | Ben Guthro <ben@guthro.net> | 2012-09-25 08:38:14 +0200 |
commit | ca71bdf62e7e96579415fce6b562f3a956d94cc9 (patch) | |
tree | e8f461d93e466a4d4935b14373642c4fb278ded2 /xen/arch/x86/domain.c | |
parent | 797b603c7e32459c782ec2738fa6a30b4fbbcb83 (diff) | |
download | xen-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.c | 10 |
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(); } |