static int xen_set_wallclock(const struct timespec *now)
 {
-       struct xen_platform_op op;
-
-       /* do nothing for domU */
-       if (!xen_initial_domain())
-               return -1;
-
-       op.cmd = XENPF_settime;
-       op.u.settime.secs = now->tv_sec;
-       op.u.settime.nsecs = now->tv_nsec;
-       op.u.settime.system_time = xen_clocksource_read();
-
-       return HYPERVISOR_dom0_op(&op);
+       return -1;
 }
 
-static int xen_pvclock_gtod_notify(struct notifier_block *nb, unsigned long was_set,
-                                  void *priv)
+static int xen_pvclock_gtod_notify(struct notifier_block *nb,
+                                  unsigned long was_set, void *priv)
 {
-       struct timespec now;
-       struct xen_platform_op op;
+       /* Protected by the calling core code serialization */
+       static struct timespec next_sync;
 
-       if (!was_set)
-               return NOTIFY_OK;
+       struct xen_platform_op op;
+       struct timespec now;
 
        now = __current_kernel_time();
 
+       /*
+        * We only take the expensive HV call when the clock was set
+        * or when the 11 minutes RTC synchronization time elapsed.
+        */
+       if (!was_set && timespec_compare(&now, &next_sync) < 0)
+               return NOTIFY_OK;
+
        op.cmd = XENPF_settime;
        op.u.settime.secs = now.tv_sec;
        op.u.settime.nsecs = now.tv_nsec;
        op.u.settime.system_time = xen_clocksource_read();
 
        (void)HYPERVISOR_dom0_op(&op);
+
+       /*
+        * Move the next drift compensation time 11 minutes
+        * ahead. That's emulating the sync_cmos_clock() update for
+        * the hardware RTC.
+        */
+       next_sync = now;
+       next_sync.tv_sec += 11 * 60;
+
        return NOTIFY_OK;
 }
 
 
        x86_platform.calibrate_tsc = xen_tsc_khz;
        x86_platform.get_wallclock = xen_get_wallclock;
-       x86_platform.set_wallclock = xen_set_wallclock;
+       /* Dom0 uses the native method to set the hardware RTC. */
+       if (!xen_initial_domain())
+               x86_platform.set_wallclock = xen_set_wallclock;
 }
 
 #ifdef CONFIG_XEN_PVHVM