aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-05-14 15:46:43 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-05-14 15:46:43 +0100
commit520302d743e55423d60ff1fdd5b0decf05105973 (patch)
tree4c569ebc6608ffd11adcdb255f4416814ace7421
parentcda3e8c2a8e98f1883a49ccdd05357797b7e9e89 (diff)
downloadxen-520302d743e55423d60ff1fdd5b0decf05105973.tar.gz
xen-520302d743e55423d60ff1fdd5b0decf05105973.tar.bz2
xen-520302d743e55423d60ff1fdd5b0decf05105973.zip
cpuidle: Fix possible false judge caused by type casting
For timer_deadline == 0 or timer_deadline - now > largest u32 case, the expected_us (in u32 type) may become wrong. Add a tunable option to ease conditional adjustment. Signed-off-by: Wei Gang <gang.wei@intel.com>
-rw-r--r--xen/arch/x86/acpi/cpu_idle.c1
-rw-r--r--xen/arch/x86/acpi/cpuidle_menu.c12
2 files changed, 10 insertions, 3 deletions
diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index 0685194029..91f839e264 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -624,6 +624,7 @@ static int check_cx(struct acpi_processor_power *power, xen_processor_cx_t *cx)
}
static unsigned int latency_factor = 2;
+integer_param("idle_latency_factor", latency_factor);
static void set_cx(
struct acpi_processor_power *acpi_power,
diff --git a/xen/arch/x86/acpi/cpuidle_menu.c b/xen/arch/x86/acpi/cpuidle_menu.c
index 683dc3bb16..27ed7f5790 100644
--- a/xen/arch/x86/acpi/cpuidle_menu.c
+++ b/xen/arch/x86/acpi/cpuidle_menu.c
@@ -45,9 +45,15 @@ struct menu_device
static DEFINE_PER_CPU(struct menu_device, menu_devices);
-static s_time_t get_sleep_length_ns(void)
+static unsigned int get_sleep_length_us(void)
{
- return per_cpu(timer_deadline, smp_processor_id()) - NOW();
+ s_time_t us = (per_cpu(timer_deadline, smp_processor_id()) - NOW()) / 1000;
+ /*
+ * while us < 0 or us > (u32)-1, return a large u32,
+ * choose (unsigned int)-2000 to avoid wrapping while added with exit
+ * latency because the latency should not larger than 2ms
+ */
+ return (us >> 32) ? (unsigned int)-2000 : (unsigned int)us;
}
static int menu_select(struct acpi_processor_power *power)
@@ -56,7 +62,7 @@ static int menu_select(struct acpi_processor_power *power)
int i;
/* determine the expected residency time */
- data->expected_us = (u32) get_sleep_length_ns() / 1000;
+ data->expected_us = get_sleep_length_us();
/* find the deepest idle state that satisfies our constraints */
for ( i = 2; i < power->count; i++ )