aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/time.c45
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
200static int xen_set_wallclock(const struct timespec *now) 200static 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
216static int xen_pvclock_gtod_notify(struct notifier_block *nb, unsigned long was_set, 205static 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