ia64/xen-unstable
changeset 18883:eed39afde7dd
cpuidle: revise tsc-save/restore to reduce tsc skew between cpus
Signed-off-by: Wei Gang <gang.wei@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Dec 05 13:03:44 2008 +0000 (2008-12-05) |
parents | 5e066dc410ac |
children | 4ffd935c08a3 |
files | xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/time.c xen/include/xen/time.h |
line diff
1.1 --- a/xen/arch/x86/acpi/cpu_idle.c Fri Dec 05 11:37:20 2008 +0000 1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c Fri Dec 05 13:03:44 2008 +0000 1.3 @@ -317,8 +317,6 @@ static void acpi_processor_idle(void) 1.4 * stopped by H/W. Without carefully handling of TSC/APIC stop issues, 1.5 * deep C state can't work correctly. 1.6 */ 1.7 - /* preparing TSC stop */ 1.8 - cstate_save_tsc(); 1.9 /* preparing APIC stop */ 1.10 lapic_timer_off(); 1.11
2.1 --- a/xen/arch/x86/time.c Fri Dec 05 11:37:20 2008 +0000 2.2 +++ b/xen/arch/x86/time.c Fri Dec 05 13:03:44 2008 +0000 2.3 @@ -48,11 +48,9 @@ struct time_scale { 2.4 2.5 struct cpu_time { 2.6 u64 local_tsc_stamp; 2.7 - u64 cstate_tsc_stamp; 2.8 s_time_t stime_local_stamp; 2.9 s_time_t stime_master_stamp; 2.10 struct time_scale tsc_scale; 2.11 - u64 cstate_plt_count_stamp; 2.12 }; 2.13 2.14 struct platform_timesource { 2.15 @@ -151,6 +149,19 @@ static inline u64 scale_delta(u64 delta, 2.16 return product; 2.17 } 2.18 2.19 +/* Compute the reciprocal of the given time_scale. */ 2.20 +static inline struct time_scale scale_reciprocal(struct time_scale scale) 2.21 +{ 2.22 + u32 q, r; 2.23 + 2.24 + asm ( 2.25 + "divl %4" 2.26 + : "=a" (q), "=d" (r) 2.27 + : "0" (1), "1" (0), "r" (scale.mul_frac) ); 2.28 + 2.29 + return (struct time_scale) { .shift = -scale.shift, .mul_frac = q }; 2.30 +} 2.31 + 2.32 /* 2.33 * cpu_mask that denotes the CPUs that needs timer interrupt coming in as 2.34 * IPIs in place of local APIC timers 2.35 @@ -644,29 +655,23 @@ static void init_platform_timer(void) 2.36 freq_string(pts->frequency), pts->name); 2.37 } 2.38 2.39 -void cstate_save_tsc(void) 2.40 +void cstate_restore_tsc(void) 2.41 { 2.42 struct cpu_time *t = &this_cpu(cpu_time); 2.43 + struct time_scale sys_to_tsc = scale_reciprocal(t->tsc_scale); 2.44 + s_time_t stime_delta; 2.45 + u64 tsc_delta; 2.46 2.47 if ( tsc_invariant ) 2.48 return; 2.49 2.50 - t->cstate_plt_count_stamp = plt_src.read_counter(); 2.51 - rdtscll(t->cstate_tsc_stamp); 2.52 -} 2.53 + stime_delta = read_platform_stime() - t->stime_master_stamp; 2.54 + if ( stime_delta < 0 ) 2.55 + stime_delta = 0; 2.56 2.57 -void cstate_restore_tsc(void) 2.58 -{ 2.59 - struct cpu_time *t = &this_cpu(cpu_time); 2.60 - u64 plt_count_delta, tsc_delta; 2.61 + tsc_delta = scale_delta(stime_delta, &sys_to_tsc); 2.62 2.63 - if ( tsc_invariant ) 2.64 - return; 2.65 - 2.66 - plt_count_delta = (plt_src.read_counter() - 2.67 - t->cstate_plt_count_stamp) & plt_mask; 2.68 - tsc_delta = scale_delta(plt_count_delta, &plt_scale) * cpu_khz/1000000UL; 2.69 - wrmsrl(MSR_IA32_TSC, t->cstate_tsc_stamp + tsc_delta); 2.70 + wrmsrl(MSR_IA32_TSC, t->local_tsc_stamp + tsc_delta); 2.71 } 2.72 2.73 /***************************************************************************
3.1 --- a/xen/include/xen/time.h Fri Dec 05 11:37:20 2008 +0000 3.2 +++ b/xen/include/xen/time.h Fri Dec 05 13:03:44 2008 +0000 3.3 @@ -13,7 +13,6 @@ 3.4 #include <asm/time.h> 3.5 3.6 extern int init_xen_time(void); 3.7 -extern void cstate_save_tsc(void); 3.8 extern void cstate_restore_tsc(void); 3.9 3.10 extern unsigned long cpu_khz;