Skip to contentSkip to conversation

new timeofday core subsystem (v A4)

RFC PATCH In review john stultz 7 participants 15 messages Apr 29, 2005 – May 3, 2005

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 new timeofday core subsystem (v A4)

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

Mostly this version is just a cleanup of the last release. One neat feature is the new sysfs interface which allows you to manually override the selected timesource while the system is running.

Included below is timeofday.c (which includes all the time of day management and accessor functions), ntp.c (which includes the ntp scaling calculation code, leapsecond processing, and ntp kernel state machine code), timesource.c (for timesource specific management functions), interface definition .h files, the example jiffies timesource (lowest common denominator time source, mainly for use as example code) and minimal hooks into arch independent code.

The patch does not function without minimal architecture specific hooks (i386, x86-64, ppc32, ppc64, ia64 and s390 examples to follow), and it should be able to be applied to a tree without affecting the code.

New in this version:
o Improved cyc2ns remainder handling
o Added getnstimeofday() interface
o Better timesource management
o Sysfs interface for overriding timesources
o Cleanups from Nish Aravamudan and Matt Mackall

Items still on the TODO list:
o make ntp adjustments be in ppb instead of ppm
o posix-timers integration
o boot time "timesource=" override option

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc2_timeofday-core_A4.patch
=========================================

drivers/Makefile +1 -0
diff -Nru a/drivers/Makefile b/drivers/Makefile
@@ -64,3 +64,4 @@
 obj-$(CONFIG_BLK_DEV_SGIIOC4)	+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
+obj-$(CONFIG_NEWTOD)		+= timesource/
drivers/timesource/Makefile new file +1 -0
diff -Nru a/drivers/timesource/Makefile b/drivers/timesource/Makefile
@@ -0,0 +1 @@
+obj-y += jiffies.o
drivers/timesource/jiffies.c new file +45 -0

45 lines not on this page · raw message

include/linux/ntp.h new file +22 -0
diff -Nru a/include/linux/ntp.h b/include/linux/ntp.h
@@ -0,0 +1,22 @@
+/*  linux/include/linux/ntp.h
+ *
+ *  Copyright (C) 2003, 2004, 2005 IBM, John Stultz ([email protected])
+ *
+ *  This file NTP state machine accessor functions.
+ */
+
+#ifndef _LINUX_NTP_H
+#define _LINUX_NTP_H
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+/* NTP state machine interfaces */
+nsec_t ntp_scale(nsec_t value);
+int ntp_advance(nsec_t value);
+int ntp_adjtimex(struct timex*);
+int ntp_leapsecond(struct timespec now);
+void ntp_clear(void);
+int get_ntp_status(void);
+
+#endif
include/linux/time.h +4 -0
diff -Nru a/include/linux/time.h b/include/linux/time.h
@@ -27,6 +27,10 @@
 
 #ifdef __KERNEL__
 
+/* timeofday base types */
+typedef u64 nsec_t;
+typedef u64 cycle_t;
+
 /* Parameters used to convert the timespec values */
 #ifndef USEC_PER_SEC
 #define USEC_PER_SEC (1000000L)
include/linux/timeofday.h new file +65 -0

65 lines not on this page · raw message

include/linux/timesource.h new file +159 -0

159 lines not on this page · raw message

init/main.c +2 -0
diff -Nru a/init/main.c b/init/main.c
@@ -47,6 +47,7 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/timeofday.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -467,6 +468,7 @@
 	pidhash_init();
 	init_timers();
 	softirq_init();
+	timeofday_init();
 	time_init();
 
 	/*
kernel/Makefile +1 -0
diff -Nru a/kernel/Makefile b/kernel/Makefile
@@ -9,6 +9,7 @@
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
 
+obj-$(CONFIG_NEWTOD) += timeofday.o timesource.o ntp.o
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
kernel/ntp.c new file +498 -0

498 lines not on this page · raw message

kernel/time.c +5 -0
diff -Nru a/kernel/time.c b/kernel/time.c
@@ -38,6 +38,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <linux/timeofday.h>
 
 /* 
  * The timezone where the local system is located.  Used as a default by some
@@ -227,6 +228,7 @@
 /* adjtimex mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
+#ifndef CONFIG_NEWTOD
 int do_adjtimex(struct timex *txc)
 {
         long ltemp, mtemp, save_adjust;
@@ -410,6 +412,7 @@
 	notify_arch_cmos_timer();
 	return(result);
 }
+#endif
 
 asmlinkage long sys_adjtimex(struct timex __user *txc_p)
 {
@@ -566,6 +569,7 @@
 
 
 #else
+#ifndef CONFIG_NEWTOD
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
  * and therefore only yields usec accuracy
@@ -578,6 +582,7 @@
 	tv->tv_sec = x.tv_sec;
 	tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
 }
+#endif /* CONFIG_NEWTOD */
 #endif
 
 #if (BITS_PER_LONG < 64)
kernel/timeofday.c new file +522 -0

522 lines not on this page · raw message

kernel/timer.c +4 -0
diff -Nru a/kernel/timer.c b/kernel/timer.c
@@ -577,6 +577,7 @@
 int tickadj = 500/HZ ? : 1;		/* microsecs */
 
 
+#ifndef CONFIG_NEWTOD
 /*
  * phase-lock loop variables
  */
@@ -807,6 +808,9 @@
 		}
 	} while (ticks);
 }
+#else /* CONFIG_NEWTOD */
+#define update_wall_time(x)
+#endif /* CONFIG_NEWTOD */
 
 /*
  * Called from the timer interrupt handler to charge one tick to the current 
kernel/timesource.c new file +210 -0

210 lines not on this page · raw message

#1 lore raw

RFC PATCH 1/1 new timeofday arch specific hooks (v A4)

All,
This patch implements the minimal architecture specific hooks to
enable the new time of day subsystem code for i386, x86-64, ia64, ppc32, ppc64 and s390. It applies on top of my linux-2.6.12-rc2_timeofday- core_A4 patch and with this patch applied, you can test the new time of day subsystem.

Basically it configs in the NEWTOD code and cuts alot of code out of the build via #ifdefs. I know, I know, #ifdefs' are ugly and bad, and the final patch will just remove the old code. For now this allows us to be flexible and easily switch between the two implementations with a single define.

While there is code for all of the arches above, I am unable to fully test all of them with the limited time I have to spend on this work. i386 and x86-64 are reasonably well tested, ppc32 less so and the others hopefully still compile :)

New in this version:
o s390 arch support! (Big thanks to Martin Schwidefsky!)

Items still on the TODO list:
o Break up each arch into its own patch
o Get rid of #ifdefs

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc2_timeofday-arch_A4.patch
========================================

arch/i386/Kconfig +4 -0
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
@@ -14,6 +14,10 @@
 	  486, 586, Pentiums, and various instruction-set-compatible chips by
 	  AMD, Cyrix, and others.
 
+config NEWTOD
+	bool
+	default y
+
 config MMU
 	bool
 	default y
arch/i386/kernel/apm.c +3 -0
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
@@ -224,6 +224,7 @@
 #include <linux/smp_lock.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
+#include <linux/timeofday.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -1205,6 +1206,7 @@
 	local_irq_disable();
 	device_power_down(PMSG_SUSPEND);
 
+	timeofday_suspend_hook();
 	/* serialize with the timer interrupt */
 	write_seqlock(&xtime_lock);
 
@@ -1234,6 +1236,7 @@
 	spin_unlock(&i8253_lock);
 	write_sequnlock(&xtime_lock);
 
+	timeofday_resume_hook();
 	if (err == APM_NO_ERROR)
 		err = APM_SUCCESS;
 	if (err != APM_SUCCESS)
arch/i386/kernel/time.c +68 -4

167 lines not on this page · raw message

arch/i386/lib/delay.c +19 -0
diff -Nru a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
@@ -23,10 +23,29 @@
 
 extern struct timer_opts* timer;
 
+#ifndef CONFIG_NEWTOD
 void __delay(unsigned long loops)
 {
 	cur_timer->delay(loops);
 }
