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 | ||
