xcp-1.6-updates/xen-4.1.hg

changeset 23281:00881b29bfe2

XENPF_set_processor_pminfo XEN_PM_CX overflows states array

Calling XENPF_set_processor_pminfo with XEN_PM_CX could cause states
array in "struct acpi_processor_power" to exceed its limit.

The array used to be reset (by function cpuidle_init_cpu()) for each
hypercall. The patch puts it back that way and adds an assertion to
make it clear in case that happens again.

Signed-off-by: Eric Chanudet <eric.chanudet@eu.citrix.com>

- convert assertion to printk() & bail
- eliminate struct acpi_processor_cx's valid member (not read anymore)
- further adjustments to one-time-only vs each-time operations in
cpuidle_init_cpu()
- don't use ACPI_STATE_Cn as array index anymore

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 24996:396801f25e92
xen-unstable date: Thu Mar 08 17:04:32 2012 +0100
author Jan Beulich <jbeulich@suse.com>
date Tue Apr 17 08:33:33 2012 +0100 (2012-04-17)
parents 4ad262a48a71
children 182633356cd4
files xen/arch/x86/acpi/cpu_idle.c xen/include/xen/cpuidle.h
line diff
     1.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Thu Apr 12 09:13:14 2012 +0100
     1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Tue Apr 17 08:33:33 2012 +0100
     1.3 @@ -69,10 +69,8 @@ static void lapic_timer_nop(void) { }
     1.4  static void (*lapic_timer_off)(void);
     1.5  static void (*lapic_timer_on)(void);
     1.6  
     1.7 -static uint64_t (*get_tick)(void);
     1.8 -static uint64_t (*ticks_elapsed)(uint64_t t1, uint64_t t2);
     1.9 -static uint64_t (*tick_to_ns)(uint64_t ticks);
    1.10 -static uint64_t (*ns_to_tick)(uint64_t ticks);
    1.11 +static uint64_t (*__read_mostly tick_to_ns)(uint64_t) = acpi_pm_tick_to_ns;
    1.12 +static uint64_t (*__read_mostly ns_to_tick)(uint64_t) = ns_to_acpi_pm_tick;
    1.13  
    1.14  extern void (*pm_idle) (void);
    1.15  extern void (*dead_idle) (void);
    1.16 @@ -222,6 +220,10 @@ static uint64_t acpi_pm_ticks_elapsed(ui
    1.17          return ((0xFFFFFFFF - t1) + t2 +1);
    1.18  }
    1.19  
    1.20 +static uint64_t (*__read_mostly get_tick)(void) = get_acpi_pm_tick;
    1.21 +static uint64_t (*__read_mostly ticks_elapsed)(uint64_t, uint64_t)
    1.22 +    = acpi_pm_ticks_elapsed;
    1.23 +
    1.24  #define MWAIT_ECX_INTERRUPT_BREAK   (0x1)
    1.25  
    1.26  /*
    1.27 @@ -607,7 +609,16 @@ static int cpuidle_init_cpu(int cpu)
    1.28      acpi_power = processor_powers[cpu];
    1.29      if ( !acpi_power )
    1.30      {
    1.31 -        int i;
    1.32 +        unsigned int i;
    1.33 +
    1.34 +        if ( cpu == 0 && boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
    1.35 +        {
    1.36 +            get_tick = get_stime_tick;
    1.37 +            ticks_elapsed = stime_ticks_elapsed;
    1.38 +            tick_to_ns = stime_tick_to_ns;
    1.39 +            ns_to_tick = ns_to_stime_tick;
    1.40 +        }
    1.41 +
    1.42          acpi_power = xmalloc(struct acpi_processor_power);
    1.43          if ( !acpi_power )
    1.44              return -ENOMEM;
    1.45 @@ -615,36 +626,15 @@ static int cpuidle_init_cpu(int cpu)
    1.46  
    1.47          for ( i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++ )
    1.48              acpi_power->states[i].idx = i;
    1.49 -     
    1.50 -        acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
    1.51 -        acpi_power->states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_EM_HALT;
    1.52 -     
    1.53 -        acpi_power->states[ACPI_STATE_C0].valid = 1;
    1.54 -        acpi_power->states[ACPI_STATE_C1].valid = 1;
    1.55 -     
    1.56 -        acpi_power->count = 2;
    1.57 -        acpi_power->safe_state = &acpi_power->states[ACPI_STATE_C1];
    1.58 +
    1.59          acpi_power->cpu = cpu;
    1.60          processor_powers[cpu] = acpi_power;
    1.61      }
    1.62  
    1.63 -    if ( cpu == 0 )
    1.64 -    {
    1.65 -        if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
    1.66 -        {
    1.67 -            get_tick = get_stime_tick;
    1.68 -            ticks_elapsed = stime_ticks_elapsed;
    1.69 -            tick_to_ns = stime_tick_to_ns;
    1.70 -            ns_to_tick = ns_to_stime_tick;
    1.71 -        }
    1.72 -        else
    1.73 -        {
    1.74 -            get_tick = get_acpi_pm_tick;
    1.75 -            ticks_elapsed = acpi_pm_ticks_elapsed;
    1.76 -            tick_to_ns = acpi_pm_tick_to_ns;
    1.77 -            ns_to_tick = ns_to_acpi_pm_tick;
    1.78 -        }
    1.79 -    }
    1.80 +    acpi_power->count = 2;
    1.81 +    acpi_power->states[1].type = ACPI_STATE_C1;
    1.82 +    acpi_power->states[1].entry_method = ACPI_CSTATE_EM_HALT;
    1.83 +    acpi_power->safe_state = &acpi_power->states[1];
    1.84  
    1.85      return 0;
    1.86  }
    1.87 @@ -863,17 +853,25 @@ static void set_cx(
    1.88      if ( check_cx(acpi_power, xen_cx) != 0 )
    1.89          return;
    1.90  
    1.91 -    if ( xen_cx->type == ACPI_STATE_C1 )
    1.92 +    switch ( xen_cx->type )
    1.93 +    {
    1.94 +    case ACPI_STATE_C1:
    1.95          cx = &acpi_power->states[1];
    1.96 -    else
    1.97 -        cx = &acpi_power->states[acpi_power->count];
    1.98 +        break;
    1.99 +    default:
   1.100 +        if ( acpi_power->count >= ACPI_PROCESSOR_MAX_POWER )
   1.101 +        {
   1.102 +    case ACPI_STATE_C0:
   1.103 +            printk(XENLOG_WARNING "CPU%u: C%d data ignored\n",
   1.104 +                   acpi_power->cpu, xen_cx->type);
   1.105 +            return;
   1.106 +        }
   1.107 +        cx = &acpi_power->states[acpi_power->count++];
   1.108 +        cx->type = xen_cx->type;
   1.109 +        break;
   1.110 +    }
   1.111  
   1.112 -    if ( !cx->valid )
   1.113 -        acpi_power->count++;
   1.114 -
   1.115 -    cx->valid    = 1;
   1.116 -    cx->type     = xen_cx->type;
   1.117 -    cx->address  = xen_cx->reg.address;
   1.118 +    cx->address = xen_cx->reg.address;
   1.119  
   1.120      switch ( xen_cx->reg.space_id )
   1.121      {
     2.1 --- a/xen/include/xen/cpuidle.h	Thu Apr 12 09:13:14 2012 +0100
     2.2 +++ b/xen/include/xen/cpuidle.h	Tue Apr 17 08:33:33 2012 +0100
     2.3 @@ -40,7 +40,6 @@
     2.4  struct acpi_processor_cx
     2.5  {
     2.6      u8 idx;
     2.7 -    u8 valid;
     2.8      u8 type;
     2.9      u32 address;
    2.10      u8 entry_method; /* ACPI_CSTATE_EM_xxx */