+#else
+#include <linux/timeofday.h>
+/* XXX - For now just use a simple loop delay
+ *  This has cpufreq issues, but so did the old method.
+ */
+void __delay(unsigned long loops)
+{
+	int d0;
+	__asm__ __volatile__(
+		"\tjmp 1f\n"
+		".align 16\n"
+		"1:\tjmp 2f\n"
+		".align 16\n"
+		"2:\tdecl %0\n\tjns 2b"
+		:"=&a" (d0)
+		:"0" (loops));
+}
+#endif
 
 inline void __const_udelay(unsigned long xloops)
 {
arch/ia64/Kconfig +5 -1
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
@@ -18,6 +18,10 @@
 	  page at <http://www.linuxia64.org/> and a mailing list at
 	  <[email protected]>.
 
+config NEWTOD
+        bool
+        default y
+
 config 64BIT
 	bool
 	default y
@@ -36,7 +40,7 @@
 
 config TIME_INTERPOLATION
 	bool
-	default y
+	default n
 
 config EFI
 	bool
arch/ia64/kernel/asm-offsets.c +2 -0
diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
@@ -222,6 +222,7 @@
 	DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
 	       offsetof (struct ia64_mca_cpu, init_stack));
 	BLANK();
+#ifndef CONFIG_NEWTOD
 	/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
 	DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
 	DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
@@ -235,5 +236,6 @@
 	DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
 	DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
 	DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
+#endif /* CONFIG_NEWTOD */
 	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 }
arch/ia64/kernel/fsys.S +12 -0
diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
@@ -145,6 +145,7 @@
 	FSYS_RETURN
 END(fsys_set_tid_address)
 
+#ifndef CONFIG_NEWTOD
 /*
  * Ensure that the time interpolator structure is compatible with the asm code
  */
@@ -326,6 +327,7 @@
 EX(.fail_efault, st8 [r31] = r9)
 EX(.fail_efault, st8 [r23] = r21)
 	FSYS_RETURN
+#endif /* !CONFIG_NEWTOD */
 .fail_einval:
 	mov r8 = EINVAL
 	mov r10 = -1
@@ -334,6 +336,7 @@
 	mov r8 = EFAULT
 	mov r10 = -1
 	FSYS_RETURN
+#ifndef CONFIG_NEWTOD
 END(fsys_gettimeofday)
 
 ENTRY(fsys_clock_gettime)
@@ -347,6 +350,7 @@
 	shl r30 = r32,15
 	br.many .gettime
 END(fsys_clock_gettime)
+#endif /* !CONFIG_NEWTOD */
 
 /*
  * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
@@ -687,7 +691,11 @@
 	data8 0				// setrlimit
 	data8 0				// getrlimit		// 1085
 	data8 0				// getrusage
+#ifdef CONFIG_NEWTOD
+	data8 0				// gettimeofday
+#else
 	data8 fsys_gettimeofday		// gettimeofday
+#endif
 	data8 0				// settimeofday
 	data8 0				// select
 	data8 0				// poll			// 1090
@@ -854,7 +862,11 @@
 	data8 0				// timer_getoverrun
 	data8 0				// timer_delete
 	data8 0				// clock_settime
+#ifdef CONFIG_NEWTOD
+	data8 0				// clock_gettime
+#else
 	data8 fsys_clock_gettime	// clock_gettime
+#endif
 	data8 0				// clock_getres		// 1255
 	data8 0				// clock_nanosleep
 	data8 0				// fstatfs64
arch/ia64/kernel/time.c +19 -0
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
@@ -21,6 +21,7 @@
 #include <linux/efi.h>
 #include <linux/profile.h>
 #include <linux/timex.h>
+#include <linux/timeofday.h>
 
 #include <asm/machvec.h>
 #include <asm/delay.h>
@@ -45,11 +46,13 @@
 
 #endif
 
+#ifndef CONFIG_NEWTOD
 static struct time_interpolator itc_interpolator = {
 	.shift = 16,
 	.mask = 0xffffffffffffffffLL,
 	.source = TIME_SOURCE_CPU
 };
+#endif /* CONFIG_NEWTOD */
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
@@ -211,6 +214,7 @@
 	local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<<IA64_NSEC_PER_CYC_SHIFT)
 					+ itc_freq/2)/itc_freq;
 
+#ifndef CONFIG_NEWTOD
 	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
 		itc_interpolator.frequency = local_cpu_data->itc_freq;
 		itc_interpolator.drift = itc_drift;
@@ -229,6 +233,7 @@
 #endif
 		register_time_interpolator(&itc_interpolator);
 	}
+#endif /* CONFIG_NEWTOD */
 
 	/* Setup the CPU local timer tick */
 	ia64_cpu_local_tick();
@@ -253,3 +258,17 @@
 	 */
 	set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
 }
+
+/* arch specific timeofday hooks */
+nsec_t read_persistent_clock(void)
+{
+        struct timespec ts;
+        efi_gettimeofday(&ts);
+        return (nsec_t)(ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec);
+}
+
+void sync_persistent_clock(struct timespec ts)
+{
+	/* XXX - Something should go here, no? */
+}
+
arch/ia64/sn/kernel/sn2/timer.c +6 -0
diff -Nru a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
@@ -19,6 +19,7 @@
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/clksupport.h>
 
+#ifndef CONFIG_NEWTOD
 extern unsigned long sn_rtc_cycles_per_second;
 
 static struct time_interpolator sn2_interpolator = {
@@ -34,3 +35,8 @@
 	sn2_interpolator.addr = RTC_COUNTER_ADDR;
 	register_time_interpolator(&sn2_interpolator);
 }
+#else
+void __init sn_timer_init(void)
+{
+}
+#endif
arch/ppc/Kconfig +4 -0
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
@@ -8,6 +8,10 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
 config UID16
 	bool
 
arch/ppc/kernel/time.c +48 -0

93 lines not on this page · raw message

arch/ppc/platforms/chrp_time.c +2 -0
diff -Nru a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
@@ -115,8 +115,10 @@
 	chrp_cmos_clock_write(save_control, RTC_CONTROL);
 	chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
 
+#ifndef CONFIG_NEWTOD
 	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
 		time_state = TIME_OK;
+#endif
 	spin_unlock(&rtc_lock);
 	return 0;
 }
arch/ppc64/Kconfig +4 -0
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
@@ -10,6 +10,10 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
 config UID16
 	bool
 
arch/ppc64/kernel/sys_ppc32.c +2 -0
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
@@ -322,8 +322,10 @@
 
 	ret = do_adjtimex(&txc);
 
+#ifndef CONFIG_NEWTOD
 	/* adjust the conversion of TB to time of day to track adjtimex */
 	ppc_adjtimex();
+#endif
 
 	if(put_user(txc.modes, &utp->modes) ||
 	   __put_user(txc.offset, &utp->offset) ||
arch/ppc64/kernel/time.c +60 -0

132 lines not on this page · raw message

arch/s390/Kconfig +4 -0
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
@@ -127,6 +127,10 @@
 	  This allows you to run 32-bit Linux/ELF binaries on your zSeries
 	  in 64 bit mode. Everybody wants this; say Y.
 
+config NEWTOD
+	bool
+	default y
+
 comment "Code generation options"
 
 choice
arch/s390/kernel/time.c +22 -0
diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
@@ -29,6 +29,7 @@
 #include <linux/profile.h>
 #include <linux/timex.h>
 #include <linux/notifier.h>
+#include <linux/timeofday.h>
 
 #include <asm/uaccess.h>
 #include <asm/delay.h>
@@ -89,6 +90,7 @@
 	return (unsigned long) now;
 }
 
+#ifndef CONFIG_NEWTOD
 /*
  * This version of gettimeofday has microsecond resolution.
  */
@@ -149,7 +151,27 @@
 }
 
 EXPORT_SYMBOL(do_settimeofday);
+#endif
 
