# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1228482224 0
# Node ID eed39afde7dd52d623d8c1a0f659507ac630d9fc
# Parent 5e066dc410ac872c8976ae4db17891ed1dc5e00e
cpuidle: revise tsc-save/restore to reduce tsc skew between cpus
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/acpi/cpu_idle.c | 2 --
xen/arch/x86/time.c | 43 ++++++++++++++++++++++++-------------------
xen/include/xen/time.h | 1 -
3 files changed, 24 insertions(+), 22 deletions(-)
diff -r 5e066dc410ac -r eed39afde7dd xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c Fri Dec 05 11:37:20 2008 +0000
+++ b/xen/arch/x86/acpi/cpu_idle.c Fri Dec 05 13:03:44 2008 +0000
@@ -317,8 +317,6 @@ static void acpi_processor_idle(void)
* stopped by H/W. Without carefully handling of TSC/APIC stop issues,
* deep C state can't work correctly.
*/
- /* preparing TSC stop */
- cstate_save_tsc();
/* preparing APIC stop */
lapic_timer_off();
diff -r 5e066dc410ac -r eed39afde7dd xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Fri Dec 05 11:37:20 2008 +0000
+++ b/xen/arch/x86/time.c Fri Dec 05 13:03:44 2008 +0000
@@ -48,11 +48,9 @@ struct time_scale {
struct cpu_time {
u64 local_tsc_stamp;
- u64 cstate_tsc_stamp;
s_time_t stime_local_stamp;
s_time_t stime_master_stamp;
struct time_scale tsc_scale;
- u64 cstate_plt_count_stamp;
};
struct platform_timesource {
@@ -151,6 +149,19 @@ static inline u64 scale_delta(u64 delta,
return product;
}
+/* Compute the reciprocal of the given time_scale. */
+static inline struct time_scale scale_reciprocal(struct time_scale scale)
+{
+ u32 q, r;
+
+ asm (
+ "divl %4"
+ : "=a" (q), "=d" (r)
+ : "0" (1), "1" (0), "r" (scale.mul_frac) );
+
+ return (struct time_scale) { .shift = -scale.shift, .mul_frac = q };
+}
+
/*
* cpu_mask that denotes the CPUs that needs timer interrupt coming in as
* IPIs in place of local APIC timers
@@ -644,29 +655,23 @@ static void init_platform_timer(void)
freq_string(pts->frequency), pts->name);
}
-void cstate_save_tsc(void)
+void cstate_restore_tsc(void)
{
struct cpu_time *t = &this_cpu(cpu_time);
+ struct time_scale sys_to_tsc = scale_reciprocal(t->tsc_scale);
+ s_time_t stime_delta;
+ u64 tsc_delta;
if ( tsc_invariant )
return;
- t->cstate_plt_count_stamp = plt_src.read_counter();
- rdtscll(t->cstate_tsc_stamp);
-}
-
-void cstate_restore_tsc(void)
-{
- struct cpu_time *t = &this_cpu(cpu_time);
- u64 plt_count_delta, tsc_delta;
-
- if ( tsc_invariant )
- return;
-
- plt_count_delta = (plt_src.read_counter() -
- t->cstate_plt_count_stamp) & plt_mask;
- tsc_delta = scale_delta(plt_count_delta, &plt_scale) * cpu_khz/1000000UL;
- wrmsrl(MSR_IA32_TSC, t->cstate_tsc_stamp + tsc_delta);
+ stime_delta = read_platform_stime() - t->stime_master_stamp;
+ if ( stime_delta < 0 )
+ stime_delta = 0;
+
+ tsc_delta = scale_delta(stime_delta, &sys_to_tsc);
+
+ wrmsrl(MSR_IA32_TSC, t->local_tsc_stamp + tsc_delta);
}
/***************************************************************************
diff -r 5e066dc410ac -r eed39afde7dd xen/include/xen/time.h
--- a/xen/include/xen/time.h Fri Dec 05 11:37:20 2008 +0000
+++ b/xen/include/xen/time.h Fri Dec 05 13:03:44 2008 +0000
@@ -13,7 +13,6 @@
#include <asm/time.h>
extern int init_xen_time(void);
-extern void cstate_save_tsc(void);
extern void cstate_restore_tsc(void);
extern unsigned long cpu_khz;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|