diff options
author | Keir Fraser <keir@xen.org> | 2011-03-05 11:37:42 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2011-03-05 11:37:42 +0000 |
commit | 1cb39d117f79892e49eb4992f6f1c4c190379b31 (patch) | |
tree | f5befd1be7e1f1a78651d269c58c7a6c46e40cca | |
parent | d4be35f81ea395a9cc13a2e55a15d0d7596c9b1d (diff) | |
download | xen-1cb39d117f79892e49eb4992f6f1c4c190379b31.tar.gz xen-1cb39d117f79892e49eb4992f6f1c4c190379b31.tar.bz2 xen-1cb39d117f79892e49eb4992f6f1c4c190379b31.zip |
x86: On CPU offline, fix master waiting for slave to be fully dead.
On two back-to-back CPU offline operations, on second offline the
cpu_state var will be CPU_STATE_DEAD from the first offline. Hence
__cpu_die() will incorrectly not wait for the second slave to fully
die and set cpu_state itself.
The fix is to set cpu_state to a new value, CPU_STATE_DYING, earlier
during CPU offline, before __cpu_die() starts to execute.
Original diagnosis and patch by Liu, Jinsong <jinsong.liu@intel.com>
Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 22975:d3d29df8f082
xen-unstable date: Sat Mar 05 11:34:41 2011 +0000
-rw-r--r-- | xen/arch/x86/smpboot.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 2c8c47d164..7c14f06286 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -74,7 +74,8 @@ static void map_cpu_to_logical_apicid(void); static int cpu_error; static enum cpu_state { - CPU_STATE_DEAD = 0, /* slave -> master: I am completely dead */ + CPU_STATE_DYING, /* slave -> master: I am dying */ + CPU_STATE_DEAD, /* slave -> master: I am completely dead */ CPU_STATE_INIT, /* master -> slave: Early bringup phase 1 */ CPU_STATE_CALLOUT, /* master -> slave: Early bringup phase 2 */ CPU_STATE_CALLIN, /* slave -> master: Completed phase 2 */ @@ -834,6 +835,8 @@ void __cpu_disable(void) extern void fixup_irqs(void); int cpu = smp_processor_id(); + set_cpu_state(CPU_STATE_DYING); + local_irq_disable(); clear_local_APIC(); /* Allow any queued timer interrupts to get serviced */ @@ -861,6 +864,7 @@ void __cpu_die(unsigned int cpu) while ( cpu_state != CPU_STATE_DEAD ) { + BUG_ON(cpu_state != CPU_STATE_DYING); mdelay(100); cpu_relax(); process_pending_softirqs(); |