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>
Wei Gang <gang.wei@xxxxxxxxx>
Tian Kevin <kevin.tian@xxxxxxxxx>
diff -r ad6925fc2317 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -60,6 +60,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;
@@ -372,6 +373,43 @@ static void acpi_processor_idle(void)
if ( cpuidle_current_governor->reflect )
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)
@@ -745,6 +783,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 ad6925fc2317 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -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);
@@ -84,6 +86,12 @@ static void default_idle(void)
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)
offline-deep-c-v2.patch
Description: offline-deep-c-v2.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|