aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-04-17 08:33:33 +0100
committerJan Beulich <jbeulich@suse.com>2012-04-17 08:33:33 +0100
commit329d4280255ff44300913f24119f52d3459c1ed0 (patch)
tree19a3c567a3788c12df04bfe60f3c74557f18bc8b
parentf89b5739abfda8ac53c44a3a6939f67e8c0a0aab (diff)
downloadxen-329d4280255ff44300913f24119f52d3459c1ed0.tar.gz
xen-329d4280255ff44300913f24119f52d3459c1ed0.tar.bz2
xen-329d4280255ff44300913f24119f52d3459c1ed0.zip
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
-rw-r--r--xen/arch/x86/acpi/cpu_idle.c78
-rw-r--r--xen/include/xen/cpuidle.h1
2 files changed, 38 insertions, 41 deletions
diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index 98b3746253..146224c044 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -69,10 +69,8 @@ static void lapic_timer_nop(void) { }
static void (*lapic_timer_off)(void);
static void (*lapic_timer_on)(void);
-static uint64_t (*get_tick)(void);
-static uint64_t (*ticks_elapsed)(uint64_t t1, uint64_t t2);
-static uint64_t (*tick_to_ns)(uint64_t ticks);
-static uint64_t (*ns_to_tick)(uint64_t ticks);
+static uint64_t (*__read_mostly tick_to_ns)(uint64_t) = acpi_pm_tick_to_ns;
+static uint64_t (*__read_mostly ns_to_tick)(uint64_t) = ns_to_acpi_pm_tick;
extern void (*pm_idle) (void);
extern void (*dead_idle) (void);
@@ -222,6 +220,10 @@ static uint64_t acpi_pm_ticks_elapsed(uint64_t t1, uint64_t t2)
return ((0xFFFFFFFF - t1) + t2 +1);
}
+static uint64_t (*__read_mostly get_tick)(void) = get_acpi_pm_tick;
+static uint64_t (*__read_mostly ticks_elapsed)(uint64_t, uint64_t)
+ = acpi_pm_ticks_elapsed;
+
#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
/*
@@ -607,7 +609,16 @@ static int cpuidle_init_cpu(int cpu)
acpi_power = processor_powers[cpu];
if ( !acpi_power )
{
- int i;
+ unsigned int i;
+
+ if ( cpu == 0 && boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
+ {
+ get_tick = get_stime_tick;
+ ticks_elapsed = stime_ticks_elapsed;
+ tick_to_ns = stime_tick_to_ns;
+ ns_to_tick = ns_to_stime_tick;
+ }
+
acpi_power = xmalloc(struct acpi_processor_power);
if ( !acpi_power )
return -ENOMEM;
@@ -615,36 +626,15 @@ static int cpuidle_init_cpu(int cpu)
for ( i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++ )
acpi_power->states[i].idx = i;
-
- acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1;
- acpi_power->states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_EM_HALT;
-
- acpi_power->states[ACPI_STATE_C0].valid = 1;
- acpi_power->states[ACPI_STATE_C1].valid = 1;
-
- acpi_power->count = 2;
- acpi_power->safe_state = &acpi_power->states[ACPI_STATE_C1];
+
acpi_power->cpu = cpu;
processor_powers[cpu] = acpi_power;
}
- if ( cpu == 0 )
- {
- if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
- {
- get_tick = get_stime_tick;
- ticks_elapsed = stime_ticks_elapsed;
- tick_to_ns = stime_tick_to_ns;
- ns_to_tick = ns_to_stime_tick;
- }
- else
- {
- get_tick = get_acpi_pm_tick;
- ticks_elapsed = acpi_pm_ticks_elapsed;
- tick_to_ns = acpi_pm_tick_to_ns;
- ns_to_tick = ns_to_acpi_pm_tick;
- }
- }
+ acpi_power->count = 2;
+ acpi_power->states[1].type = ACPI_STATE_C1;
+ acpi_power->states[1].entry_method = ACPI_CSTATE_EM_HALT;
+ acpi_power->safe_state = &acpi_power->states[1];
return 0;
}
@@ -863,17 +853,25 @@ static void set_cx(
if ( check_cx(acpi_power, xen_cx) != 0 )
return;
- if ( xen_cx->type == ACPI_STATE_C1 )
+ switch ( xen_cx->type )
+ {
+ case ACPI_STATE_C1:
cx = &acpi_power->states[1];
- else
- cx = &acpi_power->states[acpi_power->count];
-
- if ( !cx->valid )
- acpi_power->count++;
+ break;
+ default:
+ if ( acpi_power->count >= ACPI_PROCESSOR_MAX_POWER )
+ {
+ case ACPI_STATE_C0:
+ printk(XENLOG_WARNING "CPU%u: C%d data ignored\n",
+ acpi_power->cpu, xen_cx->type);
+ return;
+ }
+ cx = &acpi_power->states[acpi_power->count++];
+ cx->type = xen_cx->type;
+ break;
+ }
- cx->valid = 1;
- cx->type = xen_cx->type;
- cx->address = xen_cx->reg.address;
+ cx->address = xen_cx->reg.address;
switch ( xen_cx->reg.space_id )
{
diff --git a/xen/include/xen/cpuidle.h b/xen/include/xen/cpuidle.h
index bbdadb4ac4..9e883d242c 100644
--- a/xen/include/xen/cpuidle.h
+++ b/xen/include/xen/cpuidle.h
@@ -40,7 +40,6 @@
struct acpi_processor_cx
{
u8 idx;
- u8 valid;
u8 type;
u32 address;
u8 entry_method; /* ACPI_CSTATE_EM_xxx */