aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-06 17:09:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-06 17:09:38 -0400
commit21884a83b2192a00885d7244a1dda32debd2fbc7 (patch)
treee00267bbcac32f0114b3d21a20c61107d2314c40 /arch
parent8b70a90cabafb6a6e1a0d3f838b38355fe48337e (diff)
parent73b0cd674ccc64c921e25bd7154f26d342116539 (diff)
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer core updates from Thomas Gleixner: "The timer changes contain: - posix timer code consolidation and fixes for odd corner cases - sched_clock implementation moved from ARM to core code to avoid duplication by other architectures - alarm timer updates - clocksource and clockevents unregistration facilities - clocksource/events support for new hardware - precise nanoseconds RTC readout (Xen feature) - generic support for Xen suspend/resume oddities - the usual lot of fixes and cleanups all over the place The parts which touch other areas (ARM/XEN) have been coordinated with the relevant maintainers. Though this results in an handful of trivial to solve merge conflicts, which we preferred over nasty cross tree merge dependencies. The patches which have been committed in the last few days are bug fixes plus the posix timer lot. The latter was in akpms queue and next for quite some time; they just got forgotten and Frederic collected them last minute." * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (59 commits) hrtimer: Remove unused variable hrtimers: Move SMP function call to thread context clocksource: Reselect clocksource when watchdog validated high-res capability posix-cpu-timers: don't account cpu timer after stopped thread runtime accounting posix_timers: fix racy timer delta caching on task exit posix-timers: correctly get dying task time sample in posix_cpu_timer_schedule() selftests: add basic posix timers selftests posix_cpu_timers: consolidate expired timers check posix_cpu_timers: consolidate timer list cleanups posix_cpu_timer: consolidate expiry time type tick: Sanitize broadcast control logic tick: Prevent uncontrolled switch to oneshot mode tick: Make oneshot broadcast robust vs. CPU offlining x86: xen: Sync the CMOS RTC as well as the Xen wallclock x86: xen: Sync the wallclock when the system time is set timekeeping: Indicate that clock was set in the pvclock gtod notifier timekeeping: Pass flags instead of multiple bools to timekeeping_update() xen: Remove clock_was_set() call in the resume path hrtimers: Support resuming with two or more CPUs online (but stopped) timer: Fix jiffies wrap behavior of round_jiffies_common() ...
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/common/timer-sp.c2
-rw-r--r--arch/arm/include/asm/sched_clock.h18
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/arch_timer.c2
-rw-r--r--arch/arm/kernel/sched_clock.c217
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/mach-davinci/time.c2
-rw-r--r--arch/arm/mach-imx/time.c2
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c2
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-mmp/time.c2
-rw-r--r--arch/arm/mach-msm/timer.c2
-rw-r--r--arch/arm/mach-omap1/time.c2
-rw-r--r--arch/arm/mach-omap2/timer.c2
-rw-r--r--arch/arm/mach-pxa/time.c2
-rw-r--r--arch/arm/mach-sa1100/time.c2
-rw-r--r--arch/arm/mach-u300/timer.c2
-rw-r--r--arch/arm/plat-iop/time.c2
-rw-r--r--arch/arm/plat-omap/counter_32k.c2
-rw-r--r--arch/arm/plat-orion/time.c2
-rw-r--r--arch/arm/plat-samsung/samsung-time.c2
-rw-r--r--arch/arm/plat-versatile/sched-clock.c2
-rw-r--r--arch/x86/include/asm/mc146818rtc.h4
-rw-r--r--arch/x86/include/asm/mrst-vrtc.h4
-rw-r--r--arch/x86/include/asm/x86_init.h6
-rw-r--r--arch/x86/kernel/kvmclock.c9
-rw-r--r--arch/x86/kernel/rtc.c17
-rw-r--r--arch/x86/lguest/boot.c4
-rw-r--r--arch/x86/platform/efi/efi.c10
-rw-r--r--arch/x86/platform/mrst/vrtc.c11
-rw-r--r--arch/x86/xen/time.c58
32 files changed, 99 insertions, 302 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 531cdda016f9..5ef7af01373a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -14,6 +14,7 @@ config ARM
14 select GENERIC_IRQ_PROBE 14 select GENERIC_IRQ_PROBE
15 select GENERIC_IRQ_SHOW 15 select GENERIC_IRQ_SHOW
16 select GENERIC_PCI_IOMAP 16 select GENERIC_PCI_IOMAP
17 select GENERIC_SCHED_CLOCK
17 select GENERIC_SMP_IDLE_THREAD 18 select GENERIC_SMP_IDLE_THREAD
18 select GENERIC_IDLE_POLL_SETUP 19 select GENERIC_IDLE_POLL_SETUP
19 select GENERIC_STRNCPY_FROM_USER 20 select GENERIC_STRNCPY_FROM_USER
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index ddc740769601..023ee63827a2 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -28,8 +28,8 @@
28#include <linux/of.h> 28#include <linux/of.h>
29#include <linux/of_address.h> 29#include <linux/of_address.h>
30#include <linux/of_irq.h> 30#include <linux/of_irq.h>
31#include <linux/sched_clock.h>
31 32
32#include <asm/sched_clock.h>
33#include <asm/hardware/arm_timer.h> 33#include <asm/hardware/arm_timer.h>
34#include <asm/hardware/timer-sp.h> 34#include <asm/hardware/timer-sp.h>
35 35
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h
index 3d520ddca61b..2389b71a8e7c 100644
--- a/arch/arm/include/asm/sched_clock.h
+++ b/arch/arm/include/asm/sched_clock.h
@@ -1,16 +1,4 @@
1/* 1/* You shouldn't include this file. Use linux/sched_clock.h instead.
2 * sched_clock.h: support for extending counters to full 64-bit ns counter 2 * Temporary file until all asm/sched_clock.h users are gone
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */ 3 */
8#ifndef ASM_SCHED_CLOCK 4#include <linux/sched_clock.h>
9#define ASM_SCHED_CLOCK
10
11extern void sched_clock_postinit(void);
12extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
13
14extern unsigned long long (*sched_clock_func)(void);
15
16#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index fccfbdb03df1..86d10dd47dc4 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -16,7 +16,7 @@ CFLAGS_REMOVE_return_address.o = -pg
16# Object file lists. 16# Object file lists.
17 17
18obj-y := elf.o entry-common.o irq.o opcodes.o \ 18obj-y := elf.o entry-common.o irq.o opcodes.o \
19 process.o ptrace.o return_address.o sched_clock.o \ 19 process.o ptrace.o return_address.o \
20 setup.o signal.o stacktrace.o sys_arm.o time.o traps.o 20 setup.o signal.o stacktrace.o sys_arm.o time.o traps.o
21 21
22obj-$(CONFIG_ATAGS) += atags_parse.o 22obj-$(CONFIG_ATAGS) += atags_parse.o
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 59dcdced6e30..221f07b11ccb 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -11,9 +11,9 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/types.h> 12#include <linux/types.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/sched_clock.h>
14 15
15#include <asm/delay.h> 16#include <asm/delay.h>
16#include <asm/sched_clock.h>
17 17
18#include <clocksource/arm_arch_timer.h> 18#include <clocksource/arm_arch_timer.h>
19 19
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
deleted file mode 100644
index e8edcaa0e432..000000000000
--- a/arch/arm/kernel/sched_clock.c
+++ /dev/null
@@ -1,217 +0,0 @@
1/*
2 * sched_clock.c: support for extending counters to full 64-bit ns counter
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/clocksource.h>
9#include <linux/init.h>
10#include <linux/jiffies.h>
11#include <linux/kernel.h>
12#include <linux/moduleparam.h>
13#include <linux/sched.h>
14#include <linux/syscore_ops.h>
15#include <linux/timer.h>
16
17#include <asm/sched_clock.h>
18
19struct clock_data {
20 u64 epoch_ns;
21 u32 epoch_cyc;
22 u32 epoch_cyc_copy;
23 unsigned long rate;
24 u32 mult;
25 u32 shift;
26 bool suspended;
27 bool needs_suspend;
28};
29
30static void sched_clock_poll(unsigned long wrap_ticks);
31static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
32static int irqtime = -1;
33
34core_param(irqtime, irqtime, int, 0400);
35
36static struct clock_data cd = {
37 .mult = NSEC_PER_SEC / HZ,
38};
39
40static u32 __read_mostly sched_clock_mask = 0xffffffff;
41
42static u32 notrace jiffy_sched_clock_read(void)
43{
44 return (u32)(jiffies - INITIAL_JIFFIES);
45}
46
47static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
48
49static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
50{
51 return (cyc * mult) >> shift;
52}
53
54static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
55{
56 u64 epoch_ns;
57 u32 epoch_cyc;
58
59 if (cd.suspended)
60 return cd.epoch_ns;
61
62 /*
63 * Load the epoch_cyc and epoch_ns atomically. We do this by
64 * ensuring that we always write epoch_cyc, epoch_ns and
65 * epoch_cyc_copy in strict order, and read them in strict order.
66 * If epoch_cyc and epoch_cyc_copy are not equal, then we're in
67 * the middle of an update, and we should repeat the load.
68 */
69 do {
70 epoch_cyc = cd.epoch_cyc;
71 smp_rmb();
72 epoch_ns = cd.epoch_ns;
73 smp_rmb();
74 } while (epoch_cyc != cd.epoch_cyc_copy);
75
76 return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift);
77}
78
79/*
80 * Atomically update the sched_clock epoch.
81 */
82static void notrace update_sched_clock(void)
83{
84 unsigned long flags;
85 u32 cyc;
86 u64 ns;
87
88 cyc = read_sched_clock();
89 ns = cd.epoch_ns +
90 cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
91 cd.mult, cd.shift);
92 /*
93 * Write epoch_cyc and epoch_ns in a way that the update is
94 * detectable in cyc_to_fixed_sched_clock().
95 */
96 raw_local_irq_save(flags);
97 cd.epoch_cyc_copy = cyc;
98 smp_wmb();
99 cd.epoch_ns = ns;
100 smp_wmb();
101 cd.epoch_cyc = cyc;
102 raw_local_irq_restore(flags);
103}
104
105static void sched_clock_poll(unsigned long wrap_ticks)
106{
107 mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
108 update_sched_clock();
109}
110
111void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
112{
113 unsigned long r, w;
114 u64 res, wrap;
115 char r_unit;
116
117 if (cd.rate > rate)
118 return;
119
120 BUG_ON(bits > 32);
121 WARN_ON(!irqs_disabled());
122 read_sched_clock = read;
123 sched_clock_mask = (1 << bits) - 1;
124 cd.rate = rate;
125
126 /* calculate the mult/shift to convert counter ticks to ns. */
127 clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
128
129 r = rate;
130 if (r >= 4000000) {
131 r /= 1000000;
132 r_unit = 'M';
133 } else if (r >= 1000) {
134 r /= 1000;
135 r_unit = 'k';
136 } else
137 r_unit = ' ';
138
139 /* calculate how many ns until we wrap */
140 wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift);
141 do_div(wrap, NSEC_PER_MSEC);
142 w = wrap;
143
144 /* calculate the ns resolution of this counter */
145 res = cyc_to_ns(1ULL, cd.mult, cd.shift);
146 pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
147 bits, r, r_unit, res, w);
148
149 /*
150 * Start the timer to keep sched_clock() properly updated and
151 * sets the initial epoch.
152 */
153 sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
154 update_sched_clock();
155
156 /*
157 * Ensure that sched_clock() starts off at 0ns
158 */
159 cd.epoch_ns = 0;
160
161 /* Enable IRQ time accounting if we have a fast enough sched_clock */
162 if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
163 enable_sched_clock_irqtime();
164
165 pr_debug("Registered %pF as sched_clock source\n", read);
166}
167
168static unsigned long long notrace sched_clock_32(void)
169{
170 u32 cyc = read_sched_clock();
171 return cyc_to_sched_clock(cyc, sched_clock_mask);
172}
173
174unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
175
176unsigned long long notrace sched_clock(void)
177{
178 return sched_clock_func();
179}
180
181void __init sched_clock_postinit(void)
182{
183 /*
184 * If no sched_clock function has been provided at that point,
185 * make it the final one one.
186 */
187 if (read_sched_clock == jiffy_sched_clock_read)
188 setup_sched_clock(jiffy_sched_clock_read, 32, HZ);
189
190 sched_clock_poll(sched_clock_timer.data);
191}
192
193static int sched_clock_suspend(void)
194{
195 sched_clock_poll(sched_clock_timer.data);
196 cd.suspended = true;
197 return 0;
198}
199
200static void sched_clock_resume(void)
201{
202 cd.epoch_cyc = read_sched_clock();
203 cd.epoch_cyc_copy = cd.epoch_cyc;
204 cd.suspended = false;
205}
206
207static struct syscore_ops sched_clock_ops = {
208 .suspend = sched_clock_suspend,
209 .resume = sched_clock_resume,
210};
211
212static int __init sched_clock_syscore_init(void)
213{
214 register_syscore_ops(&sched_clock_ops);
215 return 0;
216}
217device_initcall(sched_clock_syscore_init);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index abff4e9aaee0..98aee3258398 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -24,9 +24,9 @@
24#include <linux/timer.h> 24#include <linux/timer.h>
25#include <linux/clocksource.h> 25#include <linux/clocksource.h>
26#include <linux/irq.h> 26#include <linux/irq.h>
27#include <linux/sched_clock.h>
27 28
28#include <asm/thread_info.h> 29#include <asm/thread_info.h>
29#include <asm/sched_clock.h>
30#include <asm/stacktrace.h> 30#include <asm/stacktrace.h>
31#include <asm/mach/arch.h> 31#include <asm/mach/arch.h>
32#include <asm/mach/time.h> 32#include <asm/mach/time.h>
@@ -120,6 +120,4 @@ void __init time_init(void)
120 machine_desc->init_time(); 120 machine_desc->init_time();
121 else 121 else
122 clocksource_of_init(); 122 clocksource_of_init();
123
124 sched_clock_postinit();
125} 123}
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index bad361ec1666..7a55b5c95971 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -18,8 +18,8 @@
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/sched_clock.h>
21 22
22#include <asm/sched_clock.h>
23#include <asm/mach/irq.h> 23#include <asm/mach/irq.h>
24#include <asm/mach/time.h> 24#include <asm/mach/time.h>
25 25
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index fea91313678b..cd46529e9eaa 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -26,8 +26,8 @@
26#include <linux/clockchips.h> 26#include <linux/clockchips.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/err.h> 28#include <linux/err.h>
29#include <linux/sched_clock.h>
29 30
30#include <asm/sched_clock.h>
31#include <asm/mach/time.h> 31#include <asm/mach/time.h>
32 32
33#include "common.h" 33#include "common.h"
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index a5b15c4e8def..d9e95e612fcb 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -41,6 +41,7 @@
41#include <linux/stat.h> 41#include <linux/stat.h>
42#include <linux/sys_soc.h> 42#include <linux/sys_soc.h>
43#include <linux/termios.h> 43#include <linux/termios.h>
44#include <linux/sched_clock.h>
44 45
45#include <mach/hardware.h> 46#include <mach/hardware.h>
46#include <mach/platform.h> 47#include <mach/platform.h>
@@ -48,7 +49,6 @@
48#include <asm/setup.h> 49#include <asm/setup.h>
49#include <asm/param.h> /* HZ */ 50#include <asm/param.h> /* HZ */
50#include <asm/mach-types.h> 51#include <asm/mach-types.h>
51#include <asm/sched_clock.h>
52 52
53#include <mach/lm.h> 53#include <mach/lm.h>
54#include <mach/irqs.h> 54#include <mach/irqs.h>
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index d7223b3b81f3..1f6c1fb353ad 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -30,6 +30,7 @@
30#include <linux/export.h> 30#include <linux/export.h>
31#include <linux/gpio.h> 31#include <linux/gpio.h>
32#include <linux/cpu.h> 32#include <linux/cpu.h>
33#include <linux/sched_clock.h>
33 34
34#include <mach/udc.h> 35#include <mach/udc.h>
35#include <mach/hardware.h> 36#include <mach/hardware.h>
@@ -38,7 +39,6 @@
38#include <asm/pgtable.h> 39#include <asm/pgtable.h>
39#include <asm/page.h> 40#include <asm/page.h>
40#include <asm/irq.h> 41#include <asm/irq.h>
41#include <asm/sched_clock.h>
42#include <asm/system_misc.h> 42#include <asm/system_misc.h>
43 43
44#include <asm/mach/map.h> 44#include <asm/mach/map.h>
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index 86a18b3d252e..7ac41e83cfef 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -28,8 +28,8 @@
28#include <linux/of.h> 28#include <linux/of.h>
29#include <linux/of_address.h> 29#include <linux/of_address.h>
30#include <linux/of_irq.h> 30#include <linux/of_irq.h>
31#include <linux/sched_clock.h>
31 32
32#include <asm/sched_clock.h>
33#include <mach/addr-map.h> 33#include <mach/addr-map.h>
34#include <mach/regs-timers.h> 34#include <mach/regs-timers.h>
35#include <mach/regs-apbc.h> 35#include <mach/regs-apbc.h>
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 284313f3e02c..b6418fd5fe0d 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -23,10 +23,10 @@
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_address.h> 24#include <linux/of_address.h>
25#include <linux/of_irq.h> 25#include <linux/of_irq.h>
26#include <linux/sched_clock.h>
26 27
27#include <asm/mach/time.h> 28#include <asm/mach/time.h>
28#include <asm/localtimer.h> 29#include <asm/localtimer.h>
29#include <asm/sched_clock.h>
30 30
31#include "common.h" 31#include "common.h"
32 32
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 726ec23d29c7..80603d2fef77 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -43,9 +43,9 @@
43#include <linux/clocksource.h> 43#include <linux/clocksource.h>
44#include <linux/clockchips.h> 44#include <linux/clockchips.h>
45#include <linux/io.h> 45#include <linux/io.h>
46#include <linux/sched_clock.h>
46 47
47#include <asm/irq.h> 48#include <asm/irq.h>
48#include <asm/sched_clock.h>
49 49
50#include <mach/hardware.h> 50#include <mach/hardware.h>
51#include <asm/mach/irq.h> 51#include <asm/mach/irq.h>
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 3bdb0fb02028..29ac667b7a8b 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -41,10 +41,10 @@
41#include <linux/of_irq.h> 41#include <linux/of_irq.h>
42#include <linux/platform_device.h> 42#include <linux/platform_device.h>
43#include <linux/platform_data/dmtimer-omap.h> 43#include <linux/platform_data/dmtimer-omap.h>
44#include <linux/sched_clock.h>
44 45
45#include <asm/mach/time.h> 46#include <asm/mach/time.h>
46#include <asm/smp_twd.h> 47#include <asm/smp_twd.h>
47#include <asm/sched_clock.h>
48 48
49#include "omap_hwmod.h" 49#include "omap_hwmod.h"
50#include "omap_device.h" 50#include "omap_device.h"
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 8f1ee92aea30..9aa852a8fab9 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -16,11 +16,11 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/clockchips.h> 18#include <linux/clockchips.h>
19#include <linux/sched_clock.h>
19 20
20#include <asm/div64.h> 21#include <asm/div64.h>
21#include <asm/mach/irq.h> 22#include <asm/mach/irq.h>
22#include <asm/mach/time.h> 23#include <asm/mach/time.h>
23#include <asm/sched_clock.h>
24#include <mach/regs-ost.h> 24#include <mach/regs-ost.h>
25#include <mach/irqs.h> 25#include <mach/irqs.h>
26 26
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index a59a13a665a6..713c86cd3d64 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -14,9 +14,9 @@
14#include <linux/irq.h> 14#include <linux/irq.h>
15#include <linux/timex.h> 15#include <linux/timex.h>
16#include <linux/clockchips.h> 16#include <linux/clockchips.h>
17#include <linux/sched_clock.h>
17 18
18#include <asm/mach/time.h> 19#include <asm/mach/time.h>
19#include <asm/sched_clock.h>
20#include <mach/hardware.h> 20#include <mach/hardware.h>
21#include <mach/irqs.h> 21#include <mach/irqs.h>
22 22
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 390ae5feb1d0..b5db207dfd1e 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -21,9 +21,9 @@
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/of_irq.h> 23#include <linux/of_irq.h>
24#include <linux/sched_clock.h>
24 25
25/* Generic stuff */ 26/* Generic stuff */
26#include <asm/sched_clock.h>
27#include <asm/mach/map.h> 27#include <asm/mach/map.h>
28#include <asm/mach/time.h> 28#include <asm/mach/time.h>
29 29
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
index 837a2d52e9db..29606bd75f3f 100644
--- a/arch/arm/plat-iop/time.c
+++ b/arch/arm/plat-iop/time.c
@@ -22,9 +22,9 @@
22#include <linux/clocksource.h> 22#include <linux/clocksource.h>
23#include <linux/clockchips.h> 23#include <linux/clockchips.h>
24#include <linux/export.h> 24#include <linux/export.h>
25#include <linux/sched_clock.h>
25#include <mach/hardware.h> 26#include <mach/hardware.h>
26#include <asm/irq.h> 27#include <asm/irq.h>
27#include <asm/sched_clock.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/mach/irq.h> 29#include <asm/mach/irq.h>
30#include <asm/mach/time.h> 30#include <asm/mach/time.h>
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 5b0b86bb34bb..d9bc98eb2a6b 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,9 +18,9 @@
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/clocksource.h> 20#include <linux/clocksource.h>
21#include <linux/sched_clock.h>
21 22
22#include <asm/mach/time.h> 23#include <asm/mach/time.h>
23#include <asm/sched_clock.h>
24 24
25#include <plat/counter-32k.h> 25#include <plat/counter-32k.h>
26 26
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 5d5ac0f05422..9d2b2ac74938 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -16,7 +16,7 @@
16#include <linux/clockchips.h> 16#include <linux/clockchips.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/irq.h> 18#include <linux/irq.h>
19#include <asm/sched_clock.h> 19#include <linux/sched_clock.h>
20 20
21/* 21/*
22 * MBus bridge block registers. 22 * MBus bridge block registers.
diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c
index f899cbc9b288..2957075ca836 100644
--- a/arch/arm/plat-samsung/samsung-time.c
+++ b/arch/arm/plat-samsung/samsung-time.c
@@ -15,12 +15,12 @@
15#include <linux/clk.h> 15#include <linux/clk.h>
16#include <linux/clockchips.h> 16#include <linux/clockchips.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/sched_clock.h>
18 19
19#include <asm/smp_twd.h> 20#include <asm/smp_twd.h>
20#include <asm/mach/time.h> 21#include <asm/mach/time.h>
21#include <asm/mach/arch.h> 22#include <asm/mach/arch.h>
22#include <asm/mach/map.h> 23#include <asm/mach/map.h>
23#include <asm/sched_clock.h>
24 24
25#include <mach/map.h> 25#include <mach/map.h>
26#include <plat/devs.h> 26#include <plat/devs.h>
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c
index b33b74c87232..51b109e3b6c3 100644
--- a/arch/arm/plat-versatile/sched-clock.c
+++ b/arch/arm/plat-versatile/sched-clock.c
@@ -20,8 +20,8 @@
20 */ 20 */
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/sched_clock.h>
23 24
24#include <asm/sched_clock.h>
25#include <plat/sched_clock.h> 25#include <plat/sched_clock.h>
26 26
27static void __iomem *ctr; 27static void __iomem *ctr;
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h
index d354fb781c57..a55c7efcc4ed 100644
--- a/arch/x86/include/asm/mc146818rtc.h
+++ b/arch/x86/include/asm/mc146818rtc.h
@@ -95,8 +95,8 @@ static inline unsigned char current_lock_cmos_reg(void)
95unsigned char rtc_cmos_read(unsigned char addr); 95unsigned char rtc_cmos_read(unsigned char addr);
96void rtc_cmos_write(unsigned char val, unsigned char addr); 96void rtc_cmos_write(unsigned char val, unsigned char addr);
97 97
98extern int mach_set_rtc_mmss(unsigned long nowtime); 98extern int mach_set_rtc_mmss(const struct timespec *now);
99extern unsigned long mach_get_cmos_time(void); 99extern void mach_get_cmos_time(struct timespec *now);
100 100
101#define RTC_IRQ 8 101#define RTC_IRQ 8
102 102
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h
index 73668abdbedf..1e69a75412a4 100644
--- a/arch/x86/include/asm/mrst-vrtc.h
+++ b/arch/x86/include/asm/mrst-vrtc.h
@@ -3,7 +3,7 @@
3 3
4extern unsigned char vrtc_cmos_read(unsigned char reg); 4extern unsigned char vrtc_cmos_read(unsigned char reg);
5extern void vrtc_cmos_write(unsigned char val, unsigned char reg); 5extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
6extern unsigned long vrtc_get_time(void); 6extern void vrtc_get_time(struct timespec *now);
7extern int vrtc_set_mmss(unsigned long nowtime); 7extern int vrtc_set_mmss(const struct timespec *now);
8 8
9#endif 9#endif
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index d8d99222b36a..828a1565ba57 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -142,6 +142,8 @@ struct x86_cpuinit_ops {
142 void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node); 142 void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
143}; 143};
144 144
145struct timespec;
146
145/** 147/**
146 * struct x86_platform_ops - platform specific runtime functions 148 * struct x86_platform_ops - platform specific runtime functions
147 * @calibrate_tsc: calibrate TSC 149 * @calibrate_tsc: calibrate TSC
@@ -156,8 +158,8 @@ struct x86_cpuinit_ops {
156 */ 158 */
157struct x86_platform_ops { 159struct x86_platform_ops {
158 unsigned long (*calibrate_tsc)(void); 160 unsigned long (*calibrate_tsc)(void);
159 unsigned long (*get_wallclock)(void); 161 void (*get_wallclock)(struct timespec *ts);
160 int (*set_wallclock)(unsigned long nowtime); 162 int (*set_wallclock)(const struct timespec *ts);
161 void (*iommu_shutdown)(void); 163 void (*iommu_shutdown)(void);
162 bool (*is_untracked_pat_range)(u64 start, u64 end); 164 bool (*is_untracked_pat_range)(u64 start, u64 end);
163 void (*nmi_init)(void); 165 void (*nmi_init)(void);
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 3dd37ebd591b..1f354f4b602b 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -48,10 +48,9 @@ static struct pvclock_wall_clock wall_clock;
48 * have elapsed since the hypervisor wrote the data. So we try to account for 48 * have elapsed since the hypervisor wrote the data. So we try to account for
49 * that with system time 49 * that with system time
50 */ 50 */
51static unsigned long kvm_get_wallclock(void) 51static void kvm_get_wallclock(struct timespec *now)
52{ 52{
53 struct pvclock_vcpu_time_info *vcpu_time; 53 struct pvclock_vcpu_time_info *vcpu_time;
54 struct timespec ts;
55 int low, high; 54 int low, high;
56 int cpu; 55 int cpu;
57 56
@@ -64,14 +63,12 @@ static unsigned long kvm_get_wallclock(void)
64 cpu = smp_processor_id(); 63 cpu = smp_processor_id();
65 64
66 vcpu_time = &hv_clock[cpu].pvti; 65 vcpu_time = &hv_clock[cpu].pvti;
67 pvclock_read_wallclock(&wall_clock, vcpu_time, &ts); 66 pvclock_read_wallclock(&wall_clock, vcpu_time, now);
68 67
69 preempt_enable(); 68 preempt_enable();
70
71 return ts.tv_sec;
72} 69}
73 70
74static int kvm_set_wallclock(unsigned long now) 71static int kvm_set_wallclock(const struct timespec *now)
75{ 72{
76 return -1; 73 return -1;
77} 74}
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 198eb201ed3b..0aa29394ed6f 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -38,8 +38,9 @@ EXPORT_SYMBOL(rtc_lock);
38 * jump to the next second precisely 500 ms later. Check the Motorola 38 * jump to the next second precisely 500 ms later. Check the Motorola
39 * MC146818A or Dallas DS12887 data sheet for details. 39 * MC146818A or Dallas DS12887 data sheet for details.
40 */ 40 */
41int mach_set_rtc_mmss(unsigned long nowtime) 41int mach_set_rtc_mmss(const struct timespec *now)
42{ 42{
43 unsigned long nowtime = now->tv_sec;
43 struct rtc_time tm; 44 struct rtc_time tm;
44 int retval = 0; 45 int retval = 0;
45 46
@@ -58,7 +59,7 @@ int mach_set_rtc_mmss(unsigned long nowtime)
58 return retval; 59 return retval;
59} 60}
60 61
61unsigned long mach_get_cmos_time(void) 62void mach_get_cmos_time(struct timespec *now)
62{ 63{
63 unsigned int status, year, mon, day, hour, min, sec, century = 0; 64 unsigned int status, year, mon, day, hour, min, sec, century = 0;
64 unsigned long flags; 65 unsigned long flags;
@@ -107,7 +108,8 @@ unsigned long mach_get_cmos_time(void)
107 } else 108 } else
108 year += CMOS_YEARS_OFFS; 109 year += CMOS_YEARS_OFFS;
109 110
110 return mktime(year, mon, day, hour, min, sec); 111 now->tv_sec = mktime(year, mon, day, hour, min, sec);
112 now->tv_nsec = 0;
111} 113}
112 114
113/* Routines for accessing the CMOS RAM/RTC. */ 115/* Routines for accessing the CMOS RAM/RTC. */
@@ -135,18 +137,13 @@ EXPORT_SYMBOL(rtc_cmos_write);
135 137
136int update_persistent_clock(struct timespec now) 138int update_persistent_clock(struct timespec now)
137{ 139{
138 return x86_platform.set_wallclock(now.tv_sec); 140 return x86_platform.set_wallclock(&now);
139} 141}
140 142
141/* not static: needed by APM */ 143/* not static: needed by APM */
142void read_persistent_clock(struct timespec *ts) 144void read_persistent_clock(struct timespec *ts)
143{ 145{
144 unsigned long retval; 146 x86_platform.get_wallclock(ts);
145
146 retval = x86_platform.get_wallclock();
147
148 ts->tv_sec = retval;
149 ts->tv_nsec = 0;
150} 147}
151 148
152 149
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index d482bcaf61c1..6a22c19da663 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -882,9 +882,9 @@ int lguest_setup_irq(unsigned int irq)
882 * It would be far better for everyone if the Guest had its own clock, but 882 * It would be far better for everyone if the Guest had its own clock, but
883 * until then the Host gives us the time on every interrupt. 883 * until then the Host gives us the time on every interrupt.
884 */ 884 */
885static unsigned long lguest_get_wallclock(void) 885static void lguest_get_wallclock(struct timespec *now)
886{ 886{
887 return lguest_data.time.tv_sec; 887 *now = lguest_data.time;
888} 888}
889 889
890/* 890/*
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index b410b71bdcf7..c8d5577044bb 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -274,8 +274,9 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
274 return status; 274 return status;
275} 275}
276 276
277int efi_set_rtc_mmss(unsigned long nowtime) 277int efi_set_rtc_mmss(const struct timespec *now)
278{ 278{
279 unsigned long nowtime = now->tv_sec;
279 efi_status_t status; 280 efi_status_t status;
280 efi_time_t eft; 281 efi_time_t eft;
281 efi_time_cap_t cap; 282 efi_time_cap_t cap;
@@ -310,7 +311,7 @@ int efi_set_rtc_mmss(unsigned long nowtime)
310 return 0; 311 return 0;
311} 312}
312 313
313unsigned long efi_get_time(void) 314void efi_get_time(struct timespec *now)
314{ 315{
315 efi_status_t status; 316 efi_status_t status;
316 efi_time_t eft; 317 efi_time_t eft;
@@ -320,8 +321,9 @@ unsigned long efi_get_time(void)
320 if (status != EFI_SUCCESS) 321 if (status != EFI_SUCCESS)
321 pr_err("Oops: efitime: can't read time!\n"); 322 pr_err("Oops: efitime: can't read time!\n");
322 323
323 return mktime(eft.year, eft.month, eft.day, eft.hour, 324 now->tv_sec = mktime(eft.year, eft.month, eft.day, eft.hour,
324 eft.minute, eft.second); 325 eft.minute, eft.second);
326 now->tv_nsec = 0;
325} 327}
326 328
327/* 329/*
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index d62b0a3b5c14..5e355b134ba4 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -56,7 +56,7 @@ void vrtc_cmos_write(unsigned char val, unsigned char reg)
56} 56}
57EXPORT_SYMBOL_GPL(vrtc_cmos_write); 57EXPORT_SYMBOL_GPL(vrtc_cmos_write);
58 58
59unsigned long vrtc_get_time(void) 59void vrtc_get_time(struct timespec *now)
60{ 60{
61 u8 sec, min, hour, mday, mon; 61 u8 sec, min, hour, mday, mon;
62 unsigned long flags; 62 unsigned long flags;
@@ -82,17 +82,18 @@ unsigned long vrtc_get_time(void)
82 printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " 82 printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
83 "mon: %d year: %d\n", sec, min, hour, mday, mon, year); 83 "mon: %d year: %d\n", sec, min, hour, mday, mon, year);
84 84
85 return mktime(year, mon, mday, hour, min, sec); 85 now->tv_sec = mktime(year, mon, mday, hour, min, sec);
86 now->tv_nsec = 0;
86} 87}
87 88
88int vrtc_set_mmss(unsigned long nowtime) 89int vrtc_set_mmss(const struct timespec *now)
89{ 90{
90 unsigned long flags; 91 unsigned long flags;
91 struct rtc_time tm; 92 struct rtc_time tm;
92 int year; 93 int year;
93 int retval = 0; 94 int retval = 0;
94 95
95 rtc_time_to_tm(nowtime, &tm); 96 rtc_time_to_tm(now->tv_sec, &tm);
96 if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) { 97 if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
97 /* 98 /*
98 * tm.year is the number of years since 1900, and the 99 * tm.year is the number of years since 1900, and the
@@ -110,7 +111,7 @@ int vrtc_set_mmss(unsigned long nowtime)
110 } else { 111 } else {
111 printk(KERN_ERR 112 printk(KERN_ERR
112 "%s: Invalid vRTC value: write of %lx to vRTC failed\n", 113 "%s: Invalid vRTC value: write of %lx to vRTC failed\n",
113 __FUNCTION__, nowtime); 114 __FUNCTION__, now->tv_sec);
114 retval = -EINVAL; 115 retval = -EINVAL;
115 } 116 }
116 return retval; 117 return retval;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index a690868be837..ee365895b06b 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -15,6 +15,7 @@
15#include <linux/math64.h> 15#include <linux/math64.h>
16#include <linux/gfp.h> 16#include <linux/gfp.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/pvclock_gtod.h>
18 19
19#include <asm/pvclock.h> 20#include <asm/pvclock.h>
20#include <asm/xen/hypervisor.h> 21#include <asm/xen/hypervisor.h>
@@ -179,34 +180,56 @@ static void xen_read_wallclock(struct timespec *ts)
179 put_cpu_var(xen_vcpu); 180 put_cpu_var(xen_vcpu);
180} 181}
181 182
182static unsigned long xen_get_wallclock(void) 183static void xen_get_wallclock(struct timespec *now)
183{ 184{
184 struct timespec ts; 185 xen_read_wallclock(now);
186}
185 187
186 xen_read_wallclock(&ts); 188static int xen_set_wallclock(const struct timespec *now)
187 return ts.tv_sec; 189{
190 return -1;
188} 191}
189 192
190static int xen_set_wallclock(unsigned long now) 193static int xen_pvclock_gtod_notify(struct notifier_block *nb,
194 unsigned long was_set, void *priv)
191{ 195{
196 /* Protected by the calling core code serialization */
197 static struct timespec next_sync;
198
192 struct xen_platform_op op; 199 struct xen_platform_op op;
193 int rc; 200 struct timespec now;
194 201
195 /* do nothing for domU */ 202 now = __current_kernel_time();
196 if (!xen_initial_domain()) 203
197 return -1; 204 /*
205 * We only take the expensive HV call when the clock was set
206 * or when the 11 minutes RTC synchronization time elapsed.
207 */
208 if (!was_set && timespec_compare(&now, &next_sync) < 0)
209 return NOTIFY_OK;
198 210
199 op.cmd = XENPF_settime; 211 op.cmd = XENPF_settime;
200 op.u.settime.secs = now; 212 op.u.settime.secs = now.tv_sec;
201 op.u.settime.nsecs = 0; 213 op.u.settime.nsecs = now.tv_nsec;
202 op.u.settime.system_time = xen_clocksource_read(); 214 op.u.settime.system_time = xen_clocksource_read();
203 215
204 rc = HYPERVISOR_dom0_op(&op); 216 (void)HYPERVISOR_dom0_op(&op);
205 WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now);
206 217
207 return rc; 218 /*
219 * Move the next drift compensation time 11 minutes
220 * ahead. That's emulating the sync_cmos_clock() update for
221 * the hardware RTC.
222 */
223 next_sync = now;
224 next_sync.tv_sec += 11 * 60;
225
226 return NOTIFY_OK;
208} 227}
209 228
229static struct notifier_block xen_pvclock_gtod_notifier = {
230 .notifier_call = xen_pvclock_gtod_notify,
231};
232
210static struct clocksource xen_clocksource __read_mostly = { 233static struct clocksource xen_clocksource __read_mostly = {
211 .name = "xen", 234 .name = "xen",
212 .rating = 400, 235 .rating = 400,
@@ -482,6 +505,9 @@ static void __init xen_time_init(void)
482 xen_setup_runstate_info(cpu); 505 xen_setup_runstate_info(cpu);
483 xen_setup_timer(cpu); 506 xen_setup_timer(cpu);
484 xen_setup_cpu_clockevents(); 507 xen_setup_cpu_clockevents();
508
509 if (xen_initial_domain())
510 pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
485} 511}
486 512
487void __init xen_init_time_ops(void) 513void __init xen_init_time_ops(void)
@@ -494,7 +520,9 @@ void __init xen_init_time_ops(void)
494 520
495 x86_platform.calibrate_tsc = xen_tsc_khz; 521 x86_platform.calibrate_tsc = xen_tsc_khz;
496 x86_platform.get_wallclock = xen_get_wallclock; 522 x86_platform.get_wallclock = xen_get_wallclock;
497 x86_platform.set_wallclock = xen_set_wallclock; 523 /* Dom0 uses the native method to set the hardware RTC. */
524 if (!xen_initial_domain())
525 x86_platform.set_wallclock = xen_set_wallclock;
498} 526}
499 527
500#ifdef CONFIG_XEN_PVHVM 528#ifdef CONFIG_XEN_PVHVM