From: jbohac@suse.cz
To: Andi Kleen <ak@suse.de>
Cc: linux-kernel@vger.kernel.org, Jiri Bohac <jbohac@suse.cz>,
Vojtech Pavlik <vojtech@suse.cz>,
ssouhlal@freebsd.org, arjan@infradead.org, tglx@linutronix.de,
johnstul@us.ibm.com, zippel@linux-m68k.org, andrea@suse.de
Subject: [patch 7/9] Adapt the time initialization code
Date: Thu, 01 Feb 2007 10:59:59 +0100 [thread overview]
Message-ID: <20070201103754.041245000@jet.suse.cz> (raw)
In-Reply-To: 20070201095952.589234000@jet.suse.cz
[-- Attachment #1: time_init --]
[-- Type: text/plain, Size: 8230 bytes --]
We need to:
- initialize the RDTSCP instruction if available
- decide which hardware timer to use as MT (PM or HPET)
- decide what level of TSC->MT approximation to use
- none (as slow as the hardware MT can get) -- "notsc" option
- strictly monotonic (can't be done in a vsyscall) -- default
- unguaranteed monotonicity (very fast, vsyscall) -- "nomonotonic" option
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
Index: linux-2.6.20-rc5/arch/x86_64/kernel/smpboot.c
===================================================================
--- linux-2.6.20-rc5.orig/arch/x86_64/kernel/smpboot.c
+++ linux-2.6.20-rc5/arch/x86_64/kernel/smpboot.c
@@ -318,6 +318,8 @@ static inline void set_cpu_sibling_map(i
}
}
+extern void time_initialize_cpu(void);
+
/*
* Setup code on secondary processor (after comming out of the trampoline)
*/
@@ -345,6 +347,7 @@ void __cpuinit start_secondary(void)
enable_NMI_through_LVT0(NULL);
enable_8259A_irq(0);
}
+ time_initialize_cpu();
enable_APIC_timer();
@@ -963,6 +966,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
return err;
}
+extern void time_init_gtod(void);
+
/*
* Finish the SMP boot.
*/
Index: linux-2.6.20-rc5/arch/x86_64/kernel/time.c
===================================================================
--- linux-2.6.20-rc5.orig/arch/x86_64/kernel/time.c
+++ linux-2.6.20-rc5/arch/x86_64/kernel/time.c
@@ -968,6 +968,16 @@ static struct irqaction irq0 = {
timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
};
+static void time_init_rdtsc(void)
+{
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP)) {
+ int p;
+ p = smp_processor_id();
+ printk(KERN_INFO "Initializing RDTSCP feature on cpu %d.\n", p);
+ write_rdtscp_aux(p);
+ }
+}
+
void __init time_init(void)
{
if (nohpet)
@@ -979,27 +989,40 @@ void __init time_init(void)
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
- if (!hpet_init())
- vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period;
- else
- vxtime.hpet_address = 0;
+ /* decide what to use as Master Timer: HPET or PM? */
+ if (!hpet_init()) {
+ vxtime.mt_q = (hpet_period << 32) / FSEC_PER_NSEC;
+ mt_per_tick = hpet_use_timer ?
+ hpet_tick : LATCH * 12;
+ read_master_timer = read_master_timer_hpet;
+ timename = "HPET";
+ } else
+ if (pmtmr_ioport) {
+ vxtime.mt_q = (NSEC_PER_SEC << 32) / 916363636UL;
+ mt_per_tick = (LATCH * 3) << 8;
+ read_master_timer = read_master_timer_pm;
+ timename = "PM timer";
+ } else
+ panic("No suitable Master Timer found.\n");
- if (hpet_use_timer) {
- /* set tick_nsec to use the proper rate for HPET */
- tick_nsec = TICK_NSEC_HPET;
+ /* use PIT as main timer interrupt source if we can't use HPET */
+ if (hpet_use_timer)
cpu_khz = hpet_calibrate_tsc();
- timename = "HPET";
- } else {
+ else {
pit_init();
cpu_khz = pit_calibrate_tsc();
- timename = "PIT";
}
- vxtime.mode = VXTIME_TSC;
- 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);
+ /* initialize the master timer */
+ set_master_timer64(0);
+
+ /* initialize the timekeeping variables of the boot CPU */
+ vxtime.cpu[0].tsc_last = get_cycles_sync();
+ vxtime.cpu[0].mt_last = vxtime.cpu[0].mt_base = 0;
+ vxtime.cpu[0].tsc_slope = vxtime.cpu[0].tsc_slope_avg = (((USEC_PER_SEC << 32) / vxtime.mt_q) << TSC_SLOPE_SCALE) / cpu_khz;
+ time_init_rdtsc();
+
+ vxtime.mode = VXTIME_TSCS; /* not sure yet if CPUs have synced TSCs */
setup_irq(0, &irq0);
#ifndef CONFIG_SMP
@@ -1037,28 +1060,71 @@ __cpuinit int unsynchronized_tsc(void)
*/
void time_init_gtod(void)
{
- char *timetype;
-
- if (unsynchronized_tsc())
- notsc = 1;
+ char *tsc_method;
if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
vgetcpu_mode = VGETCPU_RDTSCP;
else
vgetcpu_mode = VGETCPU_LSL;
- timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
+ if (notsc) {
+ tsc_method = "nothing";
+ vxtime.mode = VXTIME_MT;
+ }
+ else if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP)) {
+ if (nomonotonic) {
+ tsc_method = "RDTSCP";
+ vxtime.mode = VXTIME_TSCP;
+ }
+ else {
+ tsc_method = "RDTSCM (syscall)";
+ vxtime.mode = VXTIME_TSCM;
+ }
+ }
+ else {
+ tsc_method = "RDTSC";
vxtime.mode = VXTIME_TSC;
+#ifdef CONFIG_SMP
+ if (unsynchronized_tsc()) {
+ if (nomonotonic) {
+ tsc_method = "RDTSC (syscall)";
+ vxtime.mode = VXTIME_TSCS;
+ }
+ else {
+ tsc_method = "RDTSCM (syscall)";
+ vxtime.mode = VXTIME_TSCM;
+ }
+ }
+#endif
+ }
+
- 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: Using %s as master timer, %s for time caching; vsyscall %s.\n",
+ timename, tsc_method, sysctl_vsyscall ? "enabled" : "disabled");
+ printk(KERN_INFO "time.c: Using %s as interrupt source.\n",
+ hpet_use_timer ? "HPET" : "PIT");
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);
+/*
+ * initialize the per_cpu timekeeping variables
+ * for non-boot CPUs
+ */
+void time_initialize_cpu(void *info)
+{
+ unsigned long flags;
+ int cpu = smp_processor_id();
+ u64 mt_now;
+ write_seqlock_irqsave(&xtime_lock, flags);
+ mt_now = get_master_timer64();
+ vxtime.cpu[cpu].tsc_last = get_cycles_sync();
+ vxtime.cpu[cpu].mt_last = mt_now;
+ vxtime.cpu[cpu].mt_base = mt_now;
+ vxtime.cpu[cpu].tsc_slope = vxtime.cpu[0].tsc_slope;
+ vxtime.cpu[cpu].tsc_slope_avg = vxtime.cpu[0].tsc_slope_avg;
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ time_init_rdtsc();
}
__setup("report_lost_ticks", time_setup);
@@ -1098,19 +1164,38 @@ static int timer_resume(struct sys_devic
sleep_length = 0;
ctime = sleep_start;
}
- if (vxtime.hpet_address)
+
+ write_seqlock_irqsave(&xtime_lock,flags);
+
+ /* reenable the Master Timer */
+ if (read_master_timer == read_master_timer_hpet || hpet_use_timer)
hpet_reenable();
+ /* reenable PIT if used as main timer interrupt source */
else
i8254_timer_resume();
sec = ctime + clock_cmos_diff;
- write_seqlock_irqsave(&xtime_lock,flags);
xtime.tv_sec = sec;
xtime.tv_nsec = 0;
- vxtime.last_tsc = get_cycles_sync();
- write_sequnlock_irqrestore(&xtime_lock,flags);
+
+ /* re-initialize the master timer */
+ add_master_timer64(sleep_length * mt_per_tick);
+ vxtime.mt_wall += sleep_length * mt_per_tick;
+
jiffies += sleep_length;
- monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
+
+ /* re-initialize the timekeeping variables of the boot CPU */
+ vxtime.cpu[0].tsc_last = get_cycles_sync();
+ vxtime.cpu[0].mt_last = vxtime.cpu[0].mt_base = get_master_timer64();
+ /* FIXME: what speed does the cpu really start at; I doubt cpu_khz is right at this point ??!!!
+ And what speed do the non-boot cpus start at? Their timekeeping variables will probably be set wrong
+ by copying from CPU 0 in time_initialize_cpu(); Not a great deal, as they will be synced somehow,
+ but not exactly nice -JB */
+ vxtime.cpu[0].tsc_slope = vxtime.cpu[0].tsc_slope_avg =
+ (((USEC_PER_SEC << 32) / vxtime.mt_q) << TSC_SLOPE_SCALE) / cpu_khz;
+
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
touch_softlockup_watchdog();
return 0;
}
@@ -1402,3 +1487,11 @@ int __init notsc_setup(char *s)
}
__setup("notsc", notsc_setup);
+
+int __init nomonotonic_setup(char *s)
+{
+ nomonotonic = 1;
+ return 1;
+}
+
+__setup("nomonotonic", nomonotonic_setup);
Index: linux-2.6.20-rc5/include/linux/time.h
===================================================================
--- linux-2.6.20-rc5.orig/include/linux/time.h
+++ linux-2.6.20-rc5/include/linux/time.h
@@ -31,6 +31,7 @@ struct timezone {
#define MSEC_PER_SEC 1000L
#define USEC_PER_MSEC 1000L
#define NSEC_PER_USEC 1000L
+#define FSEC_PER_NSEC 1000000L
#define NSEC_PER_MSEC 1000000L
#define USEC_PER_SEC 1000000L
#define NSEC_PER_SEC 1000000000L
--
next prev parent reply other threads:[~2007-02-01 11:29 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-01 9:59 [patch 0/9] x86_64: reliable TSC-based gettimeofday jbohac
2007-02-01 9:59 ` [patch 1/9] Fix HPET init race jbohac
2007-02-02 2:34 ` Andrew Morton
2007-02-06 16:44 ` Jiri Bohac
2007-02-07 0:12 ` Andrew Morton
2007-02-10 12:31 ` Andi Kleen
2007-07-26 20:58 ` Robin Holt
2007-02-01 9:59 ` [patch 2/9] Remove the support for the VXTIME_PMTMR timer mode jbohac
2007-02-01 11:13 ` Andi Kleen
2007-02-01 13:13 ` Jiri Bohac
2007-02-01 13:13 ` Andi Kleen
2007-02-01 13:59 ` Jiri Bohac
2007-02-01 14:18 ` Andi Kleen
2007-02-01 9:59 ` [patch 3/9] Remove the support for the VXTIME_HPET " jbohac
2007-02-01 9:59 ` [patch 4/9] Remove the TSC synchronization on SMP machines jbohac
2007-02-01 11:14 ` Andi Kleen
2007-02-01 13:17 ` Jiri Bohac
2007-02-01 15:16 ` Vojtech Pavlik
2007-02-02 7:14 ` Andi Kleen
2007-02-13 0:34 ` Christoph Lameter
2007-02-13 6:40 ` Arjan van de Ven
2007-02-13 8:28 ` Andi Kleen
2007-02-13 8:41 ` Arjan van de Ven
2007-02-13 17:09 ` Christoph Lameter
2007-02-13 17:20 ` Andi Kleen
2007-02-13 22:18 ` Vojtech Pavlik
2007-02-13 22:38 ` Andrea Arcangeli
2007-02-14 6:59 ` Vojtech Pavlik
2007-02-13 23:55 ` Christoph Lameter
2007-02-14 0:18 ` Paul Mackerras
2007-02-14 0:25 ` john stultz
2007-02-02 7:13 ` Andi Kleen
2007-02-01 21:05 ` mbligh
2007-02-03 1:16 ` H. Peter Anvin
2007-02-01 9:59 ` [patch 5/9] Add all the necessary structures to the vsyscall page jbohac
2007-02-01 11:17 ` Andi Kleen
2007-02-01 9:59 ` [patch 6/9] Add the "Master Timer" jbohac
2007-02-01 11:22 ` Andi Kleen
2007-02-01 13:29 ` Jiri Bohac
2007-02-01 9:59 ` jbohac [this message]
2007-02-01 11:26 ` [patch 7/9] Adapt the time initialization code Andi Kleen
2007-02-01 13:41 ` Jiri Bohac
2007-02-01 10:00 ` [patch 8/9] Add time_update_mt_guess() jbohac
2007-02-01 11:28 ` Andi Kleen
2007-02-01 13:54 ` Jiri Bohac
2007-02-01 10:00 ` [patch 9/9] Make use of the Master Timer jbohac
2007-02-01 11:36 ` Andi Kleen
2007-02-01 14:29 ` Jiri Bohac
2007-02-01 15:23 ` Vojtech Pavlik
2007-02-02 7:05 ` Andi Kleen
2007-02-02 7:04 ` Andi Kleen
2007-02-01 11:20 ` [patch 0/9] x86_64: reliable TSC-based gettimeofday Andi Kleen
2007-02-01 11:53 ` Andrea Arcangeli
2007-02-01 12:02 ` Andi Kleen
2007-02-01 12:54 ` Andrea Arcangeli
2007-02-01 12:17 ` Ingo Molnar
2007-02-01 14:52 ` Jiri Bohac
2007-02-01 16:56 ` john stultz
2007-02-01 19:41 ` Vojtech Pavlik
2007-02-01 11:34 ` Ingo Molnar
2007-02-01 11:46 ` [-mm patch] x86_64 GTOD: offer scalable vgettimeofday Ingo Molnar
2007-02-01 12:01 ` Andi Kleen
2007-02-01 12:14 ` Ingo Molnar
2007-02-01 12:17 ` [-mm patch] x86_64 GTOD: offer scalable vgettimeofday II Andi Kleen
2007-02-01 12:24 ` Ingo Molnar
2007-02-01 12:45 ` Andi Kleen
2007-02-02 4:22 ` [patch 0/9] x86_64: reliable TSC-based gettimeofday Andrew Morton
2007-02-02 7:07 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070201103754.041245000@jet.suse.cz \
--to=jbohac@suse.cz \
--cc=ak@suse.de \
--cc=andrea@suse.de \
--cc=arjan@infradead.org \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=ssouhlal@freebsd.org \
--cc=tglx@linutronix.de \
--cc=vojtech@suse.cz \
--cc=zippel@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.