File linux-2.6-x86-support-rdtscp-for-gtod.patch of Package kernel
Date: Mon, 02 Oct 2006 16:15:54 -0400
From: Bhavana Nagendra <bnagendr@redhat.com>
Subject: Re: [RHEL 5 NEW PATCH] : Adding support for RDTSCP and vgetcpu syscall
--- linux-2.6.17.x86_64/arch/x86_64/kernel/time.c.orig 2006-10-02 15:56:53.000000000 -0400
+++ linux-2.6.17.x86_64/arch/x86_64/kernel/time.c 2006-10-02 16:10:28.000000000 -0400
@@ -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,22 @@ 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 +944,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
}
/*
@@ -962,6 +976,11 @@ __cpuinit int unsynchronized_tsc(void)
/* But TSC doesn't tick in C3 so don't use it there */
if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
return 1;
+
+ /* AMD systems with constant TSCs have synchronized clocks */
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+ (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)))
+ return 0;
#endif
return 0;
}
@@ -973,12 +992,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 +1021,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);
--- linux-2.6.17.x86_64/arch/x86_64/kernel/smpboot.c.orig 2006-10-02 15:56:47.000000000 -0400
+++ linux-2.6.17.x86_64/arch/x86_64/kernel/smpboot.c 2006-10-02 15:57:07.000000000 -0400
@@ -1181,6 +1181,8 @@ void __init smp_cpus_done(unsigned int m
#endif
check_nmi_watchdog();
+
+ time_init_gtod();
}
#ifdef CONFIG_HOTPLUG_CPU
--- linux-2.6.17.x86_64/include/asm-x86_64/proto.h.orig 2006-10-02 15:56:36.000000000 -0400
+++ linux-2.6.17.x86_64/include/asm-x86_64/proto.h 2006-10-02 15:57:07.000000000 -0400
@@ -49,6 +49,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);
--- linux-2.6.17.x86_64/include/asm-x86_64/msr.h.orig 2006-10-02 15:56:42.000000000 -0400
+++ linux-2.6.17.x86_64/include/asm-x86_64/msr.h 2006-10-02 16:05:22.000000000 -0400
@@ -66,14 +66,25 @@
#define rdtscl(low) \
__asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
+#define rdtscp(low,high,aux) \
+ asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux))
+
#define rdtscll(val) do { \
unsigned int __a,__d; \
asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
(val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
} while(0)
+#define rdtscpll(val, aux) do { \
+ unsigned long __a, __d; \
+ asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (__a), "=d" (__d), "=c" (aux)); \
+ (val) = (__d << 32) | __a; \
+} while (0)
+
#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
+#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
+
#define rdpmc(counter,low,high) \
__asm__ __volatile__("rdpmc" \
: "=a" (low), "=d" (high) \