Alok Kataria | 0ef9553 | 2008-07-01 11:43:18 -0700 | [diff] [blame^] | 1 | #include <linux/sched.h> |
| 2 | #include <linux/init.h> |
| 3 | #include <linux/module.h> |
| 4 | #include <linux/timer.h> |
| 5 | |
| 6 | unsigned int cpu_khz; /* TSC clocks / usec, not used here */ |
| 7 | EXPORT_SYMBOL(cpu_khz); |
| 8 | unsigned int tsc_khz; |
| 9 | EXPORT_SYMBOL(tsc_khz); |
| 10 | |
| 11 | /* |
| 12 | * TSC can be unstable due to cpufreq or due to unsynced TSCs |
| 13 | */ |
| 14 | int tsc_unstable; |
| 15 | |
| 16 | /* native_sched_clock() is called before tsc_init(), so |
| 17 | we must start with the TSC soft disabled to prevent |
| 18 | erroneous rdtsc usage on !cpu_has_tsc processors */ |
| 19 | int tsc_disabled = -1; |
| 20 | |
| 21 | /* |
| 22 | * Scheduler clock - returns current time in nanosec units. |
| 23 | */ |
| 24 | u64 native_sched_clock(void) |
| 25 | { |
| 26 | u64 this_offset; |
| 27 | |
| 28 | /* |
| 29 | * Fall back to jiffies if there's no TSC available: |
| 30 | * ( But note that we still use it if the TSC is marked |
| 31 | * unstable. We do this because unlike Time Of Day, |
| 32 | * the scheduler clock tolerates small errors and it's |
| 33 | * very important for it to be as fast as the platform |
| 34 | * can achive it. ) |
| 35 | */ |
| 36 | if (unlikely(tsc_disabled)) { |
| 37 | /* No locking but a rare wrong value is not a big deal: */ |
| 38 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); |
| 39 | } |
| 40 | |
| 41 | /* read the Time Stamp Counter: */ |
| 42 | rdtscll(this_offset); |
| 43 | |
| 44 | /* return the value in ns */ |
| 45 | return cycles_2_ns(this_offset); |
| 46 | } |
| 47 | |
| 48 | /* We need to define a real function for sched_clock, to override the |
| 49 | weak default version */ |
| 50 | #ifdef CONFIG_PARAVIRT |
| 51 | unsigned long long sched_clock(void) |
| 52 | { |
| 53 | return paravirt_sched_clock(); |
| 54 | } |
| 55 | #else |
| 56 | unsigned long long |
| 57 | sched_clock(void) __attribute__((alias("native_sched_clock"))); |
| 58 | #endif |
| 59 | |
| 60 | int check_tsc_unstable(void) |
| 61 | { |
| 62 | return tsc_unstable; |
| 63 | } |
| 64 | EXPORT_SYMBOL_GPL(check_tsc_unstable); |
| 65 | |
| 66 | #ifdef CONFIG_X86_TSC |
| 67 | int __init notsc_setup(char *str) |
| 68 | { |
| 69 | printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " |
| 70 | "cannot disable TSC completely.\n"); |
| 71 | tsc_disabled = 1; |
| 72 | return 1; |
| 73 | } |
| 74 | #else |
| 75 | /* |
| 76 | * disable flag for tsc. Takes effect by clearing the TSC cpu flag |
| 77 | * in cpu/common.c |
| 78 | */ |
| 79 | int __init notsc_setup(char *str) |
| 80 | { |
| 81 | setup_clear_cpu_cap(X86_FEATURE_TSC); |
| 82 | return 1; |
| 83 | } |
| 84 | #endif |
| 85 | |
| 86 | __setup("notsc", notsc_setup); |