aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/tsc.c')
-rw-r--r--arch/x86/kernel/tsc.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 6dbf0bcb44a8..ee01cd96b5e1 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -32,6 +32,7 @@ static int tsc_unstable;
32 erroneous rdtsc usage on !cpu_has_tsc processors */ 32 erroneous rdtsc usage on !cpu_has_tsc processors */
33static int tsc_disabled = -1; 33static int tsc_disabled = -1;
34 34
35static int tsc_clocksource_reliable;
35/* 36/*
36 * Scheduler clock - returns current time in nanosec units. 37 * Scheduler clock - returns current time in nanosec units.
37 */ 38 */
@@ -99,6 +100,15 @@ int __init notsc_setup(char *str)
99 100
100__setup("notsc", notsc_setup); 101__setup("notsc", notsc_setup);
101 102
103static int __init tsc_setup(char *str)
104{
105 if (!strcmp(str, "reliable"))
106 tsc_clocksource_reliable = 1;
107 return 1;
108}
109
110__setup("tsc=", tsc_setup);
111
102#define MAX_RETRIES 5 112#define MAX_RETRIES 5
103#define SMI_TRESHOLD 50000 113#define SMI_TRESHOLD 50000
104 114
@@ -738,24 +748,21 @@ static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
738 {} 748 {}
739}; 749};
740 750
741/* 751static void __init check_system_tsc_reliable(void)
742 * Geode_LX - the OLPC CPU has a possibly a very reliable TSC 752{
743 */
744#ifdef CONFIG_MGEODE_LX 753#ifdef CONFIG_MGEODE_LX
745/* RTSC counts during suspend */ 754 /* RTSC counts during suspend */
746#define RTSC_SUSP 0x100 755#define RTSC_SUSP 0x100
747
748static void __init check_geode_tsc_reliable(void)
749{
750 unsigned long res_low, res_high; 756 unsigned long res_low, res_high;
751 757
752 rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); 758 rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
759 /* Geode_LX - the OLPC CPU has a possibly a very reliable TSC */
753 if (res_low & RTSC_SUSP) 760 if (res_low & RTSC_SUSP)
754 clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; 761 tsc_clocksource_reliable = 1;
755}
756#else
757static inline void check_geode_tsc_reliable(void) { }
758#endif 762#endif
763 if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
764 tsc_clocksource_reliable = 1;
765}
759 766
760/* 767/*
761 * Make an educated guess if the TSC is trustworthy and synchronized 768 * Make an educated guess if the TSC is trustworthy and synchronized
@@ -790,6 +797,8 @@ static void __init init_tsc_clocksource(void)
790{ 797{
791 clocksource_tsc.mult = clocksource_khz2mult(tsc_khz, 798 clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
792 clocksource_tsc.shift); 799 clocksource_tsc.shift);
800 if (tsc_clocksource_reliable)
801 clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
793 /* lower the rating if we already know its unstable: */ 802 /* lower the rating if we already know its unstable: */
794 if (check_tsc_unstable()) { 803 if (check_tsc_unstable()) {
795 clocksource_tsc.rating = 0; 804 clocksource_tsc.rating = 0;
@@ -850,7 +859,7 @@ void __init tsc_init(void)
850 if (unsynchronized_tsc()) 859 if (unsynchronized_tsc())
851 mark_tsc_unstable("TSCs unsynchronized"); 860 mark_tsc_unstable("TSCs unsynchronized");
852 861
853 check_geode_tsc_reliable(); 862 check_system_tsc_reliable();
854 init_tsc_clocksource(); 863 init_tsc_clocksource();
855} 864}
856 865