ia64/xen-unstable

changeset 18748:112e81ae5824

CPUIDLE: Support C1 FFH entry

Add support for C1 FFH (mwait) entry. Meanwhile add timing for C1. The
timing for C1 should be accurate for FFH case, but may not for halt case.

Signed-off-by: Wei Gang <gang.wei@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Oct 30 13:33:40 2008 +0000 (2008-10-30)
parents 1137464400a8
children 9e5cf6778a6d
files xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/acpi/cpuidle_menu.c xen/include/xen/cpuidle.h
line diff
     1.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Thu Oct 30 13:33:17 2008 +0000
     1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Thu Oct 30 13:33:40 2008 +0000
     1.3 @@ -140,20 +140,26 @@ static void acpi_processor_ffh_cstate_en
     1.4  
     1.5  static void acpi_idle_do_entry(struct acpi_processor_cx *cx)
     1.6  {
     1.7 -    if ( cx->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE )
     1.8 +    int unused;
     1.9 +
    1.10 +    switch ( cx->entry_method )
    1.11      {
    1.12 +    case ACPI_CSTATE_EM_FFH:
    1.13          /* Call into architectural FFH based C-state */
    1.14          acpi_processor_ffh_cstate_enter(cx);
    1.15 -    }
    1.16 -    else
    1.17 -    {
    1.18 -        int unused;
    1.19 +        return;
    1.20 +    case ACPI_CSTATE_EM_SYSIO:
    1.21          /* IO port based C-state */
    1.22          inb(cx->address);
    1.23          /* Dummy wait op - must do something useless after P_LVL2 read
    1.24             because chipsets cannot guarantee that STPCLK# signal
    1.25             gets asserted in time to freeze execution properly. */
    1.26          unused = inl(pmtmr_ioport);
    1.27 +        return;
    1.28 +    case ACPI_CSTATE_EM_HALT:
    1.29 +        acpi_safe_halt();
    1.30 +        local_irq_disable();
    1.31 +        return;
    1.32      }
    1.33  }
    1.34  
    1.35 @@ -253,35 +259,11 @@ static void acpi_processor_idle(void)
    1.36      switch ( cx->type )
    1.37      {
    1.38      case ACPI_STATE_C1:
    1.39 -        /* Trace cpu idle entry */
    1.40 -        TRACE_1D(TRC_PM_IDLE_ENTRY, 1);
    1.41 -
    1.42 -        /*
    1.43 -         * Invoke C1.
    1.44 -         * Use the appropriate idle routine, the one that would
    1.45 -         * be used without acpi C-states.
    1.46 -         */
    1.47 -        if ( pm_idle_save )
    1.48 -            pm_idle_save();
    1.49 -        else 
    1.50 -            acpi_safe_halt();
    1.51 -
    1.52 -        /* Trace cpu idle exit */
    1.53 -        TRACE_1D(TRC_PM_IDLE_EXIT, 1);
    1.54 -
    1.55 -        /*
    1.56 -         * TBD: Can't get time duration while in C1, as resumes
    1.57 -         *      go to an ISR rather than here.  Need to instrument
    1.58 -         *      base interrupt handler.
    1.59 -         */
    1.60 -        sleep_ticks = 0xFFFFFFFF;
    1.61 -        break;
    1.62 -
    1.63      case ACPI_STATE_C2:
    1.64 -        if ( local_apic_timer_c2_ok )
    1.65 +        if ( cx->type == ACPI_STATE_C1 || local_apic_timer_c2_ok )
    1.66          {
    1.67              /* Trace cpu idle entry */
    1.68 -            TRACE_1D(TRC_PM_IDLE_ENTRY, 2);
    1.69 +            TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx);
    1.70              /* Get start time (ticks) */
    1.71              t1 = inl(pmtmr_ioport);
    1.72              /* Invoke C2 */
    1.73 @@ -289,7 +271,7 @@ static void acpi_processor_idle(void)
    1.74              /* Get end time (ticks) */
    1.75              t2 = inl(pmtmr_ioport);
    1.76              /* Trace cpu idle exit */
    1.77 -            TRACE_1D(TRC_PM_IDLE_EXIT, 2);
    1.78 +            TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx);
    1.79  
    1.80              /* Re-enable interrupts */
    1.81              local_irq_enable();
    1.82 @@ -396,6 +378,7 @@ static int init_cx_pminfo(struct acpi_pr
    1.83          acpi_power->states[i].idx = i;
    1.84  
    1.85      acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
    1.86 +    acpi_power->states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_EM_HALT;
    1.87  
    1.88      acpi_power->states[ACPI_STATE_C0].valid = 1;
    1.89      acpi_power->states[ACPI_STATE_C1].valid = 1;
    1.90 @@ -492,16 +475,13 @@ static int check_cx(struct acpi_processo
    1.91          break;
    1.92  
    1.93      case ACPI_ADR_SPACE_FIXED_HARDWARE:
    1.94 -        if ( cx->type > ACPI_STATE_C1 )
    1.95 -        {
    1.96 -            if ( cx->reg.bit_width != VENDOR_INTEL || 
    1.97 -                 cx->reg.bit_offset != NATIVE_CSTATE_BEYOND_HALT )
    1.98 -                return -EINVAL;
    1.99 +        if ( cx->reg.bit_width != VENDOR_INTEL || 
   1.100 +             cx->reg.bit_offset != NATIVE_CSTATE_BEYOND_HALT )
   1.101 +            return -EINVAL;
   1.102  
   1.103 -            /* assume all logical cpu has the same support for mwait */
   1.104 -            if ( acpi_processor_ffh_cstate_probe(cx) )
   1.105 -                return -EINVAL;
   1.106 -        }
   1.107 +        /* assume all logical cpu has the same support for mwait */
   1.108 +        if ( acpi_processor_ffh_cstate_probe(cx) )
   1.109 +            return -EINVAL;
   1.110          break;
   1.111  
   1.112      default:
   1.113 @@ -605,7 +585,23 @@ static void set_cx(
   1.114      cx->valid    = 1;
   1.115      cx->type     = xen_cx->type;
   1.116      cx->address  = xen_cx->reg.address;
   1.117 -    cx->space_id = xen_cx->reg.space_id;
   1.118 +
   1.119 +    switch ( xen_cx->reg.space_id )
   1.120 +    {
   1.121 +    case ACPI_ADR_SPACE_FIXED_HARDWARE:
   1.122 +        if ( xen_cx->reg.bit_width == VENDOR_INTEL &&
   1.123 +             xen_cx->reg.bit_offset == NATIVE_CSTATE_BEYOND_HALT )
   1.124 +            cx->entry_method = ACPI_CSTATE_EM_FFH;
   1.125 +        else
   1.126 +            cx->entry_method = ACPI_CSTATE_EM_HALT;
   1.127 +        break;
   1.128 +    case ACPI_ADR_SPACE_SYSTEM_IO:
   1.129 +        cx->entry_method = ACPI_CSTATE_EM_SYSIO;
   1.130 +        break;
   1.131 +    default:
   1.132 +        cx->entry_method = ACPI_CSTATE_EM_NONE;
   1.133 +    }
   1.134 +
   1.135      cx->latency  = xen_cx->latency;
   1.136      cx->power    = xen_cx->power;
   1.137      
     2.1 --- a/xen/arch/x86/acpi/cpuidle_menu.c	Thu Oct 30 13:33:17 2008 +0000
     2.2 +++ b/xen/arch/x86/acpi/cpuidle_menu.c	Thu Oct 30 13:33:40 2008 +0000
     2.3 @@ -59,7 +59,7 @@ static int menu_select(struct acpi_proce
     2.4      data->expected_us = (u32) get_sleep_length_ns() / 1000;
     2.5  
     2.6      /* find the deepest idle state that satisfies our constraints */
     2.7 -    for ( i = 1; i < power->count; i++ )
     2.8 +    for ( i = 2; i < power->count; i++ )
     2.9      {
    2.10          struct acpi_processor_cx *s = &power->states[i];
    2.11  
    2.12 @@ -81,17 +81,7 @@ static void menu_reflect(struct acpi_pro
    2.13      unsigned int last_residency; 
    2.14      unsigned int measured_us;
    2.15  
    2.16 -    /*
    2.17 -     * Ugh, this idle state doesn't support residency measurements, so we
    2.18 -     * are basically lost in the dark.  As a compromise, assume we slept
    2.19 -     * for one full standard timer tick.  However, be aware that this
    2.20 -     * could potentially result in a suboptimal state transition.
    2.21 -     */
    2.22 -    if ( target->type == ACPI_STATE_C1 )
    2.23 -        last_residency = USEC_PER_SEC / HZ;
    2.24 -    else
    2.25 -        last_residency = power->last_residency;
    2.26 -
    2.27 +    last_residency = power->last_residency;
    2.28      measured_us = last_residency + data->elapsed_us;
    2.29  
    2.30      /* if wrapping, set to max uint (-1) */
     3.1 --- a/xen/include/xen/cpuidle.h	Thu Oct 30 13:33:17 2008 +0000
     3.2 +++ b/xen/include/xen/cpuidle.h	Thu Oct 30 13:33:40 2008 +0000
     3.3 @@ -30,13 +30,18 @@
     3.4  #define ACPI_PROCESSOR_MAX_POWER        8
     3.5  #define CPUIDLE_NAME_LEN                16
     3.6  
     3.7 +#define ACPI_CSTATE_EM_NONE     0
     3.8 +#define ACPI_CSTATE_EM_SYSIO    1
     3.9 +#define ACPI_CSTATE_EM_FFH      2
    3.10 +#define ACPI_CSTATE_EM_HALT     3
    3.11 +
    3.12  struct acpi_processor_cx
    3.13  {
    3.14      u8 idx;
    3.15      u8 valid;
    3.16      u8 type;
    3.17      u32 address;
    3.18 -    u8 space_id;
    3.19 +    u8 entry_method; /* ACPI_CSTATE_EM_xxx */
    3.20      u32 latency;
    3.21      u32 latency_ticks;
    3.22      u32 power;