x86: Fix cache flush bug of cpu offline
authorLiu, Jinsong <jinsong.liu@intel.com>
Fri, 11 Mar 2011 17:18:01 +0000 (17:18 +0000)
committerLiu, Jinsong <jinsong.liu@intel.com>
Fri, 11 Mar 2011 17:18:01 +0000 (17:18 +0000)
Current xen cpu offline logic flush cache too early, which potentially
break cache coherency.  wbinvd should be the last ops before cpu going
into dead, otherwise cache may be dirty, i.e, something like setting
an A bit on page tables. Pointed out by Arjan van de Ven.

Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
xen/arch/x86/acpi/cpu_idle.c
xen/arch/x86/domain.c

index a01a27f4add8907cb8b6750a648b478d375d79d8..6fa94cab6225f8e75a8cc464daa3b9f54afd4f9d 100644 (file)
@@ -561,11 +561,14 @@ static void acpi_dead_idle(void)
     if ( (cx = &power->states[power->count-1]) == NULL )
         goto default_halt;
 
+    /*
+     * cache must be flashed as the last ops before cpu going into dead,
+     * otherwise, cpu may dead with dirty data breaking cache coherency,
+     * leading to strange errors.
+     */
+    wbinvd();
     for ( ; ; )
     {
-        if ( !power->flags.bm_check && cx->type == ACPI_STATE_C3 )
-            ACPI_FLUSH_CPU_CACHE();
-
         switch ( cx->entry_method )
         {
             case ACPI_CSTATE_EM_FFH:
@@ -579,6 +582,7 @@ static void acpi_dead_idle(void)
     }
 
 default_halt:
+    wbinvd();
     for ( ; ; )
         halt();
 }
index 09da6221af6210e330c25976bfd170af7a885267..a024e198e90b4bacdf1ee975c0becbb8ee2aaf37 100644 (file)
@@ -93,6 +93,12 @@ static void default_idle(void)
 
 static void default_dead_idle(void)
 {
+    /*
+     * cache must be flashed as the last ops before cpu going into dead,
+     * otherwise, cpu may dead with dirty data breaking cache coherency,
+     * leading to strange errors.
+     */
+    wbinvd();
     for ( ; ; )
         halt();
 }
@@ -100,7 +106,6 @@ static void default_dead_idle(void)
 static void play_dead(void)
 {
     local_irq_disable();
-    wbinvd();
 
     /*
      * NOTE: After cpu_exit_clear, per-cpu variables are no longer accessible,