diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 7 | ||||
-rw-r--r-- | arch/x86/kernel/tsc.c | 33 |
2 files changed, 28 insertions, 12 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1bbcaa8982b6..dc6b06f67fca 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -2267,6 +2267,13 @@ and is between 256 and 4096 characters. It is defined in the file | |||
2267 | Format: | 2267 | Format: |
2268 | <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq> | 2268 | <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq> |
2269 | 2269 | ||
2270 | tsc= Disable clocksource-must-verify flag for TSC. | ||
2271 | Format: <string> | ||
2272 | [x86] reliable: mark tsc clocksource as reliable, this | ||
2273 | disables clocksource verification at runtime. | ||
2274 | Used to enable high-resolution timer mode on older | ||
2275 | hardware, and in virtualized environment. | ||
2276 | |||
2270 | turbografx.map[2|3]= [HW,JOY] | 2277 | turbografx.map[2|3]= [HW,JOY] |
2271 | TurboGraFX parallel port interface | 2278 | TurboGraFX parallel port interface |
2272 | Format: | 2279 | Format: |
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 */ |
33 | static int tsc_disabled = -1; | 33 | static int tsc_disabled = -1; |
34 | 34 | ||
35 | static 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 | ||
103 | static 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 | /* | 751 | static 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 | |||
748 | static 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 | ||
757 | static 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 | ||