]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
ia64: Update fsyscall gettime to use modern vsyscall_update
authorTony Luck <tony.luck@intel.com>
Tue, 31 Oct 2017 17:43:39 +0000 (10:43 -0700)
committerTony Luck <tony.luck@intel.com>
Tue, 31 Oct 2017 17:58:36 +0000 (10:58 -0700)
John Stultz provided the outline for this patch back in May 2014 here:

http://patches.linaro.org/patch/30501/

but I let this sit on the shelf for too long and in the intervening
years almost every field in "struct timekeeper" was changed. So this
is almost completely different from his original. Though the key change
in arch/ia64/kernel/fsys.S remains the same.

The core logic change with the updated vsyscall method is that we
preserve the base nanosecond value in shifted nanoseconds, which
allows us to avoid truncating and rounding up to the next nanosecond
every tick to avoid inconsistencies.

Thus the logic moved from
nsec = ((cycle_delta * mult)>>shift) + base_nsec;
to
nsec = ((cycle_delta * mult) + base_snsec) >> shift;

Cc: John Stultz <john.stultz@linaro.org>
Cc: linux-ia64@vger.kernel.org
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/Kconfig
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/fsyscall_gtod_data.h
arch/ia64/kernel/time.c

index 6a15083cc366df9c13962206952d266625034c7f..4d032e7f1637b18355d1e6e6c95cf27fec2a5892 100644 (file)
@@ -46,7 +46,7 @@ config IA64
        select ARCH_TASK_STRUCT_ALLOCATOR
        select ARCH_THREAD_STACK_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
-       select GENERIC_TIME_VSYSCALL_OLD
+       select GENERIC_TIME_VSYSCALL
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
index 798bdb209d0004bfda2aad4a24d2119ea682f446..c5eecf3e76fc134f544c5fc39e2faa94602cc907 100644 (file)
@@ -211,6 +211,8 @@ void foo(void)
        BLANK();
        DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET,
               offsetof (struct timespec, tv_nsec));
+       DEFINE(IA64_TIME_SN_SPEC_SNSEC_OFFSET,
+              offsetof (struct time_sn_spec, snsec));
 
        DEFINE(CLONE_SETTLS_BIT, 19);
 #if CLONE_SETTLS != (1<<19)
index edbf7af958492b1624cd7c3c748c9185f9782d9f..0d3c7abb31a83f6f246053ff9ebb1394a30dc734 100644 (file)
@@ -235,9 +235,9 @@ ENTRY(fsys_gettimeofday)
        MOV_FROM_ITC(p8, p6, r2, r10)   // CPU_TIMER. 36 clocks latency!!!
 (p9)   ld8 r2 = [r30]          // MMIO_TIMER. Could also have latency issues..
 (p13)  ld8 r25 = [r19]         // get itc_lastcycle value
-       ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET     // tv_sec
+       ld8 r9 = [r22],IA64_TIME_SN_SPEC_SNSEC_OFFSET   // sec
        ;;
-       ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET    // tv_nsec
+       ld8 r8 = [r22],-IA64_TIME_SN_SPEC_SNSEC_OFFSET  // snsec
 (p13)  sub r3 = r25,r2         // Diff needed before comparison (thanks davidm)
        ;;
 (p13)  cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared
@@ -265,9 +265,9 @@ EX(.fail_efault, probe.w.fault r31, 3)
        mf
        ;;
        ld4 r10 = [r20]         // gtod_lock.sequence
-       shr.u r2 = r2,r23       // shift by factor
-       ;;
        add r8 = r8,r2          // Add xtime.nsecs
+       ;;
+       shr.u r8 = r8,r23       // shift by factor
        cmp4.ne p7,p0 = r28,r10
 (p7)   br.cond.dpnt.few .time_redo     // sequence number changed, redo
        // End critical section.
index dcc5149177315a4a4aabcb78a70298cbc9eb1f72..28363bfc9f572083efc5714a9f17cda11786481b 100644 (file)
@@ -5,10 +5,16 @@
  * fsyscall gettimeofday data
  */
 
+/* like timespec, but includes "shifted nanoseconds" */
+struct time_sn_spec {
+       u64     sec;
+       u64     snsec;
+};
+
 struct fsyscall_gtod_data_t {
        seqcount_t      seq;
-       struct timespec wall_time;
-       struct timespec monotonic_time;
+       struct time_sn_spec wall_time;
+       struct time_sn_spec monotonic_time;
        u64             clk_mask;
        u32             clk_mult;
        u32             clk_shift;
index aa7be020a9042b12b0c0ac8b05e380f0a5c0f8dc..c6ecb97151a25774bf75ce5a1663210db4f6bce3 100644 (file)
@@ -430,30 +430,32 @@ void update_vsyscall_tz(void)
 {
 }
 
-void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
-                        struct clocksource *c, u32 mult, u64 cycle_last)
+void update_vsyscall(struct timekeeper *tk)
 {
        write_seqcount_begin(&fsyscall_gtod_data.seq);
 
-        /* copy fsyscall clock data */
-        fsyscall_gtod_data.clk_mask = c->mask;
-        fsyscall_gtod_data.clk_mult = mult;
-        fsyscall_gtod_data.clk_shift = c->shift;
-        fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
-        fsyscall_gtod_data.clk_cycle_last = cycle_last;
-
-       /* 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
-                                                       + wall->tv_sec;
-       fsyscall_gtod_data.monotonic_time.tv_nsec = wtm->tv_nsec
-                                                       + wall->tv_nsec;
+       /* copy vsyscall data */
+       fsyscall_gtod_data.clk_mask = tk->tkr_mono.mask;
+       fsyscall_gtod_data.clk_mult = tk->tkr_mono.mult;
+       fsyscall_gtod_data.clk_shift = tk->tkr_mono.shift;
+       fsyscall_gtod_data.clk_fsys_mmio = tk->tkr_mono.clock->archdata.fsys_mmio;
+       fsyscall_gtod_data.clk_cycle_last = tk->tkr_mono.cycle_last;
+
+       fsyscall_gtod_data.wall_time.sec = tk->xtime_sec;
+       fsyscall_gtod_data.wall_time.snsec = tk->tkr_mono.xtime_nsec;
+
+       fsyscall_gtod_data.monotonic_time.sec = tk->xtime_sec
+                                             + tk->wall_to_monotonic.tv_sec;
+       fsyscall_gtod_data.monotonic_time.snsec = tk->tkr_mono.xtime_nsec
+                                               + ((u64)tk->wall_to_monotonic.tv_nsec
+                                                       << tk->tkr_mono.shift);
 
        /* normalize */
-       while (fsyscall_gtod_data.monotonic_time.tv_nsec >= NSEC_PER_SEC) {
-               fsyscall_gtod_data.monotonic_time.tv_nsec -= NSEC_PER_SEC;
-               fsyscall_gtod_data.monotonic_time.tv_sec++;
+       while (fsyscall_gtod_data.monotonic_time.snsec >=
+                                       (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
+               fsyscall_gtod_data.monotonic_time.snsec -=
+                                       ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift;
+               fsyscall_gtod_data.monotonic_time.sec++;
        }
 
        write_seqcount_end(&fsyscall_gtod_data.seq);