aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-09-04 16:14:46 -0400
committerJohn Stultz <john.stultz@linaro.org>2012-09-24 12:38:09 -0400
commit650ea02475106e8d6bdf561896d2ffe0d1c0ebb4 (patch)
tree0e4e06e525c8e47cd3379addbbc4895f20347df7 /arch
parent92bb1fcf57a0c2e45f7e67fbf0a8ed475a749236 (diff)
time: Convert x86_64 to using new update_vsyscall
Switch x86_64 to using sub-ns precise vsyscall Cc: Tony Luck <tony.luck@intel.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Paul Turner <pjt@google.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Richard Cochran <richardcochran@gmail.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/include/asm/vgtod.h4
-rw-r--r--arch/x86/kernel/vsyscall_64.c47
-rw-r--r--arch/x86/vdso/vclock_gettime.c22
4 files changed, 45 insertions, 30 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e3f3c1a5a744..8ec3a1aa4abd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -93,7 +93,7 @@ config X86
93 select GENERIC_CLOCKEVENTS 93 select GENERIC_CLOCKEVENTS
94 select ARCH_CLOCKSOURCE_DATA if X86_64 94 select ARCH_CLOCKSOURCE_DATA if X86_64
95 select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC) 95 select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
96 select GENERIC_TIME_VSYSCALL_OLD if X86_64 96 select GENERIC_TIME_VSYSCALL if X86_64
97 select KTIME_SCALAR if X86_32 97 select KTIME_SCALAR if X86_32
98 select GENERIC_STRNCPY_FROM_USER 98 select GENERIC_STRNCPY_FROM_USER
99 select GENERIC_STRNLEN_USER 99 select GENERIC_STRNLEN_USER
diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h
index 8b38be2de9e1..46e24d36b7da 100644
--- a/arch/x86/include/asm/vgtod.h
+++ b/arch/x86/include/asm/vgtod.h
@@ -17,8 +17,8 @@ struct vsyscall_gtod_data {
17 17
18 /* open coded 'struct timespec' */ 18 /* open coded 'struct timespec' */
19 time_t wall_time_sec; 19 time_t wall_time_sec;
20 u32 wall_time_nsec; 20 u64 wall_time_snsec;
21 u32 monotonic_time_nsec; 21 u64 monotonic_time_snsec;
22 time_t monotonic_time_sec; 22 time_t monotonic_time_sec;
23 23
24 struct timezone sys_tz; 24 struct timezone sys_tz;
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 77dde2953c64..3a3e8c9e280d 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -82,32 +82,41 @@ void update_vsyscall_tz(void)
82 vsyscall_gtod_data.sys_tz = sys_tz; 82 vsyscall_gtod_data.sys_tz = sys_tz;
83} 83}
84 84
85void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm, 85void update_vsyscall(struct timekeeper *tk)
86 struct clocksource *clock, u32 mult)
87{ 86{
88 struct timespec monotonic; 87 struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
89 88
90 write_seqcount_begin(&vsyscall_gtod_data.seq); 89 write_seqcount_begin(&vdata->seq);
91 90
92 /* copy vsyscall data */ 91 /* copy vsyscall data */
93 vsyscall_gtod_data.clock.vclock_mode = clock->archdata.vclock_mode; 92 vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
94 vsyscall_gtod_data.clock.cycle_last = clock->cycle_last; 93 vdata->clock.cycle_last = tk->clock->cycle_last;
95 vsyscall_gtod_data.clock.mask = clock->mask; 94 vdata->clock.mask = tk->clock->mask;
96 vsyscall_gtod_data.clock.mult = mult; 95 vdata->clock.mult = tk->mult;
97 vsyscall_gtod_data.clock.shift = clock->shift; 96 vdata->clock.shift = tk->shift;
98 97
99 vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; 98 vdata->wall_time_sec = tk->xtime_sec;
100 vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; 99 vdata->wall_time_snsec = tk->xtime_nsec;
100
101 vdata->monotonic_time_sec = tk->xtime_sec
102 + tk->wall_to_monotonic.tv_sec;
103 vdata->monotonic_time_snsec = tk->xtime_nsec
104 + (tk->wall_to_monotonic.tv_nsec
105 << tk->shift);
106 while (vdata->monotonic_time_snsec >=
107 (((u64)NSEC_PER_SEC) << tk->shift)) {
108 vdata->monotonic_time_snsec -=
109 ((u64)NSEC_PER_SEC) << tk->shift;
110 vdata->monotonic_time_sec++;
111 }
101 112
102 monotonic = timespec_add(*wall_time, *wtm); 113 vdata->wall_time_coarse.tv_sec = tk->xtime_sec;
103 vsyscall_gtod_data.monotonic_time_sec = monotonic.tv_sec; 114 vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
104 vsyscall_gtod_data.monotonic_time_nsec = monotonic.tv_nsec;
105 115
106 vsyscall_gtod_data.wall_time_coarse = __current_kernel_time(); 116 vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse,
107 vsyscall_gtod_data.monotonic_time_coarse = 117 tk->wall_to_monotonic);
108 timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
109 118
110 write_seqcount_end(&vsyscall_gtod_data.seq); 119 write_seqcount_end(&vdata->seq);
111} 120}
112 121
113static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, 122static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index 885eff49d6ab..4df6c373421a 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -80,7 +80,7 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
80} 80}
81 81
82 82
83notrace static inline long vgetns(void) 83notrace static inline u64 vgetsns(void)
84{ 84{
85 long v; 85 long v;
86 cycles_t cycles; 86 cycles_t cycles;
@@ -91,21 +91,24 @@ notrace static inline long vgetns(void)
91 else 91 else
92 return 0; 92 return 0;
93 v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask; 93 v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
94 return (v * gtod->clock.mult) >> gtod->clock.shift; 94 return v * gtod->clock.mult;
95} 95}
96 96
97/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */ 97/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
98notrace static int __always_inline do_realtime(struct timespec *ts) 98notrace static int __always_inline do_realtime(struct timespec *ts)
99{ 99{
100 unsigned long seq, ns; 100 unsigned long seq;
101 u64 ns;
101 int mode; 102 int mode;
102 103
104 ts->tv_nsec = 0;
103 do { 105 do {
104 seq = read_seqcount_begin(&gtod->seq); 106 seq = read_seqcount_begin(&gtod->seq);
105 mode = gtod->clock.vclock_mode; 107 mode = gtod->clock.vclock_mode;
106 ts->tv_sec = gtod->wall_time_sec; 108 ts->tv_sec = gtod->wall_time_sec;
107 ts->tv_nsec = gtod->wall_time_nsec; 109 ns = gtod->wall_time_snsec;
108 ns = vgetns(); 110 ns += vgetsns();
111 ns >>= gtod->clock.shift;
109 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 112 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
110 113
111 timespec_add_ns(ts, ns); 114 timespec_add_ns(ts, ns);
@@ -114,15 +117,18 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
114 117
115notrace static int do_monotonic(struct timespec *ts) 118notrace static int do_monotonic(struct timespec *ts)
116{ 119{
117 unsigned long seq, ns; 120 unsigned long seq;
121 u64 ns;
118 int mode; 122 int mode;
119 123
124 ts->tv_nsec = 0;
120 do { 125 do {
121 seq = read_seqcount_begin(&gtod->seq); 126 seq = read_seqcount_begin(&gtod->seq);
122 mode = gtod->clock.vclock_mode; 127 mode = gtod->clock.vclock_mode;
123 ts->tv_sec = gtod->monotonic_time_sec; 128 ts->tv_sec = gtod->monotonic_time_sec;
124 ts->tv_nsec = gtod->monotonic_time_nsec; 129 ns = gtod->monotonic_time_snsec;
125 ns = vgetns(); 130 ns += vgetsns();
131 ns >>= gtod->clock.shift;
126 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 132 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
127 timespec_add_ns(ts, ns); 133 timespec_add_ns(ts, ns);
128 134