ia64/xen-unstable

changeset 19258:35baf43f2713

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@intel.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
Signed-off-by: Tian Kevin <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Mar 02 11:11:19 2009 +0000 (2009-03-02)
parents 5e34a8966251
children 507b264f0a21
files xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/domain.c
line diff
     1.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Mon Mar 02 11:04:43 2009 +0000
     1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Mon Mar 02 11:11:19 2009 +0000
     1.3 @@ -55,6 +55,7 @@ static void (*lapic_timer_on)(void);
     1.4  
     1.5  extern u32 pmtmr_ioport;
     1.6  extern void (*pm_idle) (void);
     1.7 +extern void (*dead_idle) (void);
     1.8  
     1.9  static void (*pm_idle_save) (void) __read_mostly;
    1.10  unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER - 1;
    1.11 @@ -369,6 +370,43 @@ static void acpi_processor_idle(void)
    1.12          cpuidle_current_governor->reflect(power);
    1.13  }
    1.14  
    1.15 +static void acpi_dead_idle(void)
    1.16 +{
    1.17 +    struct acpi_processor_power *power;
    1.18 +    struct acpi_processor_cx *cx;
    1.19 +    int unused;
    1.20 +
    1.21 +    if ( (power = processor_powers[smp_processor_id()]) == NULL )
    1.22 +        goto default_halt;
    1.23 +
    1.24 +    if ( (cx = &power->states[power->count-1]) == NULL )
    1.25 +        goto default_halt;
    1.26 +
    1.27 +    for ( ; ; )
    1.28 +    {
    1.29 +        if ( !power->flags.bm_check && cx->type == ACPI_STATE_C3 )
    1.30 +            ACPI_FLUSH_CPU_CACHE();
    1.31 +
    1.32 +        switch ( cx->entry_method )
    1.33 +        {
    1.34 +            case ACPI_CSTATE_EM_FFH:
    1.35 +                /* Not treat interrupt as break event */
    1.36 +                mwait_idle_with_hints(cx->address, 0);
    1.37 +                break;
    1.38 +            case ACPI_CSTATE_EM_SYSIO:
    1.39 +                inb(cx->address);
    1.40 +                unused = inl(pmtmr_ioport);
    1.41 +                break;
    1.42 +            default:
    1.43 +                goto default_halt;
    1.44 +        }
    1.45 +    }
    1.46 +
    1.47 +default_halt:
    1.48 +    for ( ; ; )
    1.49 +        halt();
    1.50 +}
    1.51 +
    1.52  static int init_cx_pminfo(struct acpi_processor_power *acpi_power)
    1.53  {
    1.54      int i;
    1.55 @@ -740,6 +778,11 @@ long set_cx_pminfo(uint32_t cpu, struct 
    1.56          pm_idle_save = pm_idle;
    1.57          pm_idle = acpi_processor_idle;
    1.58      }
    1.59 +
    1.60 +    if ( cpu_id == 0 )
    1.61 +    {
    1.62 +        dead_idle = acpi_dead_idle;
    1.63 +    }
    1.64          
    1.65      return 0;
    1.66  }
     2.1 --- a/xen/arch/x86/domain.c	Mon Mar 02 11:04:43 2009 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Mon Mar 02 11:11:19 2009 +0000
     2.3 @@ -58,7 +58,9 @@ DEFINE_PER_CPU(u64, efer);
     2.4  DEFINE_PER_CPU(unsigned long, cr4);
     2.5  
     2.6  static void default_idle(void);
     2.7 +static void default_dead_idle(void);
     2.8  void (*pm_idle) (void) = default_idle;
     2.9 +void (*dead_idle) (void) = default_dead_idle;
    2.10  
    2.11  static void paravirt_ctxt_switch_from(struct vcpu *v);
    2.12  static void paravirt_ctxt_switch_to(struct vcpu *v);
    2.13 @@ -84,6 +86,12 @@ static void default_idle(void)
    2.14          local_irq_enable();
    2.15  }
    2.16  
    2.17 +static void default_dead_idle(void)
    2.18 +{
    2.19 +    for ( ; ; )
    2.20 +        halt();
    2.21 +}
    2.22 +
    2.23  static void play_dead(void)
    2.24  {
    2.25      /*
    2.26 @@ -102,8 +110,7 @@ static void play_dead(void)
    2.27  
    2.28      /* With physical CPU hotplug, we should halt the cpu. */
    2.29      local_irq_disable();
    2.30 -    for ( ; ; )
    2.31 -        halt();
    2.32 +    (*dead_idle)();
    2.33  }
    2.34  
    2.35  void idle_loop(void)