aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r--arch/x86_64/kernel/time.c63
1 files changed, 35 insertions, 28 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index ab9bea82945f..51afb07bc14e 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -56,6 +56,13 @@ DEFINE_SPINLOCK(i8253_lock);
56int nohpet __initdata = 0; 56int nohpet __initdata = 0;
57static int notsc __initdata = 0; 57static int notsc __initdata = 0;
58 58
59#define USEC_PER_TICK (USEC_PER_SEC / HZ)
60#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
61#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
62
63#define NS_SCALE 10 /* 2^10, carefully chosen */
64#define US_SCALE 32 /* 2^32, arbitralrily chosen */
65
59unsigned int cpu_khz; /* TSC clocks / usec, not used here */ 66unsigned int cpu_khz; /* TSC clocks / usec, not used here */
60static unsigned long hpet_period; /* fsecs / HPET clock */ 67static unsigned long hpet_period; /* fsecs / HPET clock */
61unsigned long hpet_tick; /* HPET clocks / interrupt */ 68unsigned long hpet_tick; /* HPET clocks / interrupt */
@@ -88,7 +95,7 @@ static inline unsigned int do_gettimeoffset_tsc(void)
88 t = get_cycles_sync(); 95 t = get_cycles_sync();
89 if (t < vxtime.last_tsc) 96 if (t < vxtime.last_tsc)
90 t = vxtime.last_tsc; /* hack */ 97 t = vxtime.last_tsc; /* hack */
91 x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32; 98 x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;
92 return x; 99 return x;
93} 100}
94 101
@@ -96,7 +103,7 @@ static inline unsigned int do_gettimeoffset_hpet(void)
96{ 103{
97 /* cap counter read to one tick to avoid inconsistencies */ 104 /* cap counter read to one tick to avoid inconsistencies */
98 unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last; 105 unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
99 return (min(counter,hpet_tick) * vxtime.quot) >> 32; 106 return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
100} 107}
101 108
102unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc; 109unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
@@ -116,7 +123,7 @@ void do_gettimeofday(struct timeval *tv)
116 seq = read_seqbegin(&xtime_lock); 123 seq = read_seqbegin(&xtime_lock);
117 124
118 sec = xtime.tv_sec; 125 sec = xtime.tv_sec;
119 usec = xtime.tv_nsec / 1000; 126 usec = xtime.tv_nsec / NSEC_PER_USEC;
120 127
121 /* i386 does some correction here to keep the clock 128 /* i386 does some correction here to keep the clock
122 monotonous even when ntpd is fixing drift. 129 monotonous even when ntpd is fixing drift.
@@ -127,14 +134,14 @@ void do_gettimeofday(struct timeval *tv)
127 in arch/x86_64/kernel/vsyscall.c and export all needed 134 in arch/x86_64/kernel/vsyscall.c and export all needed
128 variables in vmlinux.lds. -AK */ 135 variables in vmlinux.lds. -AK */
129 136
130 t = (jiffies - wall_jiffies) * (1000000L / HZ) + 137 t = (jiffies - wall_jiffies) * USEC_PER_TICK +
131 do_gettimeoffset(); 138 do_gettimeoffset();
132 usec += t; 139 usec += t;
133 140
134 } while (read_seqretry(&xtime_lock, seq)); 141 } while (read_seqretry(&xtime_lock, seq));
135 142
136 tv->tv_sec = sec + usec / 1000000; 143 tv->tv_sec = sec + usec / USEC_PER_SEC;
137 tv->tv_usec = usec % 1000000; 144 tv->tv_usec = usec % USEC_PER_SEC;
138} 145}
139 146
140EXPORT_SYMBOL(do_gettimeofday); 147EXPORT_SYMBOL(do_gettimeofday);
@@ -155,8 +162,8 @@ int do_settimeofday(struct timespec *tv)
155 162
156 write_seqlock_irq(&xtime_lock); 163 write_seqlock_irq(&xtime_lock);
157 164
158 nsec -= do_gettimeoffset() * 1000 + 165 nsec -= do_gettimeoffset() * NSEC_PER_USEC +
159 (jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ); 166 (jiffies - wall_jiffies) * NSEC_PER_TICK;
160 167
161 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 168 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
162 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 169 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -286,7 +293,7 @@ unsigned long long monotonic_clock(void)
286 this_offset = hpet_readl(HPET_COUNTER); 293 this_offset = hpet_readl(HPET_COUNTER);
287 } while (read_seqretry(&xtime_lock, seq)); 294 } while (read_seqretry(&xtime_lock, seq));
288 offset = (this_offset - last_offset); 295 offset = (this_offset - last_offset);
289 offset *= (NSEC_PER_SEC/HZ) / hpet_tick; 296 offset *= NSEC_PER_TICK / hpet_tick;
290 } else { 297 } else {
291 do { 298 do {
292 seq = read_seqbegin(&xtime_lock); 299 seq = read_seqbegin(&xtime_lock);
@@ -295,7 +302,8 @@ unsigned long long monotonic_clock(void)
295 base = monotonic_base; 302 base = monotonic_base;
296 } while (read_seqretry(&xtime_lock, seq)); 303 } while (read_seqretry(&xtime_lock, seq));
297 this_offset = get_cycles_sync(); 304 this_offset = get_cycles_sync();
298 offset = (this_offset - last_offset)*1000 / cpu_khz; 305 /* FIXME: 1000 or 1000000? */
306 offset = (this_offset - last_offset)*1000 / cpu_khz;
299 } 307 }
300 return base + offset; 308 return base + offset;
301} 309}
@@ -380,7 +388,7 @@ void main_timer_handler(struct pt_regs *regs)
380 } 388 }
381 389
382 monotonic_base += 390 monotonic_base +=
383 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; 391 (offset - vxtime.last) * NSEC_PER_TICK / hpet_tick;
384 392
385 vxtime.last = offset; 393 vxtime.last = offset;
386#ifdef CONFIG_X86_PM_TIMER 394#ifdef CONFIG_X86_PM_TIMER
@@ -389,24 +397,25 @@ void main_timer_handler(struct pt_regs *regs)
389#endif 397#endif
390 } else { 398 } else {
391 offset = (((tsc - vxtime.last_tsc) * 399 offset = (((tsc - vxtime.last_tsc) *
392 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ); 400 vxtime.tsc_quot) >> US_SCALE) - USEC_PER_TICK;
393 401
394 if (offset < 0) 402 if (offset < 0)
395 offset = 0; 403 offset = 0;
396 404
397 if (offset > (USEC_PER_SEC / HZ)) { 405 if (offset > USEC_PER_TICK) {
398 lost = offset / (USEC_PER_SEC / HZ); 406 lost = offset / USEC_PER_TICK;
399 offset %= (USEC_PER_SEC / HZ); 407 offset %= USEC_PER_TICK;
400 } 408 }
401 409
402 monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ; 410 /* FIXME: 1000 or 1000000? */
411 monotonic_base += (tsc - vxtime.last_tsc) * 1000000 / cpu_khz;
403 412
404 vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot; 413 vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
405 414
406 if ((((tsc - vxtime.last_tsc) * 415 if ((((tsc - vxtime.last_tsc) *
407 vxtime.tsc_quot) >> 32) < offset) 416 vxtime.tsc_quot) >> US_SCALE) < offset)
408 vxtime.last_tsc = tsc - 417 vxtime.last_tsc = tsc -
409 (((long) offset << 32) / vxtime.tsc_quot) - 1; 418 (((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
410 } 419 }
411 420
412 if (lost > 0) { 421 if (lost > 0) {
@@ -466,16 +475,15 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
466} 475}
467 476
468static unsigned int cyc2ns_scale __read_mostly; 477static unsigned int cyc2ns_scale __read_mostly;
469#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
470 478
471static inline void set_cyc2ns_scale(unsigned long cpu_khz) 479static inline void set_cyc2ns_scale(unsigned long cpu_khz)
472{ 480{
473 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; 481 cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / cpu_khz;
474} 482}
475 483
476static inline unsigned long long cycles_2_ns(unsigned long long cyc) 484static inline unsigned long long cycles_2_ns(unsigned long long cyc)
477{ 485{
478 return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; 486 return (cyc * cyc2ns_scale) >> NS_SCALE;
479} 487}
480 488
481unsigned long long sched_clock(void) 489unsigned long long sched_clock(void)
@@ -488,7 +496,7 @@ unsigned long long sched_clock(void)
488 Disadvantage is a small drift between CPUs in some configurations, 496 Disadvantage is a small drift between CPUs in some configurations,
489 but that should be tolerable. */ 497 but that should be tolerable. */
490 if (__vxtime.mode == VXTIME_HPET) 498 if (__vxtime.mode == VXTIME_HPET)
491 return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> 32; 499 return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> US_SCALE;
492#endif 500#endif
493 501
494 /* Could do CPU core sync here. Opteron can execute rdtsc speculatively, 502 /* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
@@ -631,7 +639,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
631 639
632 cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); 640 cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
633 if (!(freq->flags & CPUFREQ_CONST_LOOPS)) 641 if (!(freq->flags & CPUFREQ_CONST_LOOPS))
634 vxtime.tsc_quot = (1000L << 32) / cpu_khz; 642 vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
635 } 643 }
636 644
637 set_cyc2ns_scale(cpu_khz_ref); 645 set_cyc2ns_scale(cpu_khz_ref);
@@ -823,8 +831,7 @@ static int hpet_init(void)
823 if (hpet_period < 100000 || hpet_period > 100000000) 831 if (hpet_period < 100000 || hpet_period > 100000000)
824 return -1; 832 return -1;
825 833
826 hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) / 834 hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
827 hpet_period;
828 835
829 hpet_use_timer = (id & HPET_ID_LEGSUP); 836 hpet_use_timer = (id & HPET_ID_LEGSUP);
830 837
@@ -898,7 +905,7 @@ void __init time_init(void)
898 -xtime.tv_sec, -xtime.tv_nsec); 905 -xtime.tv_sec, -xtime.tv_nsec);
899 906
900 if (!hpet_init()) 907 if (!hpet_init())
901 vxtime_hz = (1000000000000000L + hpet_period / 2) / hpet_period; 908 vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period;
902 else 909 else
903 vxtime.hpet_address = 0; 910 vxtime.hpet_address = 0;
904 911
@@ -927,8 +934,8 @@ void __init time_init(void)
927 vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod); 934 vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
928 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", 935 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
929 cpu_khz / 1000, cpu_khz % 1000); 936 cpu_khz / 1000, cpu_khz % 1000);
930 vxtime.quot = (1000000L << 32) / vxtime_hz; 937 vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
931 vxtime.tsc_quot = (1000L << 32) / cpu_khz; 938 vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
932 vxtime.last_tsc = get_cycles_sync(); 939 vxtime.last_tsc = get_cycles_sync();
933 setup_irq(0, &irq0); 940 setup_irq(0, &irq0);
934 941