diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2015-11-23 05:42:12 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2015-12-21 09:40:59 -0500 |
commit | 760968631323f710ea0824369bbd65f812c82f08 (patch) | |
tree | 1c5b3b9f7cf389e3a0e2406f07198d16934411af | |
parent | 7d5f6f81ddbb5b532a832cbeb65472541b22a7c2 (diff) |
xen/x86: support XENPF_settime64
Try XENPF_settime64 first, if it is not available fall back to
XENPF_settime32.
No need to call __current_kernel_time() when all the info needed are
already passed via the struct timekeeper * argument.
Return NOTIFY_BAD in case of errors.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-rw-r--r-- | arch/x86/xen/time.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 3bbd377e1657..4b8af45b211a 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -16,6 +16,7 @@ | |||
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 | #include <linux/pvclock_gtod.h> |
19 | #include <linux/timekeeper_internal.h> | ||
19 | 20 | ||
20 | #include <asm/pvclock.h> | 21 | #include <asm/pvclock.h> |
21 | #include <asm/xen/hypervisor.h> | 22 | #include <asm/xen/hypervisor.h> |
@@ -123,9 +124,13 @@ static int xen_pvclock_gtod_notify(struct notifier_block *nb, | |||
123 | static struct timespec next_sync; | 124 | static struct timespec next_sync; |
124 | 125 | ||
125 | struct xen_platform_op op; | 126 | struct xen_platform_op op; |
126 | struct timespec now; | 127 | struct timespec64 now; |
128 | struct timekeeper *tk = priv; | ||
129 | static bool settime64_supported = true; | ||
130 | int ret; | ||
127 | 131 | ||
128 | now = __current_kernel_time(); | 132 | now.tv_sec = tk->xtime_sec; |
133 | now.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift); | ||
129 | 134 | ||
130 | /* | 135 | /* |
131 | * We only take the expensive HV call when the clock was set | 136 | * We only take the expensive HV call when the clock was set |
@@ -134,12 +139,28 @@ static int xen_pvclock_gtod_notify(struct notifier_block *nb, | |||
134 | if (!was_set && timespec_compare(&now, &next_sync) < 0) | 139 | if (!was_set && timespec_compare(&now, &next_sync) < 0) |
135 | return NOTIFY_OK; | 140 | return NOTIFY_OK; |
136 | 141 | ||
137 | op.cmd = XENPF_settime32; | 142 | again: |
138 | op.u.settime32.secs = now.tv_sec; | 143 | if (settime64_supported) { |
139 | op.u.settime32.nsecs = now.tv_nsec; | 144 | op.cmd = XENPF_settime64; |
140 | op.u.settime32.system_time = xen_clocksource_read(); | 145 | op.u.settime64.mbz = 0; |
146 | op.u.settime64.secs = now.tv_sec; | ||
147 | op.u.settime64.nsecs = now.tv_nsec; | ||
148 | op.u.settime64.system_time = xen_clocksource_read(); | ||
149 | } else { | ||
150 | op.cmd = XENPF_settime32; | ||
151 | op.u.settime32.secs = now.tv_sec; | ||
152 | op.u.settime32.nsecs = now.tv_nsec; | ||
153 | op.u.settime32.system_time = xen_clocksource_read(); | ||
154 | } | ||
155 | |||
156 | ret = HYPERVISOR_platform_op(&op); | ||
141 | 157 | ||
142 | (void)HYPERVISOR_platform_op(&op); | 158 | if (ret == -ENOSYS && settime64_supported) { |
159 | settime64_supported = false; | ||
160 | goto again; | ||
161 | } | ||
162 | if (ret < 0) | ||
163 | return NOTIFY_BAD; | ||
143 | 164 | ||
144 | /* | 165 | /* |
145 | * Move the next drift compensation time 11 minutes | 166 | * Move the next drift compensation time 11 minutes |