Signed-off-by: Andrew Morton --- arch/x86_64/kernel/smpboot.c | 2 + arch/x86_64/kernel/time.c | 47 ++++++++++++++++++++++++--------- include/asm-x86_64/proto.h | 1 3 files changed, 38 insertions(+), 12 deletions(-) diff -puN arch/x86_64/kernel/smpboot.c~x86_64-mm-init-rdtscp arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c~x86_64-mm-init-rdtscp +++ a/arch/x86_64/kernel/smpboot.c @@ -1183,6 +1183,8 @@ void __init smp_cpus_done(unsigned int m #endif check_nmi_watchdog(); + + time_init_gtod(); } #ifdef CONFIG_HOTPLUG_CPU diff -puN arch/x86_64/kernel/time.c~x86_64-mm-init-rdtscp arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c~x86_64-mm-init-rdtscp +++ a/arch/x86_64/kernel/time.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #ifdef CONFIG_ACPI @@ -48,7 +50,7 @@ static void cpufreq_delayed_get(void); extern void i8254_timer_resume(void); extern int using_apic_timer; -static char *time_init_gtod(void); +static char *timename = NULL; DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); @@ -892,11 +894,21 @@ static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; -void __init time_init(void) +static int __cpuinit +time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu) { - char *timename; - char *gtod; + unsigned cpu = (unsigned long) hcpu; + if (action == CPU_ONLINE && + cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) { + unsigned p; + p = smp_processor_id() | (cpu_to_node(smp_processor_id())<<12); + write_rdtscp_aux(p); + } + return NOTIFY_DONE; +} +void __init time_init(void) +{ if (nohpet) vxtime.hpet_address = 0; @@ -930,18 +942,19 @@ void __init time_init(void) } vxtime.mode = VXTIME_TSC; - gtod = time_init_gtod(); - - printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n", - vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod); - printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", - cpu_khz / 1000, cpu_khz % 1000); vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz; vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz; vxtime.last_tsc = get_cycles_sync(); setup_irq(0, &irq0); set_cyc2ns_scale(cpu_khz); + + hotcpu_notifier(time_cpu_notifier, 0); + time_cpu_notifier(NULL, CPU_ONLINE, (void *)smp_processor_id()); + +#ifndef CONFIG_SMP + time_init_gtod(); +#endif } /* @@ -965,12 +978,13 @@ __cpuinit int unsynchronized_tsc(void) /* * Decide what mode gettimeofday should use. */ -__init static char *time_init_gtod(void) +void time_init_gtod(void) { char *timetype; if (unsynchronized_tsc()) notsc = 1; + if (vxtime.hpet_address && notsc) { timetype = hpet_use_timer ? "HPET" : "PIT/HPET"; if (hpet_use_timer) @@ -993,7 +1007,16 @@ __init static char *time_init_gtod(void) timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC"; vxtime.mode = VXTIME_TSC; } - return timetype; + + printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n", + vxtime_hz / 1000000, vxtime_hz % 1000000, timename, timetype); + printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", + cpu_khz / 1000, cpu_khz % 1000); + vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz; + vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz; + vxtime.last_tsc = get_cycles_sync(); + + set_cyc2ns_scale(cpu_khz); } __setup("report_lost_ticks", time_setup); diff -puN include/asm-x86_64/proto.h~x86_64-mm-init-rdtscp include/asm-x86_64/proto.h --- a/include/asm-x86_64/proto.h~x86_64-mm-init-rdtscp +++ a/include/asm-x86_64/proto.h @@ -51,6 +51,7 @@ extern unsigned long long monotonic_base extern int sysctl_vsyscall; extern int nohpet; extern unsigned long vxtime_hz; +extern void time_init_gtod(void); extern int numa_setup(char *opt); _