[PATCH] Add initalization of the RDTSCP auxilliary values
authorVojtech Pavlik <vojtech@suse.cz>
Tue, 26 Sep 2006 08:52:28 +0000 (10:52 +0200)
committerAndi Kleen <andi@basil.nowhere.org>
Tue, 26 Sep 2006 08:52:28 +0000 (10:52 +0200)
This patch adds initalization of the RDTSCP auxilliary values to CPU numbers
to time.c. If RDTSCP is available, the MSRs are written with the respective
values. It can be later used to initalize per-cpu timekeeping variables.

AK: Some cleanups. Move externs into headers and fix CPU hotplug.

Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
Signed-off-by: Andi Kleen <ak@suse.de>
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/time.c
include/asm-x86_64/proto.h

index 15555879ce95e709025b97347110df7604f3f14a..582896f7d4207bb2abcc53be07b77d07b75b4140 100644 (file)
@@ -1181,6 +1181,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
 #endif
 
        check_nmi_watchdog();
+
+       time_init_gtod();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index 7a9b18224182ced7cd0932b2691249c69f70e4ad..97b9e46d1992e87632c69ca0bc0e633ec735f084 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/bcd.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <linux/kallsyms.h>
 #include <linux/acpi.h>
 #ifdef CONFIG_ACPI
@@ -49,7 +51,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);
@@ -893,11 +895,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;
 
@@ -931,18 +943,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 *)(long)smp_processor_id());
+
+#ifndef CONFIG_SMP
+       time_init_gtod();
+#endif
 }
 
 /*
@@ -973,12 +986,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)
@@ -1001,7 +1015,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);
index 038fe1f47e6fcb5804a5878270614289f545d9d4..3b1c6024790212674ccc47b4fe8eedabb6156661 100644 (file)
@@ -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);