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@intel.com> Wei Gang <gang.wei@intel.com> Tian Kevin <kevin.tian@intel.com> 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) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel