Jan Beulich
2012-Sep-24 15:17 UTC
[PATCH] 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>
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -659,8 +659,7 @@ void acpi_dead_idle(void)
}
default_halt:
- for ( ; ; )
- halt();
+ default_dead_idle();
}
int cpuidle_init_cpu(unsigned int cpu)
--- 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,9 @@ static void default_idle(void)
local_irq_enable();
}
-static void default_dead_idle(void)
+void default_dead_idle(void)
{
+ wbinvd();
for ( ; ; )
halt();
}
--- a/xen/include/asm-x86/cpuidle.h
+++ b/xen/include/asm-x86/cpuidle.h
@@ -18,6 +18,7 @@ extern uint64_t (*cpuidle_get_tick)(void
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 *,
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
Keir Fraser
2012-Sep-24 16:35 UTC
Re: [PATCH] x86/S3: add cache flush on secondary CPUs before going to sleep
On 24/09/2012 16:17, "Jan Beulich" <JBeulich@suse.com> wrote:> 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>Add a comment in default_dead_idle() that the wbinvd is needed in case the cpu is offline for s3 suspend. That may not otherwise be obvious! And it''s a different reason -- or at least there are other reasons why -- wbinvd is needed in acpi_dead_idle(). Apart from that: Acked-by: Keir Fraser <keir@xen.org>> --- a/xen/arch/x86/acpi/cpu_idle.c > +++ b/xen/arch/x86/acpi/cpu_idle.c > @@ -659,8 +659,7 @@ void acpi_dead_idle(void) > } > > default_halt: > - for ( ; ; ) > - halt(); > + default_dead_idle(); > } > > int cpuidle_init_cpu(unsigned int cpu) > --- 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,9 @@ static void default_idle(void) > local_irq_enable(); > } > > -static void default_dead_idle(void) > +void default_dead_idle(void) > { > + wbinvd(); > for ( ; ; ) > halt(); > } > --- a/xen/include/asm-x86/cpuidle.h > +++ b/xen/include/asm-x86/cpuidle.h > @@ -18,6 +18,7 @@ extern uint64_t (*cpuidle_get_tick)(void > > 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 *, > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel