ia64/xen-unstable
changeset 18122:85a83b919653
x86: Reintroduce clocksource=tsc.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Mon Jul 21 10:39:15 2008 +0100 (2008-07-21) |
parents | a0ce4b040114 |
children | c049e70af85f |
files | xen/arch/x86/time.c |
line diff
1.1 --- a/xen/arch/x86/time.c Mon Jul 21 10:00:18 2008 +0100 1.2 +++ b/xen/arch/x86/time.c Mon Jul 21 10:39:15 2008 +0100 1.3 @@ -481,6 +481,35 @@ static int init_pmtimer(struct platform_ 1.4 } 1.5 1.6 /************************************************************ 1.7 + * PLATFORM TIMER 5: TSC 1.8 + */ 1.9 + 1.10 +static const char plt_tsc_name[] = "TSC"; 1.11 +#define platform_timer_is_tsc() (plt_src.name == plt_tsc_name) 1.12 + 1.13 +static int init_tsctimer(struct platform_timesource *pts) 1.14 +{ 1.15 + if ( !tsc_invariant ) 1.16 + return 0; 1.17 + 1.18 + pts->name = (char *)plt_tsc_name; 1.19 + return 1; 1.20 +} 1.21 + 1.22 +static void make_tsctimer_record(void) 1.23 +{ 1.24 + struct cpu_time *t = &this_cpu(cpu_time); 1.25 + s_time_t now; 1.26 + u64 tsc; 1.27 + 1.28 + rdtscll(tsc); 1.29 + now = scale_delta(tsc, &t->tsc_scale); 1.30 + 1.31 + t->local_tsc_stamp = tsc; 1.32 + t->stime_local_stamp = t->stime_master_stamp = now; 1.33 +} 1.34 + 1.35 +/************************************************************ 1.36 * GENERIC PLATFORM TIMER INFRASTRUCTURE 1.37 */ 1.38 1.39 @@ -545,6 +574,12 @@ static void platform_time_calibration(vo 1.40 1.41 static void resume_platform_timer(void) 1.42 { 1.43 + if ( platform_timer_is_tsc() ) 1.44 + { 1.45 + /* TODO: Save/restore TSC values. */ 1.46 + return; 1.47 + } 1.48 + 1.49 /* No change in platform_stime across suspend/resume. */ 1.50 platform_timer_stamp = plt_stamp64; 1.51 plt_stamp = plt_src.read_counter(); 1.52 @@ -565,6 +600,8 @@ static void init_platform_timer(void) 1.53 rc = init_cyclone(pts); 1.54 else if ( !strcmp(opt_clocksource, "acpi") ) 1.55 rc = init_pmtimer(pts); 1.56 + else if ( !strcmp(opt_clocksource, "tsc") ) 1.57 + rc = init_tsctimer(pts); 1.58 1.59 if ( rc <= 0 ) 1.60 printk("WARNING: %s clocksource '%s'.\n", 1.61 @@ -578,6 +615,12 @@ static void init_platform_timer(void) 1.62 !init_pmtimer(pts) ) 1.63 init_pit(pts); 1.64 1.65 + if ( platform_timer_is_tsc() ) 1.66 + { 1.67 + printk("Platform timer is TSC\n"); 1.68 + return; 1.69 + } 1.70 + 1.71 plt_mask = (u64)~0ull >> (64 - pts->counter_bits); 1.72 1.73 set_time_scale(&plt_scale, pts->frequency); 1.74 @@ -780,6 +823,10 @@ int cpu_frequency_change(u64 freq) 1.75 struct cpu_time *t = &this_cpu(cpu_time); 1.76 u64 curr_tsc; 1.77 1.78 + /* Nothing to do if TSC is platform timer. Assume it is constant-rate. */ 1.79 + if ( platform_timer_is_tsc() ) 1.80 + return 0; 1.81 + 1.82 /* Sanity check: CPU frequency allegedly dropping below 1MHz? */ 1.83 if ( freq < 1000000u ) 1.84 { 1.85 @@ -861,6 +908,14 @@ static void local_time_calibration(void 1.86 /* The overall calibration scale multiplier. */ 1.87 u32 calibration_mul_frac; 1.88 1.89 + if ( platform_timer_is_tsc() ) 1.90 + { 1.91 + make_tsctimer_record(); 1.92 + update_vcpu_system_time(current); 1.93 + set_timer(&t->calibration_timer, NOW() + MILLISECS(10*1000)); 1.94 + return; 1.95 + } 1.96 + 1.97 prev_tsc = t->local_tsc_stamp; 1.98 prev_local_stime = t->stime_local_stamp; 1.99 prev_master_stime = t->stime_master_stamp; 1.100 @@ -978,6 +1033,12 @@ void init_percpu_time(void) 1.101 unsigned long flags; 1.102 s_time_t now; 1.103 1.104 + if ( platform_timer_is_tsc() ) 1.105 + { 1.106 + make_tsctimer_record(); 1.107 + goto out; 1.108 + } 1.109 + 1.110 local_irq_save(flags); 1.111 rdtscll(t->local_tsc_stamp); 1.112 now = !plt_src.read_counter ? 0 : read_platform_stime(); 1.113 @@ -986,6 +1047,7 @@ void init_percpu_time(void) 1.114 t->stime_master_stamp = now; 1.115 t->stime_local_stamp = now; 1.116 1.117 + out: 1.118 init_timer(&t->calibration_timer, local_time_calibration, 1.119 NULL, smp_processor_id()); 1.120 set_timer(&t->calibration_timer, NOW() + EPOCH); 1.121 @@ -994,19 +1056,19 @@ void init_percpu_time(void) 1.122 /* Late init function (after all CPUs are booted). */ 1.123 int __init init_xen_time(void) 1.124 { 1.125 - wc_sec = get_cmos_time(); 1.126 + local_irq_disable(); 1.127 1.128 - local_irq_disable(); 1.129 + /* check if TSC is invariant during deep C state 1.130 + this is a new feature introduced by Nehalem*/ 1.131 + if ( cpuid_edx(0x80000007) & (1u<<8) ) 1.132 + tsc_invariant = 1; 1.133 1.134 init_percpu_time(); 1.135 1.136 stime_platform_stamp = 0; 1.137 init_platform_timer(); 1.138 1.139 - /* check if TSC is invariant during deep C state 1.140 - this is a new feature introduced by Nehalem*/ 1.141 - if ( cpuid_edx(0x80000007) & (1U<<8) ) 1.142 - tsc_invariant = 1; 1.143 + do_settime(get_cmos_time(), 0, NOW()); 1.144 1.145 local_irq_enable(); 1.146 1.147 @@ -1120,9 +1182,9 @@ int time_resume(void) 1.148 1.149 resume_platform_timer(); 1.150 1.151 - do_settime(get_cmos_time() + cmos_utc_offset, 0, read_platform_stime()); 1.152 + init_percpu_time(); 1.153 1.154 - init_percpu_time(); 1.155 + do_settime(get_cmos_time() + cmos_utc_offset, 0, NOW()); 1.156 1.157 if ( !is_idle_vcpu(current) ) 1.158 update_vcpu_system_time(current);