diff -r ea6a9793928d xen/arch/x86/time.c --- a/xen/arch/x86/time.c Tue Jul 15 18:00:13 2008 +0100 +++ b/xen/arch/x86/time.c Thu Jul 17 14:34:24 2008 -0600 @@ -484,7 +484,7 @@ static int init_pmtimer(struct platform_ * PLATFORM TIMER 5: TSC */ -#define platform_timer_is_tsc() (!strcmp(plt_src.name, "TSC")) +#define platform_timer_is_tsc() (plt_src.counter_bits == 64) static u64 tsc_freq; static u64 read_tsc_count(void) @@ -496,22 +496,7 @@ static u64 read_tsc_count(void) static int init_tsctimer(struct platform_timesource *pts) { - unsigned int cpu; - - /* - * TODO: evaluate stability of TSC here, return 0 if not stable. - * For now we assume all TSCs are synchronised and hence can all share - * CPU 0's calibration values. - */ - for_each_cpu ( cpu ) - { - if ( cpu == 0 ) - continue; - memcpy(&per_cpu(cpu_time, cpu), - &per_cpu(cpu_time, 0), - sizeof(struct cpu_time)); - } - + /* TODO: evaluate stability of TSC here, return 0 if not stable */ pts->name = "TSC"; pts->frequency = tsc_freq; pts->read_counter = read_tsc_count; @@ -541,6 +526,7 @@ static void plt_overflow(void *unused) { u64 count; + ASSERT(plt_src.counter_bits <= 32); spin_lock(&platform_timer_lock); count = plt_src.read_counter(); plt_stamp64 += (count - plt_stamp) & plt_mask; @@ -575,6 +561,8 @@ static void platform_time_calibration(vo u64 count; s_time_t stamp; + if ( plt_src.counter_bits == 64 ) + return; spin_lock(&platform_timer_lock); count = plt_stamp64 + ((plt_src.read_counter() - plt_stamp) & plt_mask); stamp = __read_platform_stime(count); @@ -585,6 +573,8 @@ static void platform_time_calibration(vo static void resume_platform_timer(void) { + if ( plt_src.counter_bits == 64 ) + return; /* No change in platform_stime across suspend/resume. */ platform_timer_stamp = plt_stamp64; plt_stamp = plt_src.read_counter(); @@ -624,12 +614,21 @@ static void init_platform_timer(void) set_time_scale(&plt_scale, pts->frequency); - plt_overflow_period = scale_delta( - 1ull << (pts->counter_bits-1), &plt_scale); - init_timer(&plt_overflow_timer, plt_overflow, NULL, 0); - plt_overflow(NULL); + if (pts->counter_bits != 64 ) + { + plt_overflow_period = scale_delta( + 1ull << (pts->counter_bits-1), &plt_scale); + init_timer(&plt_overflow_timer, plt_overflow, NULL, 0); + plt_overflow(NULL); - platform_timer_stamp = plt_stamp64; + platform_timer_stamp = plt_stamp64; + } + else + { + platform_timer_stamp = stime_platform_stamp = 0; + plt_stamp = plt_stamp64 = 0; + } + printk("Platform timer is %s %s\n", freq_string(pts->frequency), pts->name); @@ -752,14 +751,19 @@ static unsigned long get_cmos_time(void) s_time_t get_s_time(void) { - struct cpu_time *t = &this_cpu(cpu_time); + struct cpu_time *t; u64 tsc, delta; s_time_t now; rdtscll(tsc); - delta = tsc - t->local_tsc_stamp; - now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale); - + if (platform_timer_is_tsc() ) + now = scale_delta(tsc, &plt_scale); + else + { + t = &this_cpu(cpu_time); + delta = tsc - t->local_tsc_stamp; + now = t->stime_local_stamp + scale_delta(delta, &t->tsc_scale); + } return now; } @@ -821,10 +825,6 @@ int cpu_frequency_change(u64 freq) { struct cpu_time *t = &this_cpu(cpu_time); u64 curr_tsc; - - /* Nothing to do if TSC is platform timer. Assume it is constant-rate. */ - if ( platform_timer_is_tsc() ) - return 0; /* Sanity check: CPU frequency allegedly dropping below 1MHz? */ if ( freq < 1000000u ) @@ -1024,12 +1024,9 @@ void init_percpu_time(void) unsigned long flags; s_time_t now; - if ( platform_timer_is_tsc() ) - return; - local_irq_save(flags); rdtscll(t->local_tsc_stamp); - now = read_platform_stime(); + now = ( !plt_src.read_counter ) ? 0 : read_platform_stime(); local_irq_restore(flags); t->stime_master_stamp = now; @@ -1047,10 +1044,10 @@ int __init init_xen_time(void) local_irq_disable(); + init_percpu_time(); + stime_platform_stamp = 0; init_platform_timer(); - - init_percpu_time(); /* check if TSC is invariant during deep C state this is a new feature introduced by Nehalem*/ @@ -1146,12 +1143,11 @@ int time_suspend(void) int time_resume(void) { - /*u64 tmp = */init_pit_and_calibrate_tsc(); + u64 tmp = init_pit_and_calibrate_tsc(); disable_pit_irq(); - /* Disable this while calibrate_tsc_ap() also is skipped. */ - /*set_time_scale(&this_cpu(cpu_time).tsc_scale, tmp);*/ + set_time_scale(&this_cpu(cpu_time).tsc_scale, tmp); resume_platform_timer();