diff options
-rw-r--r-- | arch/x86/xen/time.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 3364850d23e6..7a5671b4fec6 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -199,37 +199,42 @@ static void xen_get_wallclock(struct timespec *now) | |||
199 | 199 | ||
200 | static int xen_set_wallclock(const struct timespec *now) | 200 | static int xen_set_wallclock(const struct timespec *now) |
201 | { | 201 | { |
202 | struct xen_platform_op op; | 202 | return -1; |
203 | |||
204 | /* do nothing for domU */ | ||
205 | if (!xen_initial_domain()) | ||
206 | return -1; | ||
207 | |||
208 | op.cmd = XENPF_settime; | ||
209 | op.u.settime.secs = now->tv_sec; | ||
210 | op.u.settime.nsecs = now->tv_nsec; | ||
211 | op.u.settime.system_time = xen_clocksource_read(); | ||
212 | |||
213 | return HYPERVISOR_dom0_op(&op); | ||
214 | } | 203 | } |
215 | 204 | ||
216 | static int xen_pvclock_gtod_notify(struct notifier_block *nb, unsigned long was_set, | 205 | static int xen_pvclock_gtod_notify(struct notifier_block *nb, |
217 | void *priv) | 206 | unsigned long was_set, void *priv) |
218 | { | 207 | { |
219 | struct timespec now; | 208 | /* Protected by the calling core code serialization */ |
220 | struct xen_platform_op op; | 209 | static struct timespec next_sync; |
221 | 210 | ||
222 | if (!was_set) | 211 | struct xen_platform_op op; |
223 | return NOTIFY_OK; | 212 | struct timespec now; |
224 | 213 | ||
225 | now = __current_kernel_time(); | 214 | now = __current_kernel_time(); |
226 | 215 | ||
216 | /* | ||
217 | * We only take the expensive HV call when the clock was set | ||
218 | * or when the 11 minutes RTC synchronization time elapsed. | ||
219 | */ | ||
220 | if (!was_set && timespec_compare(&now, &next_sync) < 0) | ||
221 | return NOTIFY_OK; | ||
222 | |||
227 | op.cmd = XENPF_settime; | 223 | op.cmd = XENPF_settime; |
228 | op.u.settime.secs = now.tv_sec; | 224 | op.u.settime.secs = now.tv_sec; |
229 | op.u.settime.nsecs = now.tv_nsec; | 225 | op.u.settime.nsecs = now.tv_nsec; |
230 | op.u.settime.system_time = xen_clocksource_read(); | 226 | op.u.settime.system_time = xen_clocksource_read(); |
231 | 227 | ||
232 | (void)HYPERVISOR_dom0_op(&op); | 228 | (void)HYPERVISOR_dom0_op(&op); |
229 | |||
230 | /* | ||
231 | * Move the next drift compensation time 11 minutes | ||
232 | * ahead. That's emulating the sync_cmos_clock() update for | ||
233 | * the hardware RTC. | ||
234 | */ | ||
235 | next_sync = now; | ||
236 | next_sync.tv_sec += 11 * 60; | ||
237 | |||
233 | return NOTIFY_OK; | 238 | return NOTIFY_OK; |
234 | } | 239 | } |
235 | 240 | ||
@@ -513,7 +518,9 @@ void __init xen_init_time_ops(void) | |||
513 | 518 | ||
514 | x86_platform.calibrate_tsc = xen_tsc_khz; | 519 | x86_platform.calibrate_tsc = xen_tsc_khz; |
515 | x86_platform.get_wallclock = xen_get_wallclock; | 520 | x86_platform.get_wallclock = xen_get_wallclock; |
516 | x86_platform.set_wallclock = xen_set_wallclock; | 521 | /* Dom0 uses the native method to set the hardware RTC. */ |
522 | if (!xen_initial_domain()) | ||
523 | x86_platform.set_wallclock = xen_set_wallclock; | ||
517 | } | 524 | } |
518 | 525 | ||
519 | #ifdef CONFIG_XEN_PVHVM | 526 | #ifdef CONFIG_XEN_PVHVM |