aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/smpboot.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-03-05 11:34:41 +0000
committerKeir Fraser <keir@xen.org>2011-03-05 11:34:41 +0000
commit87fe7478aa597f8b9b744d19e3b79a64f3d9cf15 (patch)
treeb64e357f503d652046af9a4b9ab5a89c525e2dd9 /xen/arch/x86/smpboot.c
parentfaf7c3e08d731ec310dbcc96adf249812d45d27a (diff)
downloadxen-87fe7478aa597f8b9b744d19e3b79a64f3d9cf15.tar.gz
xen-87fe7478aa597f8b9b744d19e3b79a64f3d9cf15.tar.bz2
xen-87fe7478aa597f8b9b744d19e3b79a64f3d9cf15.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>
Diffstat (limited to 'xen/arch/x86/smpboot.c')
-rw-r--r--xen/arch/x86/smpboot.c6
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();