[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Merge



# HG changeset patch
# User Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
# Date 1299867677 0
# Node ID 93c63adf348622a1d94e6dba4666a1e3d1efc9d4
# Parent  9070fc88309b5712d658ee19431f2df7647b8553
# Parent  929195d87ca65aae3382065e00268ffcda4261eb
Merge
---


diff -r 9070fc88309b -r 93c63adf3486 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Fri Mar 11 18:20:53 2011 +0000
+++ b/xen/arch/x86/acpi/cpu_idle.c      Fri Mar 11 18:21:17 2011 +0000
@@ -457,6 +457,19 @@
 
     case ACPI_STATE_C3:
         /*
+         * Before invoking C3, be aware that TSC/APIC timer may be 
+         * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
+         * deep C state can't work correctly.
+         */
+        /* preparing APIC stop */
+        lapic_timer_off();
+
+        /* Get start time (ticks) */
+        t1 = get_tick();
+        /* Trace cpu idle entry */
+        TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred);
+
+        /*
          * disable bus master
          * bm_check implies we need ARB_DIS
          * !bm_check implies we need cache flush
@@ -485,20 +498,18 @@
             ACPI_FLUSH_CPU_CACHE();
         }
 
-        /*
-         * Before invoking C3, be aware that TSC/APIC timer may be 
-         * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
-         * deep C state can't work correctly.
-         */
-        /* preparing APIC stop */
-        lapic_timer_off();
-
-        /* Get start time (ticks) */
-        t1 = get_tick();
-        /* Trace cpu idle entry */
-        TRACE_4D(TRC_PM_IDLE_ENTRY, cx->idx, t1, exp, pred);
         /* Invoke C3 */
         acpi_idle_do_entry(cx);
+
+        if ( power->flags.bm_check && power->flags.bm_control )
+        {
+            /* Enable bus master arbitration */
+            spin_lock(&c3_cpu_status.lock);
+            acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
+            c3_cpu_status.count--;
+            spin_unlock(&c3_cpu_status.lock);
+        }
+
         /* Get end time (ticks) */
         t2 = get_tick();
 
@@ -509,15 +520,6 @@
         TRACE_6D(TRC_PM_IDLE_EXIT, cx->idx, t2,
                  irq_traced[0], irq_traced[1], irq_traced[2], irq_traced[3]);
 
-        if ( power->flags.bm_check && power->flags.bm_control )
-        {
-            /* Enable bus master arbitration */
-            spin_lock(&c3_cpu_status.lock);
-            if ( c3_cpu_status.count-- == num_online_cpus() )
-                acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
-            spin_unlock(&c3_cpu_status.lock);
-        }
-
         /* Re-enable interrupts */
         local_irq_enable();
         /* recovering APIC */
@@ -552,7 +554,7 @@
 {
     struct acpi_processor_power *power;
     struct acpi_processor_cx *cx;
-    int unused;
+    void *mwait_ptr;
 
     if ( (power = processor_powers[smp_processor_id()]) == NULL )
         goto default_halt;
@@ -560,24 +562,33 @@
     if ( (cx = &power->states[power->count-1]) == NULL )
         goto default_halt;
 
-    for ( ; ; )
+    mwait_ptr = (void *)&mwait_wakeup(smp_processor_id());
+
+    if ( cx->entry_method == ACPI_CSTATE_EM_FFH )
     {
-        if ( !power->flags.bm_check && cx->type == ACPI_STATE_C3 )
-            ACPI_FLUSH_CPU_CACHE();
+        /*
+         * Cache must be flushed as the last operation before sleeping.
+         * Otherwise, CPU may still hold dirty data, breaking cache coherency,
+         * leading to strange errors.
+         */
+        wbinvd();
 
-        switch ( cx->entry_method )
+        while ( 1 )
         {
-            case ACPI_CSTATE_EM_FFH:
-                /* Not treat interrupt as break event */
-                __monitor((void *)&mwait_wakeup(smp_processor_id()), 0, 0);
-                __mwait(cx->address, 0);
-                break;
-            case ACPI_CSTATE_EM_SYSIO:
-                inb(cx->address);
-                unused = inl(pmtmr_ioport);
-                break;
-            default:
-                goto default_halt;
+            /*
+             * 1. The CLFLUSH is a workaround for erratum AAI65 for
+             * the Xeon 7400 series.  
+             * 2. The WBINVD is insufficient due to the spurious-wakeup
+             * case where we return around the loop.
+             * 3. Unlike wbinvd, clflush is a light weight but not serializing 
+             * instruction, hence memory fence is necessary to make sure all 
+             * load/store visible before flush cache line.
+             */
+            mb();
+            clflush(mwait_ptr);
+            __monitor(mwait_ptr, 0, 0);
+            mb();
+            __mwait(cx->address, 0);
         }
     }
 
diff -r 9070fc88309b -r 93c63adf3486 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Mar 11 18:20:53 2011 +0000
+++ b/xen/arch/x86/domain.c     Fri Mar 11 18:21:17 2011 +0000
@@ -100,7 +100,6 @@
 static void play_dead(void)
 {
     local_irq_disable();
-    wbinvd();
 
     /*
      * NOTE: After cpu_exit_clear, per-cpu variables are no longer accessible,

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.