# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1235992279 0
# Node ID 35baf43f271363c7b71d3fba44a469590841df3a
# Parent 5e34a89662515c21e686e8a7906d140b470bcb99
x86: Make offlined CPU enter deepest C state
Before cpuidle is introduced, offlined CPU only enter C1 (by HLT
instruction). This is not optimal since C2/C3 can bring more power
saving. Since now cpuidle is introduced, it is time for offlined CPU
to enter more deeper C state.
This patch add the logic to make offlined CPU enter deepest C state,
if cpuidle is enabled.
Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
---
xen/arch/x86/acpi/cpu_idle.c | 43 +++++++++++++++++++++++++++++++++++++++++++
xen/arch/x86/domain.c | 11 +++++++++--
2 files changed, 52 insertions(+), 2 deletions(-)
diff -r 5e34a8966251 -r 35baf43f2713 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c Mon Mar 02 11:04:43 2009 +0000
+++ b/xen/arch/x86/acpi/cpu_idle.c Mon Mar 02 11:11:19 2009 +0000
@@ -55,6 +55,7 @@ static void (*lapic_timer_on)(void);
extern u32 pmtmr_ioport;
extern void (*pm_idle) (void);
+extern void (*dead_idle) (void);
static void (*pm_idle_save) (void) __read_mostly;
unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER - 1;
@@ -369,6 +370,43 @@ static void acpi_processor_idle(void)
cpuidle_current_governor->reflect(power);
}
+static void acpi_dead_idle(void)
+{
+ struct acpi_processor_power *power;
+ struct acpi_processor_cx *cx;
+ int unused;
+
+ if ( (power = processor_powers[smp_processor_id()]) == NULL )
+ goto default_halt;
+
+ if ( (cx = &power->states[power->count-1]) == NULL )
+ goto default_halt;
+
+ for ( ; ; )
+ {
+ if ( !power->flags.bm_check && cx->type == ACPI_STATE_C3 )
+ ACPI_FLUSH_CPU_CACHE();
+
+ switch ( cx->entry_method )
+ {
+ case ACPI_CSTATE_EM_FFH:
+ /* Not treat interrupt as break event */
+ mwait_idle_with_hints(cx->address, 0);
+ break;
+ case ACPI_CSTATE_EM_SYSIO:
+ inb(cx->address);
+ unused = inl(pmtmr_ioport);
+ break;
+ default:
+ goto default_halt;
+ }
+ }
+
+default_halt:
+ for ( ; ; )
+ halt();
+}
+
static int init_cx_pminfo(struct acpi_processor_power *acpi_power)
{
int i;
@@ -740,6 +778,11 @@ long set_cx_pminfo(uint32_t cpu, struct
pm_idle_save = pm_idle;
pm_idle = acpi_processor_idle;
}
+
+ if ( cpu_id == 0 )
+ {
+ dead_idle = acpi_dead_idle;
+ }
return 0;
}
diff -r 5e34a8966251 -r 35baf43f2713 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Mon Mar 02 11:04:43 2009 +0000
+++ b/xen/arch/x86/domain.c Mon Mar 02 11:11:19 2009 +0000
@@ -58,7 +58,9 @@ DEFINE_PER_CPU(unsigned long, cr4);
DEFINE_PER_CPU(unsigned long, cr4);
static void default_idle(void);
+static void default_dead_idle(void);
void (*pm_idle) (void) = default_idle;
+void (*dead_idle) (void) = default_dead_idle;
static void paravirt_ctxt_switch_from(struct vcpu *v);
static void paravirt_ctxt_switch_to(struct vcpu *v);
@@ -82,6 +84,12 @@ static void default_idle(void)
safe_halt();
else
local_irq_enable();
+}
+
+static void default_dead_idle(void)
+{
+ for ( ; ; )
+ halt();
}
static void play_dead(void)
@@ -102,8 +110,7 @@ static void play_dead(void)
/* With physical CPU hotplug, we should halt the cpu. */
local_irq_disable();
- for ( ; ; )
- halt();
+ (*dead_idle)();
}
void idle_loop(void)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|