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.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index dba7237be5c1..3080f84bf7b7 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -48,6 +48,8 @@ static void cpufreq_delayed_get(void);
48extern void i8254_timer_resume(void); 48extern void i8254_timer_resume(void);
49extern int using_apic_timer; 49extern int using_apic_timer;
50 50
51static char *time_init_gtod(void);
52
51DEFINE_SPINLOCK(rtc_lock); 53DEFINE_SPINLOCK(rtc_lock);
52DEFINE_SPINLOCK(i8253_lock); 54DEFINE_SPINLOCK(i8253_lock);
53 55
@@ -59,7 +61,7 @@ static int notsc __initdata = 0;
59unsigned int cpu_khz; /* TSC clocks / usec, not used here */ 61unsigned int cpu_khz; /* TSC clocks / usec, not used here */
60static unsigned long hpet_period; /* fsecs / HPET clock */ 62static unsigned long hpet_period; /* fsecs / HPET clock */
61unsigned long hpet_tick; /* HPET clocks / interrupt */ 63unsigned long hpet_tick; /* HPET clocks / interrupt */
62static int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */ 64int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */
63unsigned long vxtime_hz = PIT_TICK_RATE; 65unsigned long vxtime_hz = PIT_TICK_RATE;
64int report_lost_ticks; /* command line option */ 66int report_lost_ticks; /* command line option */
65unsigned long long monotonic_base; 67unsigned long long monotonic_base;
@@ -326,7 +328,10 @@ static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
326 print_symbol("rip %s\n", regs->rip); 328 print_symbol("rip %s\n", regs->rip);
327 if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) { 329 if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
328 printk(KERN_WARNING "Falling back to HPET\n"); 330 printk(KERN_WARNING "Falling back to HPET\n");
329 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; 331 if (hpet_use_timer)
332 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
333 else
334 vxtime.last = hpet_readl(HPET_COUNTER);
330 vxtime.mode = VXTIME_HPET; 335 vxtime.mode = VXTIME_HPET;
331 do_gettimeoffset = do_gettimeoffset_hpet; 336 do_gettimeoffset = do_gettimeoffset_hpet;
332 } 337 }
@@ -898,6 +903,7 @@ static struct irqaction irq0 = {
898void __init time_init(void) 903void __init time_init(void)
899{ 904{
900 char *timename; 905 char *timename;
906 char *gtod;
901 907
902#ifdef HPET_HACK_ENABLE_DANGEROUS 908#ifdef HPET_HACK_ENABLE_DANGEROUS
903 if (!vxtime.hpet_address) { 909 if (!vxtime.hpet_address) {
@@ -942,21 +948,19 @@ void __init time_init(void)
942 timename = "PIT"; 948 timename = "PIT";
943 } 949 }
944 950
945 printk(KERN_INFO "time.c: Using %ld.%06ld MHz %s timer.\n", 951 vxtime.mode = VXTIME_TSC;
946 vxtime_hz / 1000000, vxtime_hz % 1000000, timename); 952 gtod = time_init_gtod();
953
954 printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
955 vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
947 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", 956 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
948 cpu_khz / 1000, cpu_khz % 1000); 957 cpu_khz / 1000, cpu_khz % 1000);
949 vxtime.mode = VXTIME_TSC;
950 vxtime.quot = (1000000L << 32) / vxtime_hz; 958 vxtime.quot = (1000000L << 32) / vxtime_hz;
951 vxtime.tsc_quot = (1000L << 32) / cpu_khz; 959 vxtime.tsc_quot = (1000L << 32) / cpu_khz;
952 vxtime.last_tsc = get_cycles_sync(); 960 vxtime.last_tsc = get_cycles_sync();
953 setup_irq(0, &irq0); 961 setup_irq(0, &irq0);
954 962
955 set_cyc2ns_scale(cpu_khz); 963 set_cyc2ns_scale(cpu_khz);
956
957#ifndef CONFIG_SMP
958 time_init_gtod();
959#endif
960} 964}
961 965
962/* 966/*
@@ -978,9 +982,9 @@ __cpuinit int unsynchronized_tsc(void)
978} 982}
979 983
980/* 984/*
981 * Decide after all CPUs are booted what mode gettimeofday should use. 985 * Decide what mode gettimeofday should use.
982 */ 986 */
983void __init time_init_gtod(void) 987__init static char *time_init_gtod(void)
984{ 988{
985 char *timetype; 989 char *timetype;
986 990
@@ -988,7 +992,10 @@ void __init time_init_gtod(void)
988 notsc = 1; 992 notsc = 1;
989 if (vxtime.hpet_address && notsc) { 993 if (vxtime.hpet_address && notsc) {
990 timetype = hpet_use_timer ? "HPET" : "PIT/HPET"; 994 timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
991 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; 995 if (hpet_use_timer)
996 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
997 else
998 vxtime.last = hpet_readl(HPET_COUNTER);
992 vxtime.mode = VXTIME_HPET; 999 vxtime.mode = VXTIME_HPET;
993 do_gettimeoffset = do_gettimeoffset_hpet; 1000 do_gettimeoffset = do_gettimeoffset_hpet;
994#ifdef CONFIG_X86_PM_TIMER 1001#ifdef CONFIG_X86_PM_TIMER
@@ -1005,8 +1012,7 @@ void __init time_init_gtod(void)
1005 timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC"; 1012 timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
1006 vxtime.mode = VXTIME_TSC; 1013 vxtime.mode = VXTIME_TSC;
1007 } 1014 }
1008 1015 return timetype;
1009 printk(KERN_INFO "time.c: Using %s based timekeeping.\n", timetype);
1010} 1016}
1011 1017
1012__setup("report_lost_ticks", time_setup); 1018__setup("report_lost_ticks", time_setup);
@@ -1321,8 +1327,7 @@ static int __init nohpet_setup(char *s)
1321 1327
1322__setup("nohpet", nohpet_setup); 1328__setup("nohpet", nohpet_setup);
1323 1329
1324 1330int __init notsc_setup(char *s)
1325static int __init notsc_setup(char *s)
1326{ 1331{
1327 notsc = 1; 1332 notsc = 1;
1328 return 0; 1333 return 0;