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 |
