diff options
author | David Vrabel <david.vrabel@citrix.com> | 2013-05-13 13:56:06 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2013-05-28 17:00:59 -0400 |
commit | 3565184ed0c1ea46bea5b792da5f72a83c43e49b (patch) | |
tree | 4846a589a6aa295634ef585e5637872f15c19993 /arch/x86/xen | |
parent | 0a0a7e66fa269de78975ea8d4e825a66d92b8d70 (diff) |
x86: Increase precision of x86_platform.get/set_wallclock()
All the virtualized platforms (KVM, lguest and Xen) have persistent
wallclocks that have more than one second of precision.
read_persistent_wallclock() and update_persistent_wallclock() allow
for nanosecond precision but their implementation on x86 with
x86_platform.get/set_wallclock() only allows for one second precision.
This means guests may see a wallclock time that is off by up to 1
second.
Make set_wallclock() and get_wallclock() take a struct timespec
parameter (which allows for nanosecond precision) so KVM and Xen
guests may start with a more accurate wallclock time and a Xen dom0
can maintain a more accurate wallclock for guests.
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/time.c | 19 |
1 files changed, 6 insertions, 13 deletions
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 3d88bfdf9e1c..a1947ac2da82 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -191,32 +191,25 @@ static void xen_read_wallclock(struct timespec *ts) | |||
191 | put_cpu_var(xen_vcpu); | 191 | put_cpu_var(xen_vcpu); |
192 | } | 192 | } |
193 | 193 | ||
194 | static unsigned long xen_get_wallclock(void) | 194 | static void xen_get_wallclock(struct timespec *now) |
195 | { | 195 | { |
196 | struct timespec ts; | 196 | xen_read_wallclock(now); |
197 | |||
198 | xen_read_wallclock(&ts); | ||
199 | return ts.tv_sec; | ||
200 | } | 197 | } |
201 | 198 | ||
202 | static int xen_set_wallclock(unsigned long now) | 199 | static int xen_set_wallclock(const struct timespec *now) |
203 | { | 200 | { |
204 | struct xen_platform_op op; | 201 | struct xen_platform_op op; |
205 | int rc; | ||
206 | 202 | ||
207 | /* do nothing for domU */ | 203 | /* do nothing for domU */ |
208 | if (!xen_initial_domain()) | 204 | if (!xen_initial_domain()) |
209 | return -1; | 205 | return -1; |
210 | 206 | ||
211 | op.cmd = XENPF_settime; | 207 | op.cmd = XENPF_settime; |
212 | op.u.settime.secs = now; | 208 | op.u.settime.secs = now->tv_sec; |
213 | op.u.settime.nsecs = 0; | 209 | op.u.settime.nsecs = now->tv_nsec; |
214 | op.u.settime.system_time = xen_clocksource_read(); | 210 | op.u.settime.system_time = xen_clocksource_read(); |
215 | 211 | ||
216 | rc = HYPERVISOR_dom0_op(&op); | 212 | return HYPERVISOR_dom0_op(&op); |
217 | WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now); | ||
218 | |||
219 | return rc; | ||
220 | } | 213 | } |
221 | 214 | ||
222 | static struct clocksource xen_clocksource __read_mostly = { | 215 | static struct clocksource xen_clocksource __read_mostly = { |