aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/tsc.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-07-17 21:37:04 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-07-18 11:47:42 -0400
commit688340ea34c61ad12473ccd837325b59aada9a93 (patch)
tree2862f4dca8d47fc4e6ecfaba2243d813344e3cd2 /arch/i386/kernel/tsc.c
parentd572929cdd12a60732c3522f7cf011bfa29165cf (diff)
Add a sched_clock paravirt_op
The tsc-based get_scheduled_cycles interface is not a good match for Xen's runstate accounting, which reports everything in nanoseconds. This patch replaces this interface with a sched_clock interface, which matches both Xen and VMI's requirements. In order to do this, we: 1. replace get_scheduled_cycles with sched_clock 2. hoist cycles_2_ns into a common header 3. update vmi accordingly One thing to note: because sched_clock is implemented as a weak function in kernel/sched.c, we must define a real function in order to override this weak binding. This means the usual paravirt_ops technique of using an inline function won't work in this case. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Zachary Amsden <zach@vmware.com> Cc: Dan Hecht <dhecht@vmware.com> Cc: john stultz <johnstul@us.ibm.com>
Diffstat (limited to 'arch/i386/kernel/tsc.c')
-rw-r--r--arch/i386/kernel/tsc.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index ea63a30ca3e8..252f9010f283 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -84,7 +84,7 @@ static inline int check_tsc_unstable(void)
84 * 84 *
85 * -johnstul@us.ibm.com "math is hard, lets go shopping!" 85 * -johnstul@us.ibm.com "math is hard, lets go shopping!"
86 */ 86 */
87static unsigned long cyc2ns_scale __read_mostly; 87unsigned long cyc2ns_scale __read_mostly;
88 88
89#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ 89#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
90 90
@@ -93,15 +93,10 @@ static inline void set_cyc2ns_scale(unsigned long cpu_khz)
93 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; 93 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
94} 94}
95 95
96static inline unsigned long long cycles_2_ns(unsigned long long cyc)
97{
98 return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
99}
100
101/* 96/*
102 * Scheduler clock - returns current time in nanosec units. 97 * Scheduler clock - returns current time in nanosec units.
103 */ 98 */
104unsigned long long sched_clock(void) 99unsigned long long native_sched_clock(void)
105{ 100{
106 unsigned long long this_offset; 101 unsigned long long this_offset;
107 102
@@ -118,12 +113,24 @@ unsigned long long sched_clock(void)
118 return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); 113 return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
119 114
120 /* read the Time Stamp Counter: */ 115 /* read the Time Stamp Counter: */
121 get_scheduled_cycles(this_offset); 116 rdtscll(this_offset);
122 117
123 /* return the value in ns */ 118 /* return the value in ns */
124 return cycles_2_ns(this_offset); 119 return cycles_2_ns(this_offset);
125} 120}
126 121
122/* We need to define a real function for sched_clock, to override the
123 weak default version */
124#ifdef CONFIG_PARAVIRT
125unsigned long long sched_clock(void)
126{
127 return paravirt_sched_clock();
128}
129#else
130unsigned long long sched_clock(void)
131 __attribute__((alias("native_sched_clock")));
132#endif
133
127unsigned long native_calculate_cpu_khz(void) 134unsigned long native_calculate_cpu_khz(void)
128{ 135{
129 unsigned long long start, end; 136 unsigned long long start, end;