+nsec_t read_persistent_clock(void)
+{
+	unsigned long long nsecs;
+	/*
+	 * The TOD clock counts from 1900-01-01. Bit 2^12 of the
+	 * 64 bit register is micro-seconds.
+	 */
+	nsecs = get_clock() - 0x7d91048bca000000LL;
+	/*
+	 * Calc nsecs * 1000 / 4096 without overflow and
+	 * without loosing too many bits.
+	 */
+	nsecs = (((((nsecs >> 3) * 5) >> 3) * 5) >> 3) * 5;
+	return (nsec_t) nsecs;
+}
+
+void sync_persistent_clock(struct timespec ts)
+{
+}
 
 #ifdef CONFIG_PROFILING
 #define s390_do_profile(regs)	profile_tick(CPU_PROFILING, regs)
arch/x86_64/Kconfig +4 -0
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
@@ -24,6 +24,10 @@
 	bool
 	default y
 
+config NEWTOD
+	bool
+	default y
+
 config MMU
 	bool
 	default y
arch/x86_64/kernel/time.c +56 -1

141 lines not on this page · raw message

arch/x86_64/kernel/vsyscall.c +5 -0
diff -Nru a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
@@ -217,8 +217,13 @@
 	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
 	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
 	map_vsyscall();
+/* XXX - disable vsyscall gettimeofday for now */
+#ifndef CONFIG_NEWTOD
 	sysctl_vsyscall = 1;
 	register_sysctl_table(kernel_root_table2, 0);
+#else
+	sysctl_vsyscall = 0;
+#endif
 	return 0;
 }
 
include/asm-generic/div64.h +9 -0
diff -Nru a/include/asm-generic/div64.h b/include/asm-generic/div64.h
@@ -55,4 +55,13 @@
 
 #endif /* BITS_PER_LONG */
 
+#ifndef div_long_long_rem
+#define div_long_long_rem(dividend,divisor,remainder) \
+({							\
+	u64 result = dividend;				\
+	*remainder = do_div(result,divisor);		\
+	result;						\
+})
+#endif
+
 #endif /* _ASM_GENERIC_DIV64_H */
include/asm-ppc64/time.h +1 -0
diff -Nru a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
@@ -21,6 +21,7 @@
 #include <asm/processor.h>
 #include <asm/paca.h>
 #include <asm/iSeries/HvCall.h>
+#include <asm/percpu.h>
 
 /* time.c */
 extern unsigned long tb_ticks_per_jiffy;
include/linux/timeofday.h +1 -0
diff -Nru a/include/linux/timeofday.h b/include/linux/timeofday.h
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/timex.h>
+#include <linux/jiffies.h>	/* For div_long_long_rem */
 #include <asm/div64.h>
 
 #ifdef CONFIG_NEWTOD
#2 lore raw

RFC PATCH 1/1 new timeofday arch specific timesource drivers (v A4)

All,
This patch implements most of the time sources for i386, x86-64,
ppc32 and ppc64 (tsc, pit, cyclone, acpi-pm, hpet and timebase). There are also initial untested sketches for s390 and the ia64 itc and sn2_rtc timesources. It applies ontop of my linux-2.6.12-rc2_timeofday-arch_A4 patch. It provides real hardware timesources (opposed to the example jiffies timesource) that can be used for more realistic testing.

This patch is the shabbiest of the three. It needs to be broken up, and cleaned. The i386_pit.c is broken. The hpet and cyclone code have been attempted to be cleaned up so they can be shared between x86-64, i386 and ia64, but they still need testing. acpi_pm also needs to be made arch generic, but for now it will get you going so you can test and play with the core code.

New in this release:
o s390 support (Big thanks to Martin Schwidefsky!)

Items still on the TODO list:
o Fix TSC C3 stalls
o real ia64 timesources
o make cyclone/apci_pm arch generic
o example interpolation timesource
o fix i386_pit timesource
o all other arch timesources (volunteers wanted!)
o lots of cleanups
o lots of testing

thanks
-john

linux-2.6.12-rc2_timeofday-timesources_A4.patch
===============================================

arch/i386/kernel/Makefile +2 -2
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
@@ -7,10 +7,10 @@
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
-		doublefault.o quirks.o
+		doublefault.o quirks.o tsc.o
 
 obj-y				+= cpu/
-obj-y				+= timers/
+obj-$(!CONFIG_NEWTOD)		+= timers/
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
arch/i386/kernel/acpi/boot.c +3 -9
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
@@ -547,7 +547,7 @@
 
 
 #ifdef CONFIG_HPET_TIMER
-
+#include <asm/hpet.h>
 static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
 {
 	struct acpi_table_hpet *hpet_tbl;
@@ -570,18 +570,12 @@
 #ifdef	CONFIG_X86_64
         vxtime.hpet_address = hpet_tbl->addr.addrl |
                 ((long) hpet_tbl->addr.addrh << 32);
-
-        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-               hpet_tbl->id, vxtime.hpet_address);
+	hpet_address = vxtime.hpet_address;
 #else	/* X86 */
-	{
-		extern unsigned long hpet_address;
-
 		hpet_address = hpet_tbl->addr.addrl;
+#endif	/* X86 */
 		printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
 			hpet_tbl->id, hpet_address);
-	}
-#endif	/* X86 */
 
 	return 0;
 }
arch/i386/kernel/i8259.c +42 -0

48 lines not on this page · raw message

arch/i386/kernel/setup.c +2 -0
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
@@ -50,6 +50,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
+#include <asm/tsc.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -1523,6 +1524,7 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
+	tsc_init();
 }
 
 #include "setup_arch_post.h"
arch/i386/kernel/time.c +2 -0
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
@@ -88,7 +88,9 @@
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
+#ifndef CONFIG_NEWTOD
 struct timer_opts *cur_timer = &timer_none;
+#endif
 
 /*
  * This is a special lock that is owned by the CPU and holds the index
arch/i386/kernel/timers/common.c +0 -2
diff -Nru a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c
@@ -22,8 +22,6 @@
  * device.
  */
 
-#define CALIBRATE_TIME	(5 * 1000020/HZ)
-
 unsigned long __init calibrate_tsc(void)
 {
 	mach_prepare_counter();
arch/i386/kernel/tsc.c new file +111 -0

111 lines not on this page · raw message

arch/x86_64/kernel/time.c +1 -0
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
@@ -59,6 +59,7 @@
 #undef HPET_HACK_ENABLE_DANGEROUS
 
 unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
+unsigned long hpet_address;
 static unsigned long hpet_period;			/* fsecs / HPET clock */
 unsigned long hpet_tick;				/* HPET clocks / interrupt */
 unsigned long vxtime_hz = PIT_TICK_RATE;
drivers/timesource/Makefile +14 -0
diff -Nru a/drivers/timesource/Makefile b/drivers/timesource/Makefile
@@ -1 +1,15 @@
 obj-y += jiffies.o
+obj-$(CONFIG_X86) += tsc.o
+obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
+obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
+obj-$(CONFIG_HPET_TIMER) += hpet.o
+obj-$(CONFIG_PPC64) += ppc64_timebase.o
+obj-$(CONFIG_PPC) += ppc_timebase.o
+obj-$(CONFIG_ARCH_S390) += s390_tod.o
+
+# XXX - Known broken
+#obj-$(CONFIG_X86) += i386_pit.o
+
+# XXX - Untested/Uncompiled
+#obj-$(CONFIG_IA64) += itc.c
+#obj-$(CONFIG_IA64_SGI_SN2) += sn2_rtc.c
drivers/timesource/acpi_pm.c new file +116 -0

116 lines not on this page · raw message

drivers/timesource/cyclone.c new file +135 -0

135 lines not on this page · raw message

drivers/timesource/hpet.c new file +59 -0

59 lines not on this page · raw message

drivers/timesource/i386_pit.c new file +100 -0

100 lines not on this page · raw message

drivers/timesource/itc.c new file +35 -0
diff -Nru a/drivers/timesource/itc.c b/drivers/timesource/itc.c
@@ -0,0 +1,35 @@
+/* XXX - this is totally untested and uncompiled
+ * TODO:
+ *		o cpufreq issues
+ *		o unsynched ITCs ?
+ */
+#include <linux/timesource.h>
+
+/* XXX - Other includes needed for:
+ *		sal_platform_features, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT,
+ *		local_cpu_data->itc_freq
+ * See arch/ia64/kernel/time.c for ideas
+ */
+
+static struct timesource_t timesource_itc = {
+	.name = "itc",
+	.priority = 25,
+	.type = TIMESOURCE_CYCLES,
+	.mask = (cycle_t)-1,
+	.mult = 0, /* to be set */
+	.shift = 22,
+};
+
+static int init_itc_timesource(void)
+{
+	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
+		/* XXX - I'm not really sure if itc_freq is in cyc/sec */
+		timesource_itc.mult = timesource_hz2mult(local_cpu_data->itc_freq,
+									timesource_itc.shift);
+		register_timesource(&timesource_itc);
+	}
+	return 0;
+}
+
+module_init(init_itc_timesource);
+
drivers/timesource/ppc64_timebase.c new file +33 -0
diff -Nru a/drivers/timesource/ppc64_timebase.c b/drivers/timesource/ppc64_timebase.c
@@ -0,0 +1,33 @@
+#include <linux/timesource.h>
+#include <asm/time.h>
+
+static cycle_t timebase_read(void)
+{
+	return (cycle_t)get_tb();
+}
+
+struct timesource_t timesource_timebase = {
+	.name = "timebase",
+	.priority = 200,
+	.type = TIMESOURCE_FUNCTION,
+	.read_fnct = timebase_read,
+	.mask = (cycle_t)-1,
+	.mult = 0,
+	.shift = 22,
+};
+
+
+/* XXX - this should be calculated or properly externed! */
+extern unsigned long tb_to_ns_scale;
+extern unsigned long tb_to_ns_shift;
+extern unsigned long tb_ticks_per_sec;
+
+static int init_timebase_timesource(void)
+{
+	timesource_timebase.mult = timesource_hz2mult(tb_ticks_per_sec,
+										timesource_timebase.shift);
+	register_timesource(&timesource_timebase);
+	return 0;
+}
+
+module_init(init_timebase_timesource);
drivers/timesource/ppc_timebase.c new file +56 -0

