# 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
|