diff options
| -rw-r--r-- | Documentation/kernel-parameters.txt | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 96 |
2 files changed, 96 insertions, 9 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d6496fde6180..f3dc951e949f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -2461,12 +2461,13 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 2461 | to facilitate early boot debugging. | 2461 | to facilitate early boot debugging. |
| 2462 | See also Documentation/trace/events.txt | 2462 | See also Documentation/trace/events.txt |
| 2463 | 2463 | ||
| 2464 | tsc= Disable clocksource-must-verify flag for TSC. | 2464 | tsc= Disable clocksource stability checks for TSC. |
| 2465 | Format: <string> | 2465 | Format: <string> |
| 2466 | [x86] reliable: mark tsc clocksource as reliable, this | 2466 | [x86] reliable: mark tsc clocksource as reliable, this |
| 2467 | disables clocksource verification at runtime. | 2467 | disables clocksource verification at runtime, as well |
| 2468 | Used to enable high-resolution timer mode on older | 2468 | as the stability checks done at bootup. Used to enable |
| 2469 | hardware, and in virtualized environment. | 2469 | high-resolution timer mode on older hardware, and in |
| 2470 | virtualized environment. | ||
| 2470 | [x86] noirqtime: Do not use TSC to do irq accounting. | 2471 | [x86] noirqtime: Do not use TSC to do irq accounting. |
| 2471 | Used to run time disable IRQ_TIME_ACCOUNTING on any | 2472 | Used to run time disable IRQ_TIME_ACCOUNTING on any |
| 2472 | platforms where RDTSC is slow and this accounting | 2473 | platforms where RDTSC is slow and this accounting |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 0c40d8b72416..356a0d455cf9 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -872,6 +872,9 @@ __cpuinit int unsynchronized_tsc(void) | |||
| 872 | 872 | ||
| 873 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 873 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
| 874 | return 0; | 874 | return 0; |
| 875 | |||
| 876 | if (tsc_clocksource_reliable) | ||
| 877 | return 0; | ||
| 875 | /* | 878 | /* |
| 876 | * Intel systems are normally all synchronized. | 879 | * Intel systems are normally all synchronized. |
| 877 | * Exceptions must mark TSC as unstable: | 880 | * Exceptions must mark TSC as unstable: |
| @@ -879,14 +882,92 @@ __cpuinit int unsynchronized_tsc(void) | |||
| 879 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { | 882 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { |
| 880 | /* assume multi socket systems are not synchronized: */ | 883 | /* assume multi socket systems are not synchronized: */ |
| 881 | if (num_possible_cpus() > 1) | 884 | if (num_possible_cpus() > 1) |
| 882 | tsc_unstable = 1; | 885 | return 1; |
| 883 | } | 886 | } |
| 884 | 887 | ||
| 885 | return tsc_unstable; | 888 | return 0; |
| 889 | } | ||
| 890 | |||
| 891 | |||
| 892 | static void tsc_refine_calibration_work(struct work_struct *work); | ||
| 893 | static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work); | ||
| 894 | /** | ||
| 895 | * tsc_refine_calibration_work - Further refine tsc freq calibration | ||
| 896 | * @work - ignored. | ||
| 897 | * | ||
| 898 | * This functions uses delayed work over a period of a | ||
| 899 | * second to further refine the TSC freq value. Since this is | ||
| 900 | * timer based, instead of loop based, we don't block the boot | ||
| 901 | * process while this longer calibration is done. | ||
| 902 | * | ||
| 903 | * If there are any calibration anomolies (too many SMIs, etc), | ||
| 904 | * or the refined calibration is off by 1% of the fast early | ||
| 905 | * calibration, we throw out the new calibration and use the | ||
| 906 | * early calibration. | ||
| 907 | */ | ||
| 908 | static void tsc_refine_calibration_work(struct work_struct *work) | ||
| 909 | { | ||
| 910 | static u64 tsc_start = -1, ref_start; | ||
| 911 | static int hpet; | ||
| 912 | u64 tsc_stop, ref_stop, delta; | ||
| 913 | unsigned long freq; | ||
| 914 | |||
| 915 | /* Don't bother refining TSC on unstable systems */ | ||
| 916 | if (check_tsc_unstable()) | ||
| 917 | goto out; | ||
| 918 | |||
| 919 | /* | ||
| 920 | * Since the work is started early in boot, we may be | ||
| 921 | * delayed the first time we expire. So set the workqueue | ||
| 922 | * again once we know timers are working. | ||
| 923 | */ | ||
| 924 | if (tsc_start == -1) { | ||
| 925 | /* | ||
| 926 | * Only set hpet once, to avoid mixing hardware | ||
| 927 | * if the hpet becomes enabled later. | ||
| 928 | */ | ||
| 929 | hpet = is_hpet_enabled(); | ||
| 930 | schedule_delayed_work(&tsc_irqwork, HZ); | ||
| 931 | tsc_start = tsc_read_refs(&ref_start, hpet); | ||
| 932 | return; | ||
| 933 | } | ||
| 934 | |||
| 935 | tsc_stop = tsc_read_refs(&ref_stop, hpet); | ||
| 936 | |||
| 937 | /* hpet or pmtimer available ? */ | ||
| 938 | if (!hpet && !ref_start && !ref_stop) | ||
| 939 | goto out; | ||
| 940 | |||
| 941 | /* Check, whether the sampling was disturbed by an SMI */ | ||
| 942 | if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX) | ||
| 943 | goto out; | ||
| 944 | |||
| 945 | delta = tsc_stop - tsc_start; | ||
| 946 | delta *= 1000000LL; | ||
| 947 | if (hpet) | ||
| 948 | freq = calc_hpet_ref(delta, ref_start, ref_stop); | ||
| 949 | else | ||
| 950 | freq = calc_pmtimer_ref(delta, ref_start, ref_stop); | ||
| 951 | |||
| 952 | /* Make sure we're within 1% */ | ||
| 953 | if (abs(tsc_khz - freq) > tsc_khz/100) | ||
| 954 | goto out; | ||
| 955 | |||
| 956 | tsc_khz = freq; | ||
| 957 | printk(KERN_INFO "Refined TSC clocksource calibration: " | ||
| 958 | "%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000, | ||
| 959 | (unsigned long)tsc_khz % 1000); | ||
| 960 | |||
| 961 | out: | ||
| 962 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | ||
| 886 | } | 963 | } |
| 887 | 964 | ||
| 888 | static void __init init_tsc_clocksource(void) | 965 | |
| 966 | static int __init init_tsc_clocksource(void) | ||
| 889 | { | 967 | { |
| 968 | if (!cpu_has_tsc || tsc_disabled > 0) | ||
| 969 | return 0; | ||
| 970 | |||
| 890 | if (tsc_clocksource_reliable) | 971 | if (tsc_clocksource_reliable) |
| 891 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | 972 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; |
| 892 | /* lower the rating if we already know its unstable: */ | 973 | /* lower the rating if we already know its unstable: */ |
| @@ -894,8 +975,14 @@ static void __init init_tsc_clocksource(void) | |||
| 894 | clocksource_tsc.rating = 0; | 975 | clocksource_tsc.rating = 0; |
| 895 | clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; | 976 | clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; |
| 896 | } | 977 | } |
| 897 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | 978 | schedule_delayed_work(&tsc_irqwork, 0); |
| 979 | return 0; | ||
| 898 | } | 980 | } |
| 981 | /* | ||
| 982 | * We use device_initcall here, to ensure we run after the hpet | ||
| 983 | * is fully initialized, which may occur at fs_initcall time. | ||
| 984 | */ | ||
| 985 | device_initcall(init_tsc_clocksource); | ||
| 899 | 986 | ||
| 900 | void __init tsc_init(void) | 987 | void __init tsc_init(void) |
| 901 | { | 988 | { |
| @@ -949,6 +1036,5 @@ void __init tsc_init(void) | |||
| 949 | mark_tsc_unstable("TSCs unsynchronized"); | 1036 | mark_tsc_unstable("TSCs unsynchronized"); |
| 950 | 1037 | ||
| 951 | check_system_tsc_reliable(); | 1038 | check_system_tsc_reliable(); |
| 952 | init_tsc_clocksource(); | ||
| 953 | } | 1039 | } |
| 954 | 1040 | ||