56 lines not on this page · raw message

drivers/timesource/s390_tod.c new file +37 -0
diff -Nru a/drivers/timesource/s390_tod.c b/drivers/timesource/s390_tod.c
@@ -0,0 +1,37 @@
+/*
+ * linux/drivers/timesource/s390_tod.c
+ *
+ * (C) Copyright IBM Corp. 2004
+ *
+ * Author(s): Martin Schwidefsky ([email protected]),
+ *
+ * s390 TOD clock time source.
+ */
+
+#include <linux/timesource.h>
+#include <linux/timex.h>
+#include <linux/init.h>
+
+static cycle_t s390_tod_read(void)
+{
+	return get_clock();
+}
+
+struct timesource_t timesource_s390_tod = {
+	.name = "TOD",
+	.priority = 100,
+	.type = TIMESOURCE_FUNCTION,
+	.read_fnct = s390_tod_read,
+	.mask = -1ULL,
+	.mult = 1000,
+	.shift = 12
+};
+
+
+static int init_s390_timesource(void)
+{
+	register_timesource(&timesource_s390_tod);
+	return 0;
+}
+
+module_init(init_s390_timesource);
drivers/timesource/sn2_rtc.c new file +29 -0
diff -Nru a/drivers/timesource/sn2_rtc.c b/drivers/timesource/sn2_rtc.c
@@ -0,0 +1,29 @@
+#include <linux/timesource.h>
+/* XXX this will need some includes
+ * to find: sn_rtc_cycles_per_second and RTC_COUNTER_ADDR
+ * See arch/ia64/sn/kernel/sn2/timer.c for likely suspects
+ */
+
+#define SN2_RTC_MASK ((1LL << 55) - 1)
+#define SN2_SHIFT 10
+
+struct timesource_t timesource_sn2_rtc = {
+	.name = "sn2_rtc",
+	.priority = 300, /* XXX - not sure what this should be */
+	.type = TIMESOURCE_MMIO_64,
+	.mmio_ptr = NULL,
+	.mask = (cycle_t)SN2_RTC_MASK,
+	.mult = 0, /* set below */
+	.shift = SN2_SHIFT,
+};
+
+static void init_sn2_timesource(void)
+{
+	timesource_sn2_rtc.mult = timesource_hz2mult(sn_rtc_cycles_per_second,
+												SN2_SHIFT);
+	timesource_sn2_rtc.mmio_ptr = RTC_COUNTER_ADDR;
+
+	register_time_interpolator(&timesource_sn2_rtc);
+	return 0;
+}
+module_init(init_sn2_timesource);
drivers/timesource/tsc.c new file +46 -0

46 lines not on this page · raw message

include/asm-i386/mach-default/mach_timer.h +5 -1
diff -Nru a/include/asm-i386/mach-default/mach_timer.h b/include/asm-i386/mach-default/mach_timer.h
@@ -14,8 +14,12 @@
  */
 #ifndef _MACH_TIMER_H
 #define _MACH_TIMER_H
+#include <linux/jiffies.h>
+#include <asm/io.h>
 
-#define CALIBRATE_LATCH	(5 * LATCH)
+#define CALIBRATE_ITERATION 50
+#define CALIBRATE_LATCH	(CALIBRATE_ITERATION * LATCH)
+#define CALIBRATE_TIME	(CALIBRATE_ITERATION * 1000020/HZ)
 
 static inline void mach_prepare_counter(void)
 {
include/asm-i386/timer.h +8 -8
diff -Nru a/include/asm-i386/timer.h b/include/asm-i386/timer.h
@@ -2,6 +2,13 @@
 #define _ASMi386_TIMER_H
 #include <linux/init.h>
 
+#define TICK_SIZE (tick_nsec / 1000)
+void setup_pit_timer(void);
+/* Modifiers for buggy PIT handling */
+extern int pit_latch_buggy;
+extern int timer_ack;
+
+#ifndef CONFIG_NEWTOD
 /**
  * struct timer_ops - used to define a timer source
  *
@@ -29,18 +36,10 @@
 	struct timer_opts *opts;
 };
 
-#define TICK_SIZE (tick_nsec / 1000)
-
 extern struct timer_opts* __init select_timer(void);
 extern void clock_fallback(void);
-void setup_pit_timer(void);
-
-/* Modifiers for buggy PIT handling */
-
-extern int pit_latch_buggy;
 
 extern struct timer_opts *cur_timer;
-extern int timer_ack;
 
 /* list of externed timers */
 extern struct timer_opts timer_none;
@@ -60,5 +59,6 @@
 
 #ifdef CONFIG_X86_PM_TIMER
 extern struct init_timer_opts timer_pmtmr_init;
+#endif
 #endif
 #endif
include/asm-i386/tsc.h new file +6 -0
diff -Nru a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_I386_TSC_H
+#define _ASM_I386_TSC_H
+extern unsigned long cpu_freq_khz;
+void tsc_init(void);
+
+#endif
include/asm-x86_64/hpet.h +2 -1
diff -Nru a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
@@ -1,6 +1,6 @@
 #ifndef _ASM_X8664_HPET_H
 #define _ASM_X8664_HPET_H 1
-
+#include <asm/fixmap.h>
 /*
  * Documentation on HPET can be found at:
  *      http://www.intel.com/ial/home/sp/pcmmspec.htm
@@ -44,6 +44,7 @@
 #define HPET_TN_SETVAL		0x040
 #define HPET_TN_32BIT		0x100
 
+extern unsigned long hpet_address;	/* hpet memory map physical address */
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
 extern int oem_force_hpet_timer(void);
include/linux/sched.h +4 -0
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
@@ -825,7 +825,11 @@
 }
 #endif
 
+#ifndef CONFIG_NEWTOD
 extern unsigned long long sched_clock(void);
+#else
+#define sched_clock() 0
+#endif
 extern unsigned long long current_sched_time(const task_t *current_task);
 
 /* sched_exec is called by processes performing an exec */
#3 lore raw

RFC PATCH 1/1 new timeofday vsyscall proof of concept (v A4)

All,

This patch implements vsyscall-gettimeofday() functions for i386 and
x86-64 using the new timeofday core code. This is just a hackish proof of concept that shows how it could be done and what interfaces are needed to have a clean separation of the arch independent time keeping and the very arch specific vsyscall code.

I look forward to your comments and feedback.

thanks
-john

linux-2.6.12-rc2_timeofday-vsyscall_A4.patch
===============================================

arch/i386/Kconfig +4 -0
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
@@ -464,6 +464,10 @@
 	bool "Provide RTC interrupt"
 	depends on HPET_TIMER && RTC=y
 
+config NEWTOD_VSYSCALL
+	depends on EXPERIMENTAL
+	bool "VSYSCALL gettimeofday() interface"
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
arch/i386/kernel/Makefile +1 -0
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
@@ -11,6 +11,7 @@
 
 obj-y				+= cpu/
 obj-$(!CONFIG_NEWTOD)		+= timers/
+obj-$(CONFIG_NEWTOD_VSYSCALL)	+= vsyscall-gtod.o
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
arch/i386/kernel/setup.c +2 -0
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
@@ -51,6 +51,7 @@
 #include <asm/ist.h>
 #include <asm/io.h>
 #include <asm/tsc.h>
+#include <asm/vsyscall-gtod.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -1525,6 +1526,7 @@
 #endif
 #endif
 	tsc_init();
+	vsyscall_init();
 }
 
 #include "setup_arch_post.h"
arch/i386/kernel/vmlinux.lds.S +27 -0
diff -Nru a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
@@ -5,6 +5,8 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <linux/config.h>
+#include <asm/vsyscall-gtod.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -51,6 +53,31 @@
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
   _edata = .;			/* End of data section */
+
+/* VSYSCALL_GTOD data */
+#ifdef CONFIG_NEWTOD_VSYSCALL
+
+  /* vsyscall entry */
+   . = ALIGN(64);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .vsyscall_0 VSYSCALL_GTOD_START: AT ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) { *(.vsyscall_0) }
+  __vsyscall_0 = LOADADDR(.vsyscall_0);
+
+
+	/* generic gtod variables */
+  . = ALIGN(64);
+  .vsyscall_gtod_data : AT ((LOADADDR(.vsyscall_0) + SIZEOF(.vsyscall_0) + 63) & ~(63)) { *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = LOADADDR(.vsyscall_gtod_data);
+
+    . = ALIGN(16);
+  .vsyscall_gtod_lock : AT ((LOADADDR(.vsyscall_gtod_data) + SIZEOF(.vsyscall_gtod_data) + 15) & ~(15)) { *(.vsyscall_gtod_lock) }
+  vsyscall_gtod_lock = LOADADDR(.vsyscall_gtod_lock);
+
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
+  . = LOADADDR(.vsyscall_0) + 4096;
+#endif
+/* END of VSYSCALL_GTOD data*/
 
   . = ALIGN(THREAD_SIZE);	/* init_task */
   .data.init_task : { *(.data.init_task) }
arch/i386/kernel/vsyscall-gtod.c new file +193 -0

193 lines not on this page · raw message

arch/x86_64/Kconfig +4 -0
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
@@ -57,6 +57,10 @@
 	bool
 	default y
 
+config NEWTOD_VSYSCALL
+	depends on EXPERIMENTAL
+	bool "VSYSCALL gettimeofday() interface"
+
 config GENERIC_ISA_DMA
 	bool
 	default y
arch/x86_64/kernel/time.c +3 -1
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
@@ -81,6 +81,7 @@
 	rdtscll(*tsc);
 }
 
+#ifndef CONFIG_NEWTOD
 /*
  * do_gettimeoffset() returns microseconds since last timer interrupt was
  * triggered by hardware. A memory read of HPET is slower than a register read
@@ -108,7 +109,6 @@
 
 unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
 
-#ifndef CONFIG_NEWTOD
 /*
  * This version of gettimeofday() has microsecond resolution and better than
  * microsecond precision, as we're using at least a 10 MHz (usually 14.31818
@@ -976,6 +976,7 @@
 	/* Some systems will want to disable TSC and use HPET. */
 	if (oem_force_hpet_timer())
 		notsc = 1;
+#ifndef CONFIG_NEWTOD
 	if (vxtime.hpet_address && notsc) {
 		timetype = "HPET";
 		vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
@@ -987,6 +988,7 @@
 	}
 
 	printk(KERN_INFO "time.c: Using %s based timekeeping.\n", timetype);
+#endif /* CONFIG_NEWTOD */
 }
 
 __setup("report_lost_ticks", time_setup);
arch/x86_64/kernel/vmlinux.lds.S +7 -0
diff -Nru a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
@@ -71,6 +71,13 @@
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .jiffies : AT CACHE_ALIGN(AFTER(.xtime)) { *(.jiffies) }
   jiffies = LOADADDR(.jiffies);
+
+  .vsyscall_gtod_data : AT AFTER(.jiffies) { *(.vsyscall_gtod_data) }
+  vsyscall_gtod_data = LOADADDR(.vsyscall_gtod_data);
+  .vsyscall_gtod_lock : AT AFTER(.vsyscall_gtod_data) { *(.vsyscall_gtod_lock) }
+  vsyscall_gtod_lock = LOADADDR(.vsyscall_gtod_lock);
+
+
   .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
   . = LOADADDR(.vsyscall_0) + 4096;
 
arch/x86_64/kernel/vsyscall.c +106 -6

150 lines not on this page · raw message

include/asm-i386/fixmap.h +6 -0
diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
@@ -27,6 +27,7 @@
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
+#include <asm/vsyscall-gtod.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
@@ -53,6 +54,11 @@
 enum fixed_addresses {
 	FIX_HOLE,
 	FIX_VSYSCALL,
+#ifdef CONFIG_NEWTOD_VSYSCALL
+	FIX_VSYSCALL_GTOD_LAST_PAGE,
+	FIX_VSYSCALL_GTOD_FIRST_PAGE = FIX_VSYSCALL_GTOD_LAST_PAGE
+					+ VSYSCALL_GTOD_NUMPAGES - 1,
+#endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
include/asm-i386/pgtable.h +4 -0
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
@@ -159,6 +159,8 @@
 #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_VSYSCALL \
+	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
@@ -166,6 +168,8 @@
 #define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
 #define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
 #define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+#define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL)
+#define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL|(__PAGE_KERNEL_RO | _PAGE_PCD))
 
 /*
  * The i386 can't do page protection for execute, and considers that
include/asm-i386/vsyscall-gtod.h new file +41 -0

41 lines not on this page · raw message

include/asm-x86_64/vsyscall.h +2 -0
diff -Nru a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
@@ -22,6 +22,8 @@
 #define __section_sysctl_vsyscall __attribute__ ((unused, __section__ (".sysctl_vsyscall"), aligned(16)))
 #define __section_xtime __attribute__ ((unused, __section__ (".xtime"), aligned(16)))
 #define __section_xtime_lock __attribute__ ((unused, __section__ (".xtime_lock"), aligned(16)))
+#define __section_vsyscall_gtod_data __attribute__ ((unused, __section__ (".vsyscall_gtod_data"),aligned(16)))
+#define __section_vsyscall_gtod_lock __attribute__ ((unused, __section__ (".vsyscall_gtod_lock"),aligned(16)))
 
 #define VXTIME_TSC	1
 #define VXTIME_HPET	2
kernel/timeofday.c +15 -1
diff -Nru a/kernel/timeofday.c b/kernel/timeofday.c
@@ -41,7 +41,6 @@
 *   o Added getnstimeofday
 *   o Cleanups from Nish Aravamudan
 * TODO List:
-*   o vsyscall/fsyscall infrastructure
 *   o clock_was_set hook
 **********************************************************************/
 
@@ -116,6 +115,12 @@
  */
 extern nsec_t read_persistent_clock(void);
 extern void sync_persistent_clock(struct timespec ts);
+#ifdef CONFIG_NEWTOD_VSYSCALL
+extern void arch_update_vsyscall_gtod(nsec_t wall_time, cycle_t offset_base,
+				struct timesource_t* timesource, int ntp_adj);
+#else
+#define arch_update_vsyscall_gtod(x,y,z,w) {}
+#endif
 
 
 /* get_lowres_timestamp():
@@ -282,6 +287,9 @@
 
 	update_legacy_time_values();
 
+	arch_update_vsyscall_gtod(system_time + wall_time_offset, offset_base,
+							timesource, ntp_adj);
+
 	write_sequnlock_irqrestore(&system_time_lock, flags);
 
 	return 0;
@@ -473,6 +481,9 @@
 	/* sync legacy values */
 	update_legacy_time_values();
 
+	arch_update_vsyscall_gtod(system_time + wall_time_offset, offset_base,
+							timesource, ntp_adj);
+
 	write_sequnlock_irqrestore(&system_time_lock, flags);
 
 	/* Set us up to go off on the next interval */
@@ -501,6 +512,9 @@
 	/* clear NTP scaling factor & state machine */
 	ntp_adj = 0;
 	ntp_clear();
+
+	arch_update_vsyscall_gtod(system_time + wall_time_offset, offset_base,
+							timesource, ntp_adj);
 
 	/* initialize legacy time values */
 	update_legacy_time_values();
#4 lore raw

Re: [RFC][PATCH (2/4)] new timeofday arch specific hooks (v A4)

In reply to john stultz

Hi!

Quoted 3 lines

ppc64 and s390. It applies on top of my linux-2.6.12-rc2_timeofday- core_A4 patch and with this patch applied, you can test the new time of day subsystem.

....

arch/i386/kernel/apm.c line 1210

Quoted 4 lines

device_power_down(PMSG_SUSPEND);

arch/i386/kernel/apm.c +1 -0
+	timeofday_suspend_hook();
 	/* serialize with the timer interrupt */

You should not add hooks like this. Just add your own [sys]_device.
Pavel

Signature · 1 line
64 bytes from 195.113.31.123: icmp_seq=28 ttl=51 time=448769.1 ms         
#5 lore raw

Re: [RFC][PATCH (2/4)] new timeofday arch specific hooks (v A4)

Quoted 5 lines · Pavel Machek

Hi!

Quoted 3 lines

ppc64 and s390. It applies on top of my linux-2.6.12-rc2_timeofday- core_A4 patch and with this patch applied, you can test the new time of day subsystem.

Quoted 7 lines

....

arch/i386/kernel/apm.c line 1210

Quoted 4 lines

device_power_down(PMSG_SUSPEND);

arch/i386/kernel/apm.c +1 -0
+	timeofday_suspend_hook();
 	/* serialize with the timer interrupt */

You should not add hooks like this. Just add your own [sys]_device.

Agreed. Sorry I didn't get to it the last time you mentioned it.

thanks
-john

#6 lore raw

RFC PATCH 1/1 new timeofday-based soft-timer subsystem

In reply to john stultz
Quoted 5 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patch attempts to being this process. I would greatly appreciate any comments.

Some design points:

1) The patch is small but does a lot.
a) Renames timer_jiffies to last_timer_time (now that we are not jiffies-based).
b) Converts the soft-timer time-vector's/bucket's entries to timerinterval (a new unit) width, instead of jiffy width.
c) Defines timerintervals to be the current time as reported by the new timeofday-subsystem shifted down by 20 bits and masked to only grab the lower 32 bits. This effectively emulates a 32-bit millisecond value.
d) Uses do_monotonic_clock() (converted to timerintervals) as the basis for addition and expiration instead of jiffies.
e) Adds some new helper functions for dealing with nanosecond values.

2) Currently, the patch is dependent upon John's timeofday core rework. For arches that will not have the new timeofday (or for which the rework is still in progress), I can emulate the existing system with a separate patch. The goal of this patch, though, is just to show how easy the new system can be implemented and the benefits.

3) The reason for the re-work?: Many people complain about all of the adding of 1 jiffy here or there to fix bugs. This new systems is fundamentally human-time oriented and deals with those issues correctly.

The code is reasonably well commented, but does expect readers to understand the current system to some degree.

This is my first posting of this re-work, so I expect criticism, but am happy to make changes.

Thanks,
Nish

include/linux/jiffies.h +31 -2
diff -urpN 2.6.12-rc2-tod2/include/linux/jiffies.h 2.6.12-rc2-tod2-timer/include/linux/jiffies.h
@@ -263,7 +263,7 @@ static inline unsigned int jiffies_to_ms
 #endif
 }
 
-static inline unsigned int jiffies_to_usecs(const unsigned long j)
+static inline unsigned long jiffies_to_usecs(const unsigned long j)
 {
 #if HZ <= 1000000 && !(1000000 % HZ)
 	return (1000000 / HZ) * j;
@@ -274,6 +274,17 @@ static inline unsigned int jiffies_to_us
 #endif
 }
 
+static inline nsec_t jiffies_to_nsecs(const unsigned long j)
+{
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	return (NSEC_PER_SEC / HZ) * (nsec_t)j;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return ((nsec_t)j + (HZ / NSEC_PER_SEC) - 1)/(HZ / NSEC_PER_SEC);
+#else
+	return ((nsec_t)j * NSEC_PER_SEC) / HZ;
+#endif
+}
+
 static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
 	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
@@ -287,7 +298,7 @@ static inline unsigned long msecs_to_jif
 #endif
 }
 
-static inline unsigned long usecs_to_jiffies(const unsigned int u)
+static inline unsigned long usecs_to_jiffies(const unsigned long u)
 {
 	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
 		return MAX_JIFFY_OFFSET;
@@ -300,6 +311,24 @@ static inline unsigned long usecs_to_jif
 #endif
 }
 
+static inline unsigned long nsecs_to_jiffies(const nsec_t n)
+{
+	nsec_t temp;
+	if (n > jiffies_to_nsecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= NSEC_PER_SEC && !(NSEC_PER_SEC % HZ)
+	temp = n + (NSEC_PER_SEC / HZ) - 1;
+	do_div(temp, (NSEC_PER_SEC / HZ));
+	return (unsigned long)temp;
+#elif HZ > NSEC_PER_SEC && !(HZ % NSEC_PER_SEC)
+	return n * (HZ / NSEC_PER_SEC);
+#else
+	temp = n * HZ + NSEC_PER_SEC - 1;
+	do_div(temp, NSEC_PER_SEC);
+	return (unsigned long)temp;
+#endif
+}
+
 /*
  * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
  * that a remainder subtract here would not do the right thing as the
include/linux/sched.h +6 -0
diff -urpN 2.6.12-rc2-tod2/include/linux/sched.h 2.6.12-rc2-tod2-timer/include/linux/sched.h
@@ -182,7 +182,13 @@ extern void scheduler_tick(void);
 extern int in_sched_functions(unsigned long addr);
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_NSECS	((nsec_t)(-1))
+#define	MAX_SCHEDULE_TIMEOUT_MSECS	ULONG_MAX
+#define	MAX_SCHEDULE_TIMEOUT_USECS	UINT_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
+extern nsec_t FASTCALL(schedule_timeout_nsecs(nsec_t timeout_nsecs));
+extern unsigned long FASTCALL(schedule_timeout_usecs(unsigned long timeout_usecs));
+extern unsigned int FASTCALL(schedule_timeout_msecs(unsigned int timeout_msesc));
 asmlinkage void schedule(void);
 
 struct namespace;
include/linux/timer.h +3 -18
diff -urpN 2.6.12-rc2-tod2/include/linux/timer.h 2.6.12-rc2-tod2-timer/include/linux/timer.h
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
+#include <linux/timeofday.h>
 
 struct tvec_t_base_s;
 
@@ -65,27 +66,11 @@ extern void add_timer_on(struct timer_li
 extern int del_timer(struct timer_list * timer);
 extern int __mod_timer(struct timer_list *timer, unsigned long expires);
 extern int mod_timer(struct timer_list *timer, unsigned long expires);
+extern void add_timer(struct timer_list *timer);
+extern int set_timer_nsecs(struct timer_list *timer, nsec_t expires_nsecs);
 
 extern unsigned long next_timer_interrupt(void);
 
-/***
- * add_timer - start a timer
- * @timer: the timer to be added
- *
- * The kernel will do a ->function(->data) callback from the
- * timer interrupt at the ->expired point in the future. The
- * current time is 'jiffies'.
- *
- * The timer's ->expired, ->function (and if the handler uses it, ->data)
- * fields must be set prior calling this function.
- *
- * Timers with an ->expired field in the past will be executed in the next
- * timer tick.
- */
-static inline void add_timer(struct timer_list * timer)
-{
-	__mod_timer(timer, timer->expires);
-}
 
 #ifdef CONFIG_SMP
   extern int del_timer_sync(struct timer_list *timer);
kernel/timer.c +190 -16

336 lines not on this page · raw message

#7 lore raw

Re: [RFC][PATCH] new timeofday-based soft-timer subsystem

Quoted 10 lines · Nishanth Aravamudan
Quoted 5 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

Quoted 5 lines

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patch attempts to being this process. I would greatly appreciate any comments.

Also working closely with John and Nish, I have been taking advantage of the new human-time soft-timer subsystem and the NO_IDLE_HZ code to dynamically schedule interrupts as needed. The idea is to have interrupt source drivers (PIT, Local APIC, HPET, ppc decrementers, etc) similar to the time sources in John's timeofday patches.

Because the resolution of the soft-timer sybsystem is configurable via TIMER_INTERVAL_BITS, and the timeofday code is now free of the periodic system tick, we can move the soft-timers to a dynamically scheduled interrupt system. We can achieve both sub-millisecond timer resolution and NO_IDLE_HZ simply by adjusting TIMER_INTERVAL_BITS and scheduling the next timer interrupt appropriately whenever a soft-timer is added or removed.

In general at the end of set_timer_nsecs(), we see when the next timer is due to expire and pass that value (in absolute nanoseconds) to schedule_next_timer_interrupt(). Each interrupt source driver is then free to reprogram the hard-timer to the "best" interval. For something like the local APIC, that may be exactly when the next timer needs to go off. For the PIT, it may do nothing at all and just fire periodically.

I have a prototype using the PIT, which just demonstrates that the system will still run this way. Obviously other timers will perform much better since the PIT is so slow to program.

I feel that this is a clean approach to two soft-timer issues: resolution and NO_IDLE_HZ. It integrates well with the patches from John and Nish and is a direct approach to these issues, rather than an attempt to add support on top of a jiffies based soft-timer subsystem.

I'd appreciate any feedback people have to offer. Particularly those that have been working on alternative approaches to things like high resolution timers and NO_IDLE_HZ.

Thanks,

Signature · 5 lines
Darren Hart
IBM Linux Technology Center
Linux Kernel Team
Phone: 503 578 3185
  T/L: 775 3185
#8 lore raw

Re: [RFC][PATCH] new timeofday-based soft-timer subsystem

In reply to Nishanth Aravamudan
Quoted 11 lines · Nishanth Aravamudan
Quoted 5 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patch attempts to being this process. I would greatly appreciate any comments.

I am not sure if anyone has looked at this patch closely, but I have noticed one issue: My code assumes that all the rounding will be done internally (rounding up on addition to find to the nearest timerinterval); however, current interfaces do much of the rounding before passing on structures on to the soft-timer subsystem, because the jiffies-based one always rounds down.

This is most clear in sys_nanosleep(). Without any modifications to the syscall, but with my patch applied, one will see around 5 millisecond sleeps for a 1 millisecond request. This occurs, I believe, because jiffies_to_timespec() rounds up once, we add one if there is any value and then in internally I round up once more. If I rewrite sys_nanosleep() to use schedule_timeout_nsecs() and thus never convert from nanoseconds, I see 2 millisecond sleeps for 1 millisecond requests, which is much closer (and accurate, as our granularity is slightly greater than 1 millisecond and we are interruptiing at HZ=1000 slightly more often than ever millisecond). This seems to be the right solution, but then there is another issue: the restart_block used by sys_nanosleep() only allows for 4 unsigned long arguments, when, in fact, nanoseconds are a 64-bit quantity in the kernel. As long as the nanosleep() request is no more than around 4 seconds, we should be ok using unsigned longs. But anything longer will simply truncate currently. I am not certain of a clean way to modify the restart_block to incorporate a 64-bit quantity, as it is used by other interfaces as well.

I still need to update the other version of nanosleep() (nsleep() and posix) before I post an updated patch. Just wanted to let everyone know of the issue.

Thanks,
Nish

#9 lore raw

Re: [RFC][PATCH] new timeofday-based soft-timer subsystem

Quoted 5 lines · Nishanth Aravamudan

but then there is another issue: the restart_block used by sys_nanosleep() only allows for 4 unsigned long arguments, when, in fact, nanoseconds are a 64-bit quantity in the kernel. As long as the nanosleep() request is no more than around 4 seconds, we should be ok using unsigned longs.

My man page for nanosleep specifies that the "nanoseconds" portion of the timespec must be under 1 billion and is of type "long". Is that no longer valid?

Chris

#10 lore raw

Re: [RFC][PATCH] new timeofday-based soft-timer subsystem

Quoted 11 lines · Chris Friesen
Quoted 5 lines · Nishanth Aravamudan

but then there is another issue: the restart_block used by sys_nanosleep() only allows for 4 unsigned long arguments, when, in fact, nanoseconds are a 64-bit quantity in the kernel. As long as the nanosleep() request is no more than around 4 seconds, we should be ok using unsigned longs.

My man page for nanosleep specifies that the "nanoseconds" portion of the timespec must be under 1 billion and is of type "long". Is that no longer valid?

Certainly would be, but the problem is if you pass in a timespec ts, where

    ts.tv_sec = 10;
    ts.tv_nsec = 99999;

This will overflow a 32-bit nanosecond representation internally (10000099999 > 4294967296). Sorry for the confusion, the unsigned long I was referring to was the internal representation of the nanoseconds converted from the timespec parameter.

Thanks,
Nish

#11 lore raw

Re: [RFC][PATCH] new timeofday-based soft-timer subsystem

In reply to Nishanth Aravamudan
Quoted 13 lines · Nishanth Aravamudan
Quoted 11 lines · Nishanth Aravamudan
Quoted 5 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

I have been working closely with John to re-work the soft-timer subsytem to use the new timeofday() subsystem. The following patch attempts to being this process. I would greatly appreciate any comments.

Quoted 6 lines

I am not sure if anyone has looked at this patch closely, but I have noticed one issue: My code assumes that all the rounding will be done internally (rounding up on addition to find to the nearest timerinterval); however, current interfaces do much of the rounding before passing on structures on to the soft-timer subsystem, because the jiffies-based one always rounds down.

A for instance: sys_nanosleep() assumes (correctly) that the jiffies-based soft-timer subsystem rounds down, so it rounds up (twice). But since I now round-up internally, that is not necessary. Fix sys_nanosleep() to do this right.

Still todo: change restart->arg0 to be a pointer to an nsec_t.

kernel/timer.c +11 -11
diff -urpN 2.6.12-rc2-tod/kernel/timer.c 2.6.12-rc2-tod-timer/kernel/timer.c
@@ -1141,21 +1311,21 @@ asmlinkage long sys_gettid(void)
 
 static long __sched nanosleep_restart(struct restart_block *restart)
 {
-	unsigned long expire = restart->arg0, now = jiffies;
+	nsec_t expire = restart->arg0, now = do_monotonic_clock();
 	struct timespec __user *rmtp = (struct timespec __user *) restart->arg1;
 	long ret;
 
 	/* Did it expire while we handled signals? */
-	if (!time_after(expire, now))
+	if (now > expire)
 		return 0;
 
-	current->state = TASK_INTERRUPTIBLE;
-	expire = schedule_timeout(expire - now);
+	set_current_state(TASK_INTERRUPTIBLE);
+	expire = schedule_timeout_nsecs(expire - now);
 
 	ret = 0;
 	if (expire) {
 		struct timespec t;
-		jiffies_to_timespec(expire, &t);
+		t = ns2timespec(expire);
 
 		ret = -ERESTART_RESTARTBLOCK;
 		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
@@ -1168,7 +1338,7 @@ static long __sched nanosleep_restart(st
 asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
 {
 	struct timespec t;
-	unsigned long expire;
+	nsec_t expire;
 	long ret;
 
 	if (copy_from_user(&t, rqtp, sizeof(t)))
@@ -1177,20 +1347,20 @@ asmlinkage long sys_nanosleep(struct tim
 	if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
 		return -EINVAL;
 
-	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-	current->state = TASK_INTERRUPTIBLE;
-	expire = schedule_timeout(expire);
+	expire = timespec2ns(&t);
+	set_current_state(TASK_INTERRUPTIBLE);
+	expire = schedule_timeout_nsecs(expire);
 
 	ret = 0;
 	if (expire) {
 		struct restart_block *restart;
-		jiffies_to_timespec(expire, &t);
+		t = ns2timespec(expire);
 		if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
 			return -EFAULT;
 
 		restart = &current_thread_info()->restart_block;
 		restart->fn = nanosleep_restart;
-		restart->arg0 = jiffies + expire;
+		restart->arg0 = do_monotonic_clock() + expire;
 		restart->arg1 = (unsigned long) rmtp;
 		ret = -ERESTART_RESTARTBLOCK;
 	}
#12 lore raw
In reply to john stultz

Ack. At the last minute I accidentally committed a line I didn't mean to, so the timeofday-core_A4 patch doesn't build.

This patch fixes the problem. Please use it instead.

linux-2.6.12-rc2_timeofday-core_A4fix.patch
===========================================

drivers/Makefile +1 -0
diff -Nru a/drivers/Makefile b/drivers/Makefile
@@ -64,3 +64,4 @@
 obj-$(CONFIG_BLK_DEV_SGIIOC4)	+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
+obj-$(CONFIG_NEWTOD)		+= timesource/
drivers/timesource/Makefile new file +1 -0
diff -Nru a/drivers/timesource/Makefile b/drivers/timesource/Makefile
@@ -0,0 +1 @@
+obj-y += jiffies.o
drivers/timesource/jiffies.c new file +45 -0

45 lines not on this page · raw message

include/linux/ntp.h new file +22 -0
diff -Nru a/include/linux/ntp.h b/include/linux/ntp.h
@@ -0,0 +1,22 @@
+/*  linux/include/linux/ntp.h
+ *
+ *  Copyright (C) 2003, 2004, 2005 IBM, John Stultz ([email protected])
+ *
+ *  This file NTP state machine accessor functions.
+ */
+
+#ifndef _LINUX_NTP_H
+#define _LINUX_NTP_H
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+/* NTP state machine interfaces */
+nsec_t ntp_scale(nsec_t value);
+int ntp_advance(nsec_t value);
+int ntp_adjtimex(struct timex*);
+int ntp_leapsecond(struct timespec now);
+void ntp_clear(void);
+int get_ntp_status(void);
+
+#endif
include/linux/time.h +4 -0
diff -Nru a/include/linux/time.h b/include/linux/time.h
@@ -27,6 +27,10 @@
 
 #ifdef __KERNEL__
 
+/* timeofday base types */
+typedef u64 nsec_t;
+typedef u64 cycle_t;
+
 /* Parameters used to convert the timespec values */
 #ifndef USEC_PER_SEC
 #define USEC_PER_SEC (1000000L)
include/linux/timeofday.h new file +65 -0

65 lines not on this page · raw message

include/linux/timesource.h new file +159 -0

159 lines not on this page · raw message

init/main.c +2 -0
diff -Nru a/init/main.c b/init/main.c
@@ -47,6 +47,7 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/timeofday.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -467,6 +468,7 @@
 	pidhash_init();
 	init_timers();
 	softirq_init();
+	timeofday_init();
 	time_init();
 
 	/*
kernel/Makefile +1 -0
diff -Nru a/kernel/Makefile b/kernel/Makefile
@@ -9,6 +9,7 @@
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
 
+obj-$(CONFIG_NEWTOD) += timeofday.o timesource.o ntp.o
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
kernel/ntp.c new file +500 -0

500 lines not on this page · raw message

kernel/time.c +5 -0
diff -Nru a/kernel/time.c b/kernel/time.c
@@ -38,6 +38,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <linux/timeofday.h>
 
 /* 
  * The timezone where the local system is located.  Used as a default by some
@@ -227,6 +228,7 @@
 /* adjtimex mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
+#ifndef CONFIG_NEWTOD
 int do_adjtimex(struct timex *txc)
 {
         long ltemp, mtemp, save_adjust;
@@ -410,6 +412,7 @@
 	notify_arch_cmos_timer();
 	return(result);
 }
+#endif
 
 asmlinkage long sys_adjtimex(struct timex __user *txc_p)
 {
@@ -566,6 +569,7 @@
 
 
 #else
+#ifndef CONFIG_NEWTOD
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
  * and therefore only yields usec accuracy
@@ -578,6 +582,7 @@
 	tv->tv_sec = x.tv_sec;
 	tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
 }
+#endif /* CONFIG_NEWTOD */
 #endif
 
 #if (BITS_PER_LONG < 64)
kernel/timeofday.c new file +521 -0

521 lines not on this page · raw message

kernel/timer.c +4 -0
diff -Nru a/kernel/timer.c b/kernel/timer.c
@@ -577,6 +577,7 @@
 int tickadj = 500/HZ ? : 1;		/* microsecs */
 
 
+#ifndef CONFIG_NEWTOD
 /*
  * phase-lock loop variables
  */
@@ -807,6 +808,9 @@
 		}
 	} while (ticks);
 }
+#else /* CONFIG_NEWTOD */
+#define update_wall_time(x)
+#endif /* CONFIG_NEWTOD */
 
 /*
  * Called from the timer interrupt handler to charge one tick to the current 
kernel/timesource.c new file +210 -0

210 lines not on this page · raw message

#13 lore raw
In reply to john stultz
Quoted 18 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

Mostly this version is just a cleanup of the last release. One neat feature is the new sysfs interface which allows you to manually override the selected timesource while the system is running.

Included below is timeofday.c (which includes all the time of day management and accessor functions), ntp.c (which includes the ntp scaling calculation code, leapsecond processing, and ntp kernel state machine code), timesource.c (for timesource specific management functions), interface definition .h files, the example jiffies timesource (lowest common denominator time source, mainly for use as example code) and minimal hooks into arch independent code.

Quoted 3 lines

The patch does not function without minimal architecture specific hooks (i386, x86-64, ppc32, ppc64, ia64 and s390 examples to follow), and it should be able to be applied to a tree without affecting the code.

My concern at this point is how to deal with the userland gettimofday implementation in the ppc64 vDSO ...

Ben.

#14 lore raw
Quoted 19 lines · Benjamin Herrenschmidt
Quoted 18 lines · john stultz

All,
This patch implements the architecture independent portion of
the time of day subsystem. For a brief description on the rework, see
here: http://lwn.net/Articles/120850/ (Many thanks to the LWN team for that clear writeup!)

Mostly this version is just a cleanup of the last release. One neat feature is the new sysfs interface which allows you to manually override the selected timesource while the system is running.

Included below is timeofday.c (which includes all the time of day management and accessor functions), ntp.c (which includes the ntp scaling calculation code, leapsecond processing, and ntp kernel state machine code), timesource.c (for timesource specific management functions), interface definition .h files, the example jiffies timesource (lowest common denominator time source, mainly for use as example code) and minimal hooks into arch independent code.

Quoted 6 lines
Quoted 3 lines

The patch does not function without minimal architecture specific hooks (i386, x86-64, ppc32, ppc64, ia64 and s390 examples to follow), and it should be able to be applied to a tree without affecting the code.

My concern at this point is how to deal with the userland gettimofday implementation in the ppc64 vDSO ...

Hopefully in a method very similar to the way the vsyscall patch does for i386/x86-64. The idea being that the core code makes an arch specific call passing the core timekeeping values whenever they are changed. Then the arch specific implementation can use those values in a similar fashion to calculate time.

I'm not very familiar with ppc64's vDSO implementation, so please let me know if there is a constraint that would make this difficult.

thanks
-john