aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/time.c')
-rw-r--r--arch/x86_64/kernel/time.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 0e3b60e1ac5b..fb8c809b4cd9 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -26,6 +26,10 @@
26#include <linux/sysdev.h> 26#include <linux/sysdev.h>
27#include <linux/bcd.h> 27#include <linux/bcd.h>
28#include <linux/kallsyms.h> 28#include <linux/kallsyms.h>
29#include <linux/acpi.h>
30#ifdef CONFIG_ACPI
31#include <acpi/achware.h> /* for PM timer frequency */
32#endif
29#include <asm/8253pit.h> 33#include <asm/8253pit.h>
30#include <asm/pgtable.h> 34#include <asm/pgtable.h>
31#include <asm/vsyscall.h> 35#include <asm/vsyscall.h>
@@ -396,6 +400,10 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
396 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; 400 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
397 401
398 vxtime.last = offset; 402 vxtime.last = offset;
403#ifdef CONFIG_X86_PM_TIMER
404 } else if (vxtime.mode == VXTIME_PMTMR) {
405 lost = pmtimer_mark_offset();
406#endif
399 } else { 407 } else {
400 offset = (((tsc - vxtime.last_tsc) * 408 offset = (((tsc - vxtime.last_tsc) *
401 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ); 409 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -898,6 +906,13 @@ void __init time_init(void)
898 hpet_period; 906 hpet_period;
899 cpu_khz = hpet_calibrate_tsc(); 907 cpu_khz = hpet_calibrate_tsc();
900 timename = "HPET"; 908 timename = "HPET";
909#ifdef CONFIG_X86_PM_TIMER
910 } else if (pmtmr_ioport) {
911 vxtime_hz = PM_TIMER_FREQUENCY;
912 timename = "PM";
913 pit_init();
914 cpu_khz = pit_calibrate_tsc();
915#endif
901 } else { 916 } else {
902 pit_init(); 917 pit_init();
903 cpu_khz = pit_calibrate_tsc(); 918 cpu_khz = pit_calibrate_tsc();
@@ -923,35 +938,50 @@ void __init time_init(void)
923} 938}
924 939
925/* 940/*
941 * Make an educated guess if the TSC is trustworthy and synchronized
942 * over all CPUs.
943 */
944static __init int unsynchronized_tsc(void)
945{
946#ifdef CONFIG_SMP
947 if (oem_force_hpet_timer())
948 return 1;
949 /* Intel systems are normally all synchronized. Exceptions
950 are handled in the OEM check above. */
951 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
952 return 0;
953 /* All in a single socket - should be synchronized */
954 if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
955 return 0;
956#endif
957 /* Assume multi socket systems are not synchronized */
958 return num_online_cpus() > 1;
959}
960
961/*
926 * Decide after all CPUs are booted what mode gettimeofday should use. 962 * Decide after all CPUs are booted what mode gettimeofday should use.
927 */ 963 */
928void __init time_init_gtod(void) 964void __init time_init_gtod(void)
929{ 965{
930 char *timetype; 966 char *timetype;
931 967
932 /* 968 if (unsynchronized_tsc())
933 * AMD systems with more than one CPU don't have fully synchronized
934 * TSCs. Always use HPET gettimeofday for these, although it is slower.
935 * Intel SMP systems usually have synchronized TSCs, so use always
936 * the TSC.
937 *
938 * Exceptions:
939 * IBM Summit2 checked by oem_force_hpet_timer().
940 * AMD dual core may also not need HPET. Check me.
941 *
942 * Can be turned off with "notsc".
943 */
944 if (num_online_cpus() > 1 &&
945 boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
946 notsc = 1;
947 /* Some systems will want to disable TSC and use HPET. */
948 if (oem_force_hpet_timer())
949 notsc = 1; 969 notsc = 1;
950 if (vxtime.hpet_address && notsc) { 970 if (vxtime.hpet_address && notsc) {
951 timetype = "HPET"; 971 timetype = "HPET";
952 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; 972 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
953 vxtime.mode = VXTIME_HPET; 973 vxtime.mode = VXTIME_HPET;
954 do_gettimeoffset = do_gettimeoffset_hpet; 974 do_gettimeoffset = do_gettimeoffset_hpet;
975#ifdef CONFIG_X86_PM_TIMER
976 /* Using PM for gettimeofday is quite slow, but we have no other
977 choice because the TSC is too unreliable on some systems. */
978 } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
979 timetype = "PM";
980 do_gettimeoffset = do_gettimeoffset_pm;
981 vxtime.mode = VXTIME_PMTMR;
982 sysctl_vsyscall = 0;
983 printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
984#endif
955 } else { 985 } else {
956 timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC"; 986 timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
957 vxtime.mode = VXTIME_TSC; 987 vxtime.mode = VXTIME_TSC;