From affd1003494c5e0ce4c446087be92dd00fa2ea4c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 20 Jun 2010 19:03:08 +0000 Subject: [PATCH] --- yaml --- r: 206153 b: refs/heads/master c: 0e469db8f70c2645acdc90981c0480a3e19d5e68 h: refs/heads/master i: 206151: 4ebb953f79c7e981f0e07b2dceb8d23492ee3dad v: v3 --- [refs] | 2 +- .../feature-removal-schedule.txt | 10 + trunk/Documentation/kernel-parameters.txt | 3 +- trunk/arch/alpha/Kconfig | 4 + trunk/arch/arm/Kconfig | 4 + trunk/arch/avr32/Kconfig | 3 + trunk/arch/blackfin/Kconfig | 3 + trunk/arch/cris/Kconfig | 3 + trunk/arch/frv/Kconfig | 4 + trunk/arch/h8300/Kconfig | 4 + trunk/arch/ia64/Kconfig | 4 + trunk/arch/ia64/kernel/time.c | 7 +- trunk/arch/m32r/Kconfig | 3 + trunk/arch/m68k/Kconfig | 3 + trunk/arch/m68knommu/Kconfig | 4 + trunk/arch/microblaze/Kconfig | 3 + trunk/arch/mips/Kconfig | 4 + trunk/arch/mn10300/Kconfig | 3 + trunk/arch/parisc/Kconfig | 4 + trunk/arch/powerpc/Kconfig | 3 + .../arch/powerpc/include/asm/vdso_datapage.h | 2 + trunk/arch/powerpc/kernel/asm-offsets.c | 1 + trunk/arch/powerpc/kernel/time.c | 58 +++--- .../arch/powerpc/kernel/vdso32/gettimeofday.S | 184 ++++-------------- .../arch/powerpc/kernel/vdso64/gettimeofday.S | 88 ++------- trunk/arch/s390/Kconfig | 3 + trunk/arch/s390/kernel/time.c | 8 +- trunk/arch/score/Kconfig | 3 + trunk/arch/sh/Kconfig | 3 + trunk/arch/sparc/Kconfig | 3 + trunk/arch/um/Kconfig.common | 4 + trunk/arch/um/kernel/time.c | 13 +- trunk/arch/x86/Kconfig | 5 +- trunk/arch/x86/kernel/hpet.c | 13 +- trunk/arch/x86/kernel/tsc.c | 5 +- trunk/arch/x86/kernel/vsyscall_64.c | 17 +- trunk/arch/xtensa/Kconfig | 3 + trunk/drivers/Makefile | 4 +- trunk/drivers/acpi/acpi_pad.c | 2 +- trunk/drivers/acpi/processor_idle.c | 2 +- trunk/drivers/clocksource/acpi_pm.c | 9 +- trunk/drivers/misc/Kconfig | 4 +- trunk/include/linux/clocksource.h | 17 +- trunk/include/linux/time.h | 21 +- trunk/kernel/hrtimer.c | 9 +- trunk/kernel/time.c | 16 ++ trunk/kernel/time/Kconfig | 4 +- trunk/kernel/time/clocksource.c | 33 +--- trunk/kernel/time/timekeeping.c | 79 ++++++-- trunk/kernel/trace/Kconfig | 4 +- 50 files changed, 327 insertions(+), 368 deletions(-) diff --git a/[refs] b/[refs] index 4ee8d0584505..d40d93332a67 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 852db46d55e85b475a72e665ca08d3317769ceef +refs/heads/master: 0e469db8f70c2645acdc90981c0480a3e19d5e68 diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index cd648dbb5146..1571c0c83dba 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -549,6 +549,16 @@ Who: Avi Kivity ---------------------------- +What: xtime, wall_to_monotonic +When: 2.6.36+ +Files: kernel/time/timekeeping.c include/linux/time.h +Why: Cleaning up timekeeping internal values. Please use + existing timekeeping accessor functions to access + the equivalent functionality. +Who: John Stultz + +---------------------------- + What: KVM kernel-allocated memory slots When: July 2010 Why: Since 2.6.25, kvm supports user-allocated memory slots, which are diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 8abdfd7cb571..2b2407d9a6d0 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -73,6 +73,7 @@ parameter is applicable: MTD MTD (Memory Technology Device) support is enabled. NET Appropriate network support is enabled. NUMA NUMA support is enabled. + GENERIC_TIME The generic timeofday code is enabled. NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. PV_OPS A paravirtualized kernel is enabled. @@ -467,7 +468,7 @@ and is between 256 and 4096 characters. It is defined in the file clocksource is not available, it defaults to PIT. Format: { pit | tsc | cyclone | pmtmr } - clocksource= Override the default clocksource + clocksource= [GENERIC_TIME] Override the default clocksource Format: Override the default clocksource and use the clocksource with the name specified. diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index b9647bb66d13..3e2e540a0f2a 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -47,6 +47,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + bool + default y + config GENERIC_CMOS_UPDATE def_bool y diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 655b4ae76314..98922f7d2d12 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -41,6 +41,10 @@ config SYS_SUPPORTS_APM_EMULATION config GENERIC_GPIO bool +config GENERIC_TIME + bool + default y + config ARCH_USES_GETTIMEOFFSET bool default n diff --git a/trunk/arch/avr32/Kconfig b/trunk/arch/avr32/Kconfig index f51572772e21..f2b319333184 100644 --- a/trunk/arch/avr32/Kconfig +++ b/trunk/arch/avr32/Kconfig @@ -45,6 +45,9 @@ config GENERIC_IRQ_PROBE config RWSEM_GENERIC_SPINLOCK def_bool y +config GENERIC_TIME + def_bool y + config GENERIC_CLOCKEVENTS def_bool y diff --git a/trunk/arch/blackfin/Kconfig b/trunk/arch/blackfin/Kconfig index c88fd3584122..f66294b4f9d2 100644 --- a/trunk/arch/blackfin/Kconfig +++ b/trunk/arch/blackfin/Kconfig @@ -614,6 +614,9 @@ comment "Kernel Timer/Scheduler" source kernel/Kconfig.hz +config GENERIC_TIME + def_bool y + config GENERIC_CLOCKEVENTS bool "Generic clock events" default y diff --git a/trunk/arch/cris/Kconfig b/trunk/arch/cris/Kconfig index 887ef855be2a..e25bf4440b51 100644 --- a/trunk/arch/cris/Kconfig +++ b/trunk/arch/cris/Kconfig @@ -20,6 +20,9 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config GENERIC_TIME + def_bool y + config GENERIC_CMOS_UPDATE def_bool y diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index 16399bd24993..4b5830bcbe2e 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -40,6 +40,10 @@ config GENERIC_HARDIRQS_NO__DO_IRQ bool default y +config GENERIC_TIME + bool + default y + config TIME_LOW_RES bool default y diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 988b6ff34cc4..53cc669e6d59 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -62,6 +62,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + bool + default y + config GENERIC_BUG bool depends on BUG diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 8711d13cd79f..95610820041e 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -82,6 +82,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + bool + default y + config GENERIC_TIME_VSYSCALL bool default y diff --git a/trunk/arch/ia64/kernel/time.c b/trunk/arch/ia64/kernel/time.c index ed6f22eb5b12..653b3c46ea82 100644 --- a/trunk/arch/ia64/kernel/time.c +++ b/trunk/arch/ia64/kernel/time.c @@ -471,8 +471,7 @@ void update_vsyscall_tz(void) { } -void update_vsyscall(struct timespec *wall, struct timespec *wtm, - struct clocksource *c, u32 mult) +void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult) { unsigned long flags; @@ -488,9 +487,9 @@ void update_vsyscall(struct timespec *wall, struct timespec *wtm, /* copy kernel time structures */ fsyscall_gtod_data.wall_time.tv_sec = wall->tv_sec; fsyscall_gtod_data.wall_time.tv_nsec = wall->tv_nsec; - fsyscall_gtod_data.monotonic_time.tv_sec = wtm->tv_sec + fsyscall_gtod_data.monotonic_time.tv_sec = wall_to_monotonic.tv_sec + wall->tv_sec; - fsyscall_gtod_data.monotonic_time.tv_nsec = wtm->tv_nsec + fsyscall_gtod_data.monotonic_time.tv_nsec = wall_to_monotonic.tv_nsec + wall->tv_nsec; /* normalize */ diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index 836abbbc9c04..3a9319f93e89 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -44,6 +44,9 @@ config HZ int default 100 +config GENERIC_TIME + def_bool y + config ARCH_USES_GETTIMEOFFSET def_bool y diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 8030e2481d97..2e3737b92ffc 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -59,6 +59,9 @@ config HZ int default 100 +config GENERIC_TIME + def_bool y + config ARCH_USES_GETTIMEOFFSET def_bool y diff --git a/trunk/arch/m68knommu/Kconfig b/trunk/arch/m68knommu/Kconfig index 2609c394e1df..efeb6033fc17 100644 --- a/trunk/arch/m68knommu/Kconfig +++ b/trunk/arch/m68knommu/Kconfig @@ -63,6 +63,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + bool + default y + config GENERIC_CMOS_UPDATE bool default y diff --git a/trunk/arch/microblaze/Kconfig b/trunk/arch/microblaze/Kconfig index 14f03cea94a1..505a08592423 100644 --- a/trunk/arch/microblaze/Kconfig +++ b/trunk/arch/microblaze/Kconfig @@ -48,6 +48,9 @@ config GENERIC_IRQ_PROBE config GENERIC_CALIBRATE_DELAY def_bool y +config GENERIC_TIME + def_bool y + config GENERIC_TIME_VSYSCALL def_bool n diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 01c44cbdf163..cdaae942623d 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -733,6 +733,10 @@ config GENERIC_CLOCKEVENTS bool default y +config GENERIC_TIME + bool + default y + config GENERIC_CMOS_UPDATE bool default y diff --git a/trunk/arch/mn10300/Kconfig b/trunk/arch/mn10300/Kconfig index 444b9f918fdf..1c4565a9102b 100644 --- a/trunk/arch/mn10300/Kconfig +++ b/trunk/arch/mn10300/Kconfig @@ -46,6 +46,9 @@ config GENERIC_FIND_NEXT_BIT config GENERIC_HWEIGHT def_bool y +config GENERIC_TIME + def_bool y + config GENERIC_BUG def_bool y diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index 907417d187e1..05a366a5c4d5 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -66,6 +66,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_TIME + bool + default y + config TIME_LOW_RES bool depends on SMP diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 25e6bf457457..2031a2846865 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -29,6 +29,9 @@ config MMU config GENERIC_CMOS_UPDATE def_bool y +config GENERIC_TIME + def_bool y + config GENERIC_TIME_VSYSCALL def_bool y diff --git a/trunk/arch/powerpc/include/asm/vdso_datapage.h b/trunk/arch/powerpc/include/asm/vdso_datapage.h index 13c2c283e178..08679c5319b8 100644 --- a/trunk/arch/powerpc/include/asm/vdso_datapage.h +++ b/trunk/arch/powerpc/include/asm/vdso_datapage.h @@ -85,6 +85,7 @@ struct vdso_data { __s32 wtom_clock_sec; /* Wall to monotonic clock */ __s32 wtom_clock_nsec; struct timespec stamp_xtime; /* xtime as at tb_orig_stamp */ + __u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */ __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ }; @@ -105,6 +106,7 @@ struct vdso_data { __s32 wtom_clock_sec; /* Wall to monotonic clock */ __s32 wtom_clock_nsec; struct timespec stamp_xtime; /* xtime as at tb_orig_stamp */ + __u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ __u32 dcache_block_size; /* L1 d-cache block size */ __u32 icache_block_size; /* L1 i-cache block size */ diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c index 496cc5b3984f..acbbac6aaa22 100644 --- a/trunk/arch/powerpc/kernel/asm-offsets.c +++ b/trunk/arch/powerpc/kernel/asm-offsets.c @@ -342,6 +342,7 @@ int main(void) DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec)); DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime)); + DEFINE(STAMP_SEC_FRAC, offsetof(struct vdso_data, stamp_sec_fraction)); DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size)); DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size)); DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size)); diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index e215f76bba1c..5adebaf47f13 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -849,25 +849,10 @@ static cycle_t timebase_read(struct clocksource *cs) return (cycle_t)get_tb(); } -void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, - struct clocksource *clock, u32 mult) +static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, + u64 new_tb_to_xs, struct timespec *now, + u32 frac_sec) { - u64 new_tb_to_xs, new_stamp_xsec; - - if (clock != &clocksource_timebase) - return; - - /* Make userspace gettimeofday spin until we're done. */ - ++vdso_data->tb_update_count; - smp_mb(); - - /* XXX this assumes clock->shift == 22 */ - /* 4611686018 ~= 2^(20+64-22) / 1e9 */ - new_tb_to_xs = (u64) mult * 4611686018ULL; - new_stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC; - do_div(new_stamp_xsec, 1000000000); - new_stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC; - /* * tb_update_count is used to allow the userspace gettimeofday code * to assure itself that it sees a consistent view of the tb_to_xs and @@ -879,16 +864,43 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, * We expect the caller to have done the first increment of * vdso_data->tb_update_count already. */ - vdso_data->tb_orig_stamp = clock->cycle_last; + vdso_data->tb_orig_stamp = new_tb_stamp; vdso_data->stamp_xsec = new_stamp_xsec; vdso_data->tb_to_xs = new_tb_to_xs; - vdso_data->wtom_clock_sec = wtm->tv_sec; - vdso_data->wtom_clock_nsec = wtm->tv_nsec; - vdso_data->stamp_xtime = *wall_time; + vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; + vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; + vdso_data->stamp_xtime = *now; + vdso_data->stamp_sec_fraction = frac_sec; smp_wmb(); ++(vdso_data->tb_update_count); } +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) +{ + u64 t2x, stamp_xsec; + u32 frac_sec; + + if (clock != &clocksource_timebase) + return; + + /* Make userspace gettimeofday spin until we're done. */ + ++vdso_data->tb_update_count; + smp_mb(); + + /* XXX this assumes clock->shift == 22 */ + /* 4611686018 ~= 2^(20+64-22) / 1e9 */ + t2x = (u64) mult * 4611686018ULL; + stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC; + do_div(stamp_xsec, 1000000000); + stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC; + + BUG_ON(wall_time->tv_nsec >= NSEC_PER_SEC); + /* this is tv_nsec / 1e9 as a 0.32 fraction */ + frac_sec = ((u64) wall_time->tv_nsec * 18446744073ULL) >> 32; + update_gtod(clock->cycle_last, stamp_xsec, t2x, wall_time, frac_sec); +} + void update_vsyscall_tz(void) { /* Make userspace gettimeofday spin until we're done. */ @@ -1093,7 +1105,7 @@ void __init time_init(void) vdso_data->tb_orig_stamp = tb_last_jiffy; vdso_data->tb_update_count = 0; vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; - vdso_data->stamp_xsec = (u64) get_seconds() * XSEC_PER_SEC; + vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; vdso_data->tb_to_xs = tb_to_xs; write_sequnlock_irqrestore(&xtime_lock, flags); diff --git a/trunk/arch/powerpc/kernel/vdso32/gettimeofday.S b/trunk/arch/powerpc/kernel/vdso32/gettimeofday.S index ee038d4bf252..4ee09ee2e836 100644 --- a/trunk/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/trunk/arch/powerpc/kernel/vdso32/gettimeofday.S @@ -19,8 +19,10 @@ /* Offset for the low 32-bit part of a field of long type */ #ifdef CONFIG_PPC64 #define LOPART 4 +#define TSPEC_TV_SEC TSPC64_TV_SEC+LOPART #else #define LOPART 0 +#define TSPEC_TV_SEC TSPC32_TV_SEC #endif .text @@ -41,23 +43,11 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) mr r9, r3 /* datapage ptr in r9 */ cmplwi r10,0 /* check if tv is NULL */ beq 3f - bl __do_get_xsec@local /* get xsec from tb & kernel */ - bne- 2f /* out of line -> do syscall */ - - /* seconds are xsec >> 20 */ - rlwinm r5,r4,12,20,31 - rlwimi r5,r3,12,0,19 - stw r5,TVAL32_TV_SEC(r10) - - /* get remaining xsec and convert to usec. we scale - * up remaining xsec by 12 bits and get the top 32 bits - * of the multiplication - */ - rlwinm r5,r4,12,0,19 - lis r6,1000000@h - ori r6,r6,1000000@l - mulhwu r5,r5,r6 - stw r5,TVAL32_TV_USEC(r10) + lis r7,1000000@ha /* load up USEC_PER_SEC */ + addi r7,r7,1000000@l /* so we get microseconds in r4 */ + bl __do_get_tspec@local /* get sec/usec from tb & kernel */ + stw r3,TVAL32_TV_SEC(r10) + stw r4,TVAL32_TV_USEC(r10) 3: cmplwi r11,0 /* check if tz is NULL */ beq 1f @@ -70,14 +60,6 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) crclr cr0*4+so li r3,0 blr - -2: - mtlr r12 - mr r3,r10 - mr r4,r11 - li r0,__NR_gettimeofday - sc - blr .cfi_endproc V_FUNCTION_END(__kernel_gettimeofday) @@ -100,7 +82,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) mr r11,r4 /* r11 saves tp */ bl __get_datapage@local /* get data page */ mr r9,r3 /* datapage ptr in r9 */ - + lis r7,NSEC_PER_SEC@h /* want nanoseconds */ + ori r7,r7,NSEC_PER_SEC@l 50: bl __do_get_tspec@local /* get sec/nsec from tb & kernel */ bne cr1,80f /* not monotonic -> all done */ @@ -198,83 +181,12 @@ V_FUNCTION_END(__kernel_clock_getres) /* - * This is the core of gettimeofday() & friends, it returns the xsec - * value in r3 & r4 and expects the datapage ptr (non clobbered) - * in r9. clobbers r0,r4,r5,r6,r7,r8. - * When returning, r8 contains the counter value that can be reused - * by the monotonic clock implementation - */ -__do_get_xsec: - .cfi_startproc - /* Check for update count & load values. We use the low - * order 32 bits of the update count - */ -1: lwz r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9) - andi. r0,r8,1 /* pending update ? loop */ - bne- 1b - xor r0,r8,r8 /* create dependency */ - add r9,r9,r0 - - /* Load orig stamp (offset to TB) */ - lwz r5,CFG_TB_ORIG_STAMP(r9) - lwz r6,(CFG_TB_ORIG_STAMP+4)(r9) - - /* Get a stable TB value */ -2: mftbu r3 - mftbl r4 - mftbu r0 - cmpl cr0,r3,r0 - bne- 2b - - /* Substract tb orig stamp. If the high part is non-zero, we jump to - * the slow path which call the syscall. - * If it's ok, then we have our 32 bits tb_ticks value in r7 - */ - subfc r7,r6,r4 - subfe. r0,r5,r3 - bne- 3f - - /* Load scale factor & do multiplication */ - lwz r5,CFG_TB_TO_XS(r9) /* load values */ - lwz r6,(CFG_TB_TO_XS+4)(r9) - mulhwu r4,r7,r5 - mulhwu r6,r7,r6 - mullw r0,r7,r5 - addc r6,r6,r0 - - /* At this point, we have the scaled xsec value in r4 + XER:CA - * we load & add the stamp since epoch - */ - lwz r5,CFG_STAMP_XSEC(r9) - lwz r6,(CFG_STAMP_XSEC+4)(r9) - adde r4,r4,r6 - addze r3,r5 - - /* We now have our result in r3,r4. We create a fake dependency - * on that result and re-check the counter - */ - or r6,r4,r3 - xor r0,r6,r6 - add r9,r9,r0 - lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) - cmpl cr0,r8,r0 /* check if updated */ - bne- 1b - - /* Warning ! The caller expects CR:EQ to be set to indicate a - * successful calculation (so it won't fallback to the syscall - * method). We have overriden that CR bit in the counter check, - * but fortunately, the loop exit condition _is_ CR:EQ set, so - * we can exit safely here. If you change this code, be careful - * of that side effect. - */ -3: blr - .cfi_endproc - -/* - * This is the core of clock_gettime(), it returns the current - * time in seconds and nanoseconds in r3 and r4. + * This is the core of clock_gettime() and gettimeofday(), + * it returns the current time in r3 (seconds) and r4. + * On entry, r7 gives the resolution of r4, either USEC_PER_SEC + * or NSEC_PER_SEC, giving r4 in microseconds or nanoseconds. * It expects the datapage ptr in r9 and doesn't clobber it. - * It clobbers r0, r5, r6, r10 and returns NSEC_PER_SEC in r7. + * It clobbers r0, r5 and r6. * On return, r8 contains the counter value that can be reused. * This clobbers cr0 but not any other cr field. */ @@ -297,70 +209,58 @@ __do_get_tspec: 2: mftbu r3 mftbl r4 mftbu r0 - cmpl cr0,r3,r0 + cmplw cr0,r3,r0 bne- 2b /* Subtract tb orig stamp and shift left 12 bits. */ - subfc r7,r6,r4 + subfc r4,r6,r4 subfe r0,r5,r3 slwi r0,r0,12 - rlwimi. r0,r7,12,20,31 - slwi r7,r7,12 + rlwimi. r0,r4,12,20,31 + slwi r4,r4,12 - /* Load scale factor & do multiplication */ + /* + * Load scale factor & do multiplication. + * We only use the high 32 bits of the tb_to_xs value. + * Even with a 1GHz timebase clock, the high 32 bits of + * tb_to_xs will be at least 4 million, so the error from + * ignoring the low 32 bits will be no more than 0.25ppm. + * The error will just make the clock run very very slightly + * slow until the next time the kernel updates the VDSO data, + * at which point the clock will catch up to the kernel's value, + * so there is no long-term error accumulation. + */ lwz r5,CFG_TB_TO_XS(r9) /* load values */ - lwz r6,(CFG_TB_TO_XS+4)(r9) - mulhwu r3,r7,r6 - mullw r10,r7,r5 - mulhwu r4,r7,r5 - addc r10,r3,r10 + mulhwu r4,r4,r5 li r3,0 beq+ 4f /* skip high part computation if 0 */ mulhwu r3,r0,r5 - mullw r7,r0,r5 - mulhwu r5,r0,r6 - mullw r6,r0,r6 - adde r4,r4,r7 - addze r3,r3 + mullw r5,r0,r5 addc r4,r4,r5 addze r3,r3 - addc r10,r10,r6 - -4: addze r4,r4 /* add in carry */ - lis r7,NSEC_PER_SEC@h - ori r7,r7,NSEC_PER_SEC@l - mulhwu r4,r4,r7 /* convert to nanoseconds */ - - /* At this point, we have seconds & nanoseconds since the xtime - * stamp in r3+CA and r4. Load & add the xtime stamp. +4: + /* At this point, we have seconds since the xtime stamp + * as a 32.32 fixed-point number in r3 and r4. + * Load & add the xtime stamp. */ -#ifdef CONFIG_PPC64 - lwz r5,STAMP_XTIME+TSPC64_TV_SEC+LOPART(r9) - lwz r6,STAMP_XTIME+TSPC64_TV_NSEC+LOPART(r9) -#else - lwz r5,STAMP_XTIME+TSPC32_TV_SEC(r9) - lwz r6,STAMP_XTIME+TSPC32_TV_NSEC(r9) -#endif - add r4,r4,r6 + lwz r5,STAMP_XTIME+TSPEC_TV_SEC(r9) + lwz r6,STAMP_SEC_FRAC(r9) + addc r4,r4,r6 adde r3,r3,r5 - /* We now have our result in r3,r4. We create a fake dependency - * on that result and re-check the counter + /* We create a fake dependency on the result in r3/r4 + * and re-check the counter */ or r6,r4,r3 xor r0,r6,r6 add r9,r9,r0 lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) - cmpl cr0,r8,r0 /* check if updated */ + cmplw cr0,r8,r0 /* check if updated */ bne- 1b - /* check for nanosecond overflow and adjust if necessary */ - cmpw r4,r7 - bltlr /* all done if no overflow */ - subf r4,r7,r4 /* adjust if overflow */ - addi r3,r3,1 + mulhwu r4,r4,r7 /* convert to micro or nanoseconds */ blr .cfi_endproc diff --git a/trunk/arch/powerpc/kernel/vdso64/gettimeofday.S b/trunk/arch/powerpc/kernel/vdso64/gettimeofday.S index 262cd5857a56..e97a9a0dc4ac 100644 --- a/trunk/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/trunk/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -33,18 +33,11 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) bl V_LOCAL_FUNC(__get_datapage) /* get data page */ cmpldi r11,0 /* check if tv is NULL */ beq 2f - bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ - lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ - ori r7,r7,16960 - rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ - rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ - std r5,TVAL64_TV_SEC(r11) /* store sec in tv */ - subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ - mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / - * XSEC_PER_SEC - */ - rldicl r0,r0,44,20 - std r0,TVAL64_TV_USEC(r11) /* store usec in tv */ + lis r7,1000000@ha /* load up USEC_PER_SEC */ + addi r7,r7,1000000@l + bl V_LOCAL_FUNC(__do_get_tspec) /* get sec/us from tb & kernel */ + std r4,TVAL64_TV_SEC(r11) /* store sec in tv */ + std r5,TVAL64_TV_USEC(r11) /* store usec in tv */ 2: cmpldi r10,0 /* check if tz is NULL */ beq 1f lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */ @@ -77,6 +70,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) .cfi_register lr,r12 mr r11,r4 /* r11 saves tp */ bl V_LOCAL_FUNC(__get_datapage) /* get data page */ + lis r7,NSEC_PER_SEC@h /* want nanoseconds */ + ori r7,r7,NSEC_PER_SEC@l 50: bl V_LOCAL_FUNC(__do_get_tspec) /* get time from tb & kernel */ bne cr1,80f /* if not monotonic, all done */ @@ -171,49 +166,12 @@ V_FUNCTION_END(__kernel_clock_getres) /* - * This is the core of gettimeofday(), it returns the xsec - * value in r4 and expects the datapage ptr (non clobbered) - * in r3. clobbers r0,r4,r5,r6,r7,r8 - * When returning, r8 contains the counter value that can be reused - */ -V_FUNCTION_BEGIN(__do_get_xsec) - .cfi_startproc - /* check for update count & load values */ -1: ld r8,CFG_TB_UPDATE_COUNT(r3) - andi. r0,r8,1 /* pending update ? loop */ - bne- 1b - xor r0,r8,r8 /* create dependency */ - add r3,r3,r0 - - /* Get TB & offset it. We use the MFTB macro which will generate - * workaround code for Cell. - */ - MFTB(r7) - ld r9,CFG_TB_ORIG_STAMP(r3) - subf r7,r9,r7 - - /* Scale result */ - ld r5,CFG_TB_TO_XS(r3) - mulhdu r7,r7,r5 - - /* Add stamp since epoch */ - ld r6,CFG_STAMP_XSEC(r3) - add r4,r6,r7 - - xor r0,r4,r4 - add r3,r3,r0 - ld r0,CFG_TB_UPDATE_COUNT(r3) - cmpld cr0,r0,r8 /* check if updated */ - bne- 1b - blr - .cfi_endproc -V_FUNCTION_END(__do_get_xsec) - -/* - * This is the core of clock_gettime(), it returns the current - * time in seconds and nanoseconds in r4 and r5. + * This is the core of clock_gettime() and gettimeofday(), + * it returns the current time in r4 (seconds) and r5. + * On entry, r7 gives the resolution of r5, either USEC_PER_SEC + * or NSEC_PER_SEC, giving r5 in microseconds or nanoseconds. * It expects the datapage ptr in r3 and doesn't clobber it. - * It clobbers r0 and r6 and returns NSEC_PER_SEC in r7. + * It clobbers r0, r6 and r9. * On return, r8 contains the counter value that can be reused. * This clobbers cr0 but not any other cr field. */ @@ -229,18 +187,18 @@ V_FUNCTION_BEGIN(__do_get_tspec) /* Get TB & offset it. We use the MFTB macro which will generate * workaround code for Cell. */ - MFTB(r7) + MFTB(r6) ld r9,CFG_TB_ORIG_STAMP(r3) - subf r7,r9,r7 + subf r6,r9,r6 /* Scale result */ ld r5,CFG_TB_TO_XS(r3) - sldi r7,r7,12 /* compute time since stamp_xtime */ - mulhdu r6,r7,r5 /* in units of 2^-32 seconds */ + sldi r6,r6,12 /* compute time since stamp_xtime */ + mulhdu r6,r6,r5 /* in units of 2^-32 seconds */ /* Add stamp since epoch */ ld r4,STAMP_XTIME+TSPC64_TV_SEC(r3) - ld r5,STAMP_XTIME+TSPC64_TV_NSEC(r3) + lwz r5,STAMP_SEC_FRAC(r3) or r0,r4,r5 or r0,r0,r6 xor r0,r0,r0 @@ -250,17 +208,11 @@ V_FUNCTION_BEGIN(__do_get_tspec) bne- 1b /* reload if so */ /* convert to seconds & nanoseconds and add to stamp */ - lis r7,NSEC_PER_SEC@h - ori r7,r7,NSEC_PER_SEC@l - mulhwu r0,r6,r7 /* compute nanoseconds and */ + add r6,r6,r5 /* add on fractional seconds of xtime */ + mulhwu r5,r6,r7 /* compute micro or nanoseconds and */ srdi r6,r6,32 /* seconds since stamp_xtime */ - clrldi r0,r0,32 - add r5,r5,r0 /* add nanoseconds together */ - cmpd r5,r7 /* overflow? */ + clrldi r5,r5,32 add r4,r4,r6 - bltlr /* all done if no overflow */ - subf r5,r7,r5 /* if overflow, adjust */ - addi r4,r4,1 blr .cfi_endproc V_FUNCTION_END(__do_get_tspec) diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index f0777a47e3a5..bee1c0f794cf 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -40,6 +40,9 @@ config ARCH_HAS_ILOG2_U64 config GENERIC_HWEIGHT def_bool y +config GENERIC_TIME + def_bool y + config GENERIC_TIME_VSYSCALL def_bool y diff --git a/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index aeb30c6f279c..a2163c95eb98 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/arch/s390/kernel/time.c @@ -207,8 +207,8 @@ struct clocksource * __init clocksource_default_clock(void) return &clocksource_tod; } -void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, - struct clocksource *clock, u32 mult) +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) { if (clock != &clocksource_tod) return; @@ -219,8 +219,8 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, vdso_data->xtime_tod_stamp = clock->cycle_last; vdso_data->xtime_clock_sec = wall_time->tv_sec; vdso_data->xtime_clock_nsec = wall_time->tv_nsec; - vdso_data->wtom_clock_sec = wtm->tv_sec; - vdso_data->wtom_clock_nsec = wtm->tv_nsec; + vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; + vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; vdso_data->ntp_mult = mult; smp_wmb(); ++vdso_data->tb_update_count; diff --git a/trunk/arch/score/Kconfig b/trunk/arch/score/Kconfig index be4a15584751..55d413e6dcf2 100644 --- a/trunk/arch/score/Kconfig +++ b/trunk/arch/score/Kconfig @@ -55,6 +55,9 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_CLOCKEVENTS def_bool y +config GENERIC_TIME + def_bool y + config SCHED_NO_NO_OMIT_FRAME_POINTER def_bool y diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 33990fa95af0..82868fee21fd 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -98,6 +98,9 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_IOMAP bool +config GENERIC_TIME + def_bool y + config GENERIC_CLOCKEVENTS def_bool y diff --git a/trunk/arch/sparc/Kconfig b/trunk/arch/sparc/Kconfig index 1cd0d9d3c761..c0015db247ba 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -66,6 +66,9 @@ config BITS default 32 if SPARC32 default 64 if SPARC64 +config GENERIC_TIME + def_bool y + config ARCH_USES_GETTIMEOFFSET bool default y if SPARC32 diff --git a/trunk/arch/um/Kconfig.common b/trunk/arch/um/Kconfig.common index 7c8e277f6d34..0d207e73a758 100644 --- a/trunk/arch/um/Kconfig.common +++ b/trunk/arch/um/Kconfig.common @@ -55,6 +55,10 @@ config GENERIC_BUG default y depends on BUG +config GENERIC_TIME + bool + default y + config GENERIC_CLOCKEVENTS bool default y diff --git a/trunk/arch/um/kernel/time.c b/trunk/arch/um/kernel/time.c index 2b8b262e5c23..c8b9c469fcd7 100644 --- a/trunk/arch/um/kernel/time.c +++ b/trunk/arch/um/kernel/time.c @@ -102,17 +102,16 @@ static void __init setup_itimer(void) clockevents_register_device(&itimer_clockevent); } -void read_persistent_clock(struct timespec *ts) -{ - nsecs = os_nsecs(); - set_normalized_timespec(ts, nsecs / NSEC_PER_SEC, - nsecs % NSEC_PER_SEC); -} - void __init time_init(void) { long long nsecs; timer_init(); + + nsecs = os_nsecs(); + set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC, + -nsecs % NSEC_PER_SEC); + set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC, + nsecs % NSEC_PER_SEC); late_time_init = setup_itimer; } diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 546b610ad71c..dcb0593b4a66 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -72,6 +72,9 @@ config ARCH_DEFCONFIG default "arch/x86/configs/i386_defconfig" if X86_32 default "arch/x86/configs/x86_64_defconfig" if X86_64 +config GENERIC_TIME + def_bool y + config GENERIC_CMOS_UPDATE def_bool y @@ -2043,7 +2046,7 @@ config SCx200 config SCx200HR_TIMER tristate "NatSemi SCx200 27MHz High-Resolution Timer Support" - depends on SCx200 + depends on SCx200 && GENERIC_TIME default y ---help--- This driver provides a clocksource built upon the on-chip diff --git a/trunk/arch/x86/kernel/hpet.c b/trunk/arch/x86/kernel/hpet.c index 33dbcc4ec5ff..ba390d731175 100644 --- a/trunk/arch/x86/kernel/hpet.c +++ b/trunk/arch/x86/kernel/hpet.c @@ -16,6 +16,7 @@ #include #define HPET_MASK CLOCKSOURCE_MASK(32) +#define HPET_SHIFT 22 /* FSEC = 10^-15 NSEC = 10^-9 */ @@ -786,6 +787,7 @@ static struct clocksource clocksource_hpet = { .rating = 250, .read = read_hpet, .mask = HPET_MASK, + .shift = HPET_SHIFT, .flags = CLOCK_SOURCE_IS_CONTINUOUS, .resume = hpet_resume_counter, #ifdef CONFIG_X86_64 @@ -796,7 +798,6 @@ static struct clocksource clocksource_hpet = { static int hpet_clocksource_register(void) { u64 start, now; - u64 hpet_freq; cycle_t t1; /* Start the counter */ @@ -831,15 +832,9 @@ static int hpet_clocksource_register(void) * mult = (hpet_period * 2^shift)/10^6 * mult = (hpet_period << shift)/FSEC_PER_NSEC */ + clocksource_hpet.mult = div_sc(hpet_period, FSEC_PER_NSEC, HPET_SHIFT); - /* Need to convert hpet_period (fsec/cyc) to cyc/sec: - * - * cyc/sec = FSEC_PER_SEC/hpet_period(fsec/cyc) - * cyc/sec = (FSEC_PER_NSEC * NSEC_PER_SEC)/hpet_period - */ - hpet_freq = FSEC_PER_NSEC * NSEC_PER_SEC; - do_div(hpet_freq, hpet_period); - clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq); + clocksource_register(&clocksource_hpet); return 0; } diff --git a/trunk/arch/x86/kernel/tsc.c b/trunk/arch/x86/kernel/tsc.c index ce8e50239332..9faf91ae1841 100644 --- a/trunk/arch/x86/kernel/tsc.c +++ b/trunk/arch/x86/kernel/tsc.c @@ -751,6 +751,7 @@ static struct clocksource clocksource_tsc = { .read = read_tsc, .resume = resume_tsc, .mask = CLOCKSOURCE_MASK(64), + .shift = 22, .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_MUST_VERIFY, #ifdef CONFIG_X86_64 @@ -844,6 +845,8 @@ __cpuinit int unsynchronized_tsc(void) static void __init init_tsc_clocksource(void) { + clocksource_tsc.mult = clocksource_khz2mult(tsc_khz, + clocksource_tsc.shift); if (tsc_clocksource_reliable) clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; /* lower the rating if we already know its unstable: */ @@ -851,7 +854,7 @@ static void __init init_tsc_clocksource(void) clocksource_tsc.rating = 0; clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; } - clocksource_register_khz(&clocksource_tsc, tsc_khz); + clocksource_register(&clocksource_tsc); } #ifdef CONFIG_X86_64 diff --git a/trunk/arch/x86/kernel/vsyscall_64.c b/trunk/arch/x86/kernel/vsyscall_64.c index dcbb28c4b694..1c0c6ab9c60f 100644 --- a/trunk/arch/x86/kernel/vsyscall_64.c +++ b/trunk/arch/x86/kernel/vsyscall_64.c @@ -73,8 +73,8 @@ void update_vsyscall_tz(void) write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); } -void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, - struct clocksource *clock, u32 mult) +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, + u32 mult) { unsigned long flags; @@ -87,7 +87,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, vsyscall_gtod_data.clock.shift = clock->shift; vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; - vsyscall_gtod_data.wall_to_monotonic = *wtm; + vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic; vsyscall_gtod_data.wall_time_coarse = __current_kernel_time(); write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); } @@ -169,18 +169,13 @@ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz) * unlikely */ time_t __vsyscall(1) vtime(time_t *t) { - unsigned seq; + struct timeval tv; time_t result; if (unlikely(!__vsyscall_gtod_data.sysctl_enabled)) return time_syscall(t); - do { - seq = read_seqbegin(&__vsyscall_gtod_data.lock); - - result = __vsyscall_gtod_data.wall_time_sec; - - } while (read_seqretry(&__vsyscall_gtod_data.lock, seq)); - + vgettimeofday(&tv, NULL); + result = tv.tv_sec; if (t) *t = result; return result; diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index 0859bfd8ae93..ebe228d02b08 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -48,6 +48,9 @@ config HZ int default 100 +config GENERIC_TIME + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index ae473445ad6d..91874e048552 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -101,9 +101,7 @@ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_ARCH_SHMOBILE) += sh/ -ifndef CONFIG_ARCH_USES_GETTIMEOFFSET -obj-y += clocksource/ -endif +obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_DCA) += dca/ obj-$(CONFIG_HID) += hid/ diff --git a/trunk/drivers/acpi/acpi_pad.c b/trunk/drivers/acpi/acpi_pad.c index b76848c80be3..446aced33aff 100644 --- a/trunk/drivers/acpi/acpi_pad.c +++ b/trunk/drivers/acpi/acpi_pad.c @@ -77,7 +77,7 @@ static void power_saving_mwait_init(void) power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | (highest_subcstate - 1); -#if defined(CONFIG_X86) +#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: case X86_VENDOR_INTEL: diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 294e10b5480a..e9a8026d39f0 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -264,7 +264,7 @@ int acpi_processor_resume(struct acpi_device * device) return 0; } -#if defined(CONFIG_X86) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) static void tsc_check_state(int state) { switch (boot_cpu_data.x86_vendor) { diff --git a/trunk/drivers/clocksource/acpi_pm.c b/trunk/drivers/clocksource/acpi_pm.c index cfb0f5278415..72a633a6ec98 100644 --- a/trunk/drivers/clocksource/acpi_pm.c +++ b/trunk/drivers/clocksource/acpi_pm.c @@ -68,7 +68,10 @@ static struct clocksource clocksource_acpi_pm = { .rating = 200, .read = acpi_pm_read, .mask = (cycle_t)ACPI_PM_MASK, + .mult = 0, /*to be calculated*/ + .shift = 22, .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; @@ -187,6 +190,9 @@ static int __init init_acpi_pm_clocksource(void) if (!pmtmr_ioport) return -ENODEV; + clocksource_acpi_pm.mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, + clocksource_acpi_pm.shift); + /* "verify" this timing source: */ for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { udelay(100 * j); @@ -214,8 +220,7 @@ static int __init init_acpi_pm_clocksource(void) if (verify_pmtmr_rate() != 0) return -ENODEV; - return clocksource_register_hz(&clocksource_acpi_pm, - PMTMR_TICKS_PER_SEC); + return clocksource_register(&clocksource_acpi_pm); } /* We use fs_initcall because we want the PCI fixups to have run diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 5b9ba4834ce1..26386a92f5aa 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -72,7 +72,7 @@ config ATMEL_TCLIB config ATMEL_TCB_CLKSRC bool "TC Block Clocksource" - depends on ATMEL_TCLIB + depends on ATMEL_TCLIB && GENERIC_TIME default y help Select this to get a high precision clocksource based on a @@ -240,7 +240,7 @@ config CS5535_MFGPT_DEFAULT_IRQ config CS5535_CLOCK_EVENT_SRC tristate "CS5535/CS5536 high-res timer (MFGPT) events" - depends on GENERIC_CLOCKEVENTS && CS5535_MFGPT + depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT help This driver provides a clock event source based on the MFGPT timer(s) in the CS5535 and CS5536 companion chips. diff --git a/trunk/include/linux/clocksource.h b/trunk/include/linux/clocksource.h index c37b21ad5a3b..5ea3c60c160c 100644 --- a/trunk/include/linux/clocksource.h +++ b/trunk/include/linux/clocksource.h @@ -292,8 +292,6 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec); */ extern int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq); -extern void -__clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq); static inline int clocksource_register_hz(struct clocksource *cs, u32 hz) { @@ -305,15 +303,6 @@ static inline int clocksource_register_khz(struct clocksource *cs, u32 khz) return __clocksource_register_scale(cs, 1000, khz); } -static inline void __clocksource_updatefreq_hz(struct clocksource *cs, u32 hz) -{ - __clocksource_updatefreq_scale(cs, 1, hz); -} - -static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz) -{ - __clocksource_updatefreq_scale(cs, 1000, khz); -} static inline void clocksource_calc_mult_shift(struct clocksource *cs, u32 freq, u32 minsec) @@ -324,13 +313,11 @@ clocksource_calc_mult_shift(struct clocksource *cs, u32 freq, u32 minsec) #ifdef CONFIG_GENERIC_TIME_VSYSCALL extern void -update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult); +update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult); extern void update_vsyscall_tz(void); #else static inline void -update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult) +update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult) { } diff --git a/trunk/include/linux/time.h b/trunk/include/linux/time.h index cb34e35fabac..ea3559f0b3f2 100644 --- a/trunk/include/linux/time.h +++ b/trunk/include/linux/time.h @@ -76,25 +76,9 @@ extern unsigned long mktime(const unsigned int year, const unsigned int mon, const unsigned int min, const unsigned int sec); extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec); - -/* - * timespec_add_safe assumes both values are positive and checks - * for overflow. It will return TIME_T_MAX if the reutrn would be - * smaller then either of the arguments. - */ extern struct timespec timespec_add_safe(const struct timespec lhs, const struct timespec rhs); - -static inline struct timespec timespec_add(struct timespec lhs, - struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec, - lhs.tv_nsec + rhs.tv_nsec); - return ts_delta; -} - /* * sub = lhs - rhs, in normalized form */ @@ -113,6 +97,8 @@ static inline struct timespec timespec_sub(struct timespec lhs, #define timespec_valid(ts) \ (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC)) +extern struct timespec xtime; +extern struct timespec wall_to_monotonic; extern seqlock_t xtime_lock; extern void read_persistent_clock(struct timespec *ts); @@ -124,8 +110,7 @@ extern int timekeeping_suspended; unsigned long get_seconds(void); struct timespec current_kernel_time(void); -struct timespec __current_kernel_time(void); /* does not take xtime_lock */ -struct timespec __get_wall_to_monotonic(void); /* does not take xtime_lock */ +struct timespec __current_kernel_time(void); /* does not hold xtime_lock */ struct timespec get_monotonic_coarse(void); #define CURRENT_TIME (current_kernel_time()) diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 809f48c70553..5c69e996bd0f 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -90,7 +90,7 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) do { seq = read_seqbegin(&xtime_lock); xts = __current_kernel_time(); - tom = __get_wall_to_monotonic(); + tom = wall_to_monotonic; } while (read_seqretry(&xtime_lock, seq)); xtim = timespec_to_ktime(xts); @@ -612,7 +612,7 @@ static int hrtimer_reprogram(struct hrtimer *timer, static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base; - struct timespec realtime_offset, wtm; + struct timespec realtime_offset; unsigned long seq; if (!hrtimer_hres_active()) @@ -620,9 +620,10 @@ static void retrigger_next_event(void *arg) do { seq = read_seqbegin(&xtime_lock); - wtm = __get_wall_to_monotonic(); + set_normalized_timespec(&realtime_offset, + -wall_to_monotonic.tv_sec, + -wall_to_monotonic.tv_nsec); } while (read_seqretry(&xtime_lock, seq)); - set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); base = &__get_cpu_var(hrtimer_bases); diff --git a/trunk/kernel/time.c b/trunk/kernel/time.c index ba9b338d1835..848b1c2ab09a 100644 --- a/trunk/kernel/time.c +++ b/trunk/kernel/time.c @@ -300,6 +300,22 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran) } EXPORT_SYMBOL(timespec_trunc); +#ifndef CONFIG_GENERIC_TIME +/* + * Simulate gettimeofday using do_gettimeofday which only allows a timeval + * and therefore only yields usec accuracy + */ +void getnstimeofday(struct timespec *tv) +{ + struct timeval x; + + do_gettimeofday(&x); + tv->tv_sec = x.tv_sec; + tv->tv_nsec = x.tv_usec * NSEC_PER_USEC; +} +EXPORT_SYMBOL_GPL(getnstimeofday); +#endif + /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. diff --git a/trunk/kernel/time/Kconfig b/trunk/kernel/time/Kconfig index f06a8a365648..95ed42951e0a 100644 --- a/trunk/kernel/time/Kconfig +++ b/trunk/kernel/time/Kconfig @@ -6,7 +6,7 @@ config TICK_ONESHOT config NO_HZ bool "Tickless System (Dynamic Ticks)" - depends on !ARCH_USES_GETTIMEOFFSET && GENERIC_CLOCKEVENTS + depends on GENERIC_TIME && GENERIC_CLOCKEVENTS select TICK_ONESHOT help This option enables a tickless system: timer interrupts will @@ -15,7 +15,7 @@ config NO_HZ config HIGH_RES_TIMERS bool "High Resolution Timer Support" - depends on !ARCH_USES_GETTIMEOFFSET && GENERIC_CLOCKEVENTS + depends on GENERIC_TIME && GENERIC_CLOCKEVENTS select TICK_ONESHOT help This option enables high resolution timer support. If your diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c index c18d7efa1b4b..f08e99c1d561 100644 --- a/trunk/kernel/time/clocksource.c +++ b/trunk/kernel/time/clocksource.c @@ -531,7 +531,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs) return max_nsecs - (max_nsecs >> 5); } -#ifndef CONFIG_ARCH_USES_GETTIMEOFFSET +#ifdef CONFIG_GENERIC_TIME /** * clocksource_select - Select the best clocksource available @@ -577,7 +577,7 @@ static void clocksource_select(void) } } -#else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ +#else /* CONFIG_GENERIC_TIME */ static inline void clocksource_select(void) { } @@ -639,18 +639,19 @@ static void clocksource_enqueue(struct clocksource *cs) #define MAX_UPDATE_LENGTH 5 /* Seconds */ /** - * __clocksource_updatefreq_scale - Used update clocksource with new freq + * __clocksource_register_scale - Used to install new clocksources * @t: clocksource to be registered * @scale: Scale factor multiplied against freq to get clocksource hz * @freq: clocksource frequency (cycles per second) divided by scale * - * This should only be called from the clocksource->enable() method. + * Returns -EBUSY if registration fails, zero otherwise. * * This *SHOULD NOT* be called directly! Please use the - * clocksource_updatefreq_hz() or clocksource_updatefreq_khz helper functions. + * clocksource_register_hz() or clocksource_register_khz helper functions. */ -void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) +int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) { + /* * Ideally we want to use some of the limits used in * clocksource_max_deferment, to provide a more informed @@ -661,27 +662,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) NSEC_PER_SEC/scale, MAX_UPDATE_LENGTH*scale); cs->max_idle_ns = clocksource_max_deferment(cs); -} -EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); - -/** - * __clocksource_register_scale - Used to install new clocksources - * @t: clocksource to be registered - * @scale: Scale factor multiplied against freq to get clocksource hz - * @freq: clocksource frequency (cycles per second) divided by scale - * - * Returns -EBUSY if registration fails, zero otherwise. - * - * This *SHOULD NOT* be called directly! Please use the - * clocksource_register_hz() or clocksource_register_khz helper functions. - */ -int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) -{ - - /* Intialize mult/shift and max_idle_ns */ - __clocksource_updatefreq_scale(cs, scale, freq); - /* Add clocksource to the clcoksource list */ mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); clocksource_select(); diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index e14c839e9faa..caf8d4d4f5c8 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -153,8 +153,8 @@ __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock); * - wall_to_monotonic is no longer the boot time, getboottime must be * used instead. */ -static struct timespec xtime __attribute__ ((aligned (16))); -static struct timespec wall_to_monotonic __attribute__ ((aligned (16))); +struct timespec xtime __attribute__ ((aligned (16))); +struct timespec wall_to_monotonic __attribute__ ((aligned (16))); static struct timespec total_sleep_time; /* @@ -170,10 +170,11 @@ void timekeeping_leap_insert(int leapsecond) { xtime.tv_sec += leapsecond; wall_to_monotonic.tv_sec -= leapsecond; - update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); } +#ifdef CONFIG_GENERIC_TIME + /** * timekeeping_forward_now - update clock to the current time * @@ -327,8 +328,7 @@ int do_settimeofday(struct timespec *tv) timekeeper.ntp_error = 0; ntp_clear(); - update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); write_sequnlock_irqrestore(&xtime_lock, flags); @@ -376,6 +376,52 @@ void timekeeping_notify(struct clocksource *clock) tick_clock_notify(); } +#else /* GENERIC_TIME */ + +static inline void timekeeping_forward_now(void) { } + +/** + * ktime_get - get the monotonic time in ktime_t format + * + * returns the time in ktime_t format + */ +ktime_t ktime_get(void) +{ + struct timespec now; + + ktime_get_ts(&now); + + return timespec_to_ktime(now); +} +EXPORT_SYMBOL_GPL(ktime_get); + +/** + * ktime_get_ts - get the monotonic clock in timespec format + * @ts: pointer to timespec variable + * + * The function calculates the monotonic clock from the realtime + * clock and the wall_to_monotonic offset and stores the result + * in normalized timespec format in the variable pointed to by @ts. + */ +void ktime_get_ts(struct timespec *ts) +{ + struct timespec tomono; + unsigned long seq; + + do { + seq = read_seqbegin(&xtime_lock); + getnstimeofday(ts); + tomono = wall_to_monotonic; + + } while (read_seqretry(&xtime_lock, seq)); + + set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, + ts->tv_nsec + tomono.tv_nsec); +} +EXPORT_SYMBOL_GPL(ktime_get_ts); + +#endif /* !GENERIC_TIME */ + /** * ktime_get_real - get the real (wall-) time in ktime_t format * @@ -533,9 +579,9 @@ static int timekeeping_resume(struct sys_device *dev) if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { ts = timespec_sub(ts, timekeeping_suspend_time); - xtime = timespec_add(xtime, ts); + xtime = timespec_add_safe(xtime, ts); wall_to_monotonic = timespec_sub(wall_to_monotonic, ts); - total_sleep_time = timespec_add(total_sleep_time, ts); + total_sleep_time = timespec_add_safe(total_sleep_time, ts); } /* re-base the last cycle value */ timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); @@ -738,11 +784,10 @@ void update_wall_time(void) return; clock = timekeeper.clock; - -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET - offset = timekeeper.cycle_interval; -#else +#ifdef CONFIG_GENERIC_TIME offset = (clock->read(clock) - clock->cycle_last) & clock->mask; +#else + offset = timekeeper.cycle_interval; #endif timekeeper.xtime_nsec = (s64)xtime.tv_nsec << timekeeper.shift; @@ -811,8 +856,7 @@ void update_wall_time(void) } /* check to see if there is a new clocksource to use */ - update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); } /** @@ -843,7 +887,7 @@ EXPORT_SYMBOL_GPL(getboottime); */ void monotonic_to_bootbased(struct timespec *ts) { - *ts = timespec_add(*ts, total_sleep_time); + *ts = timespec_add_safe(*ts, total_sleep_time); } EXPORT_SYMBOL_GPL(monotonic_to_bootbased); @@ -858,11 +902,6 @@ struct timespec __current_kernel_time(void) return xtime; } -struct timespec __get_wall_to_monotonic(void) -{ - return wall_to_monotonic; -} - struct timespec current_kernel_time(void) { struct timespec now; diff --git a/trunk/kernel/trace/Kconfig b/trunk/kernel/trace/Kconfig index 7531ddaf3afe..8b1797c4545b 100644 --- a/trunk/kernel/trace/Kconfig +++ b/trunk/kernel/trace/Kconfig @@ -153,7 +153,7 @@ config IRQSOFF_TRACER bool "Interrupts-off Latency Tracer" default n depends on TRACE_IRQFLAGS_SUPPORT - depends on !ARCH_USES_GETTIMEOFFSET + depends on GENERIC_TIME select TRACE_IRQFLAGS select GENERIC_TRACER select TRACER_MAX_TRACE @@ -175,7 +175,7 @@ config IRQSOFF_TRACER config PREEMPT_TRACER bool "Preemption-off Latency Tracer" default n - depends on !ARCH_USES_GETTIMEOFFSET + depends on GENERIC_TIME depends on PREEMPT select GENERIC_TRACER select TRACER_MAX_TRACE