]> xenbits.xensource.com Git - people/tklengyel/xen.git/commitdiff
x86: On CPU offline, fix master waiting for slave to be fully dead.
authorKeir Fraser <keir@xen.org>
Sat, 5 Mar 2011 11:34:41 +0000 (11:34 +0000)
committerKeir Fraser <keir@xen.org>
Sat, 5 Mar 2011 11:34:41 +0000 (11:34 +0000)
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/arch/x86/smpboot.c

index 2c8c47d164d193624dac41afcc258ecc446a3e11..7c14f062868c10b924b9033de6eeac3a8f0a8c80 100644 (file)
@@ -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();