From dc6252c81a64c798ad774505f4dc47c09bf2ea8c Mon Sep 17 00:00:00 2001 Message-Id: From: Marcelo Tosatti Date: Fri, 5 Jul 2013 19:31:30 +0200 Subject: [PATCH 1/3] kvmclock: clock should count only if vm is running RH-Author: Marcelo Tosatti Message-id: <20130705193130.GA19059@amt.cnet> Patchwork-id: 52353 O-Subject: [PATCH RHEL6.5 qemu-kvm] kvmclock: clock should count only if vm is running Bugzilla: 903454 RH-Acked-by: Gleb Natapov RH-Acked-by: Igor Mammedov RH-Acked-by: Paolo Bonzini BZ: 903454 commit acaa14a2341c3944f394ff0ca484d1fea3ec7b5a upstream (of qemu-kvm.git uq/master branch). kvmclock should not count while vm is paused, because: 1) if the vm is paused for long periods, timekeeping math can overflow while converting the (large) clocksource delta to nanoseconds. 2) Users rely on CLOCK_MONOTONIC to count run time, that is, time which OS has been in a runnable state (see CLOCK_BOOTTIME). Change kvmclock driver so as to save clock value when vm transitions from runnable to stopped state, and to restore clock value from stopped to runnable transition. Signed-off-by: Marcelo Tosatti Signed-off-by: Gleb Natapov Signed-off-by: Michal Novotny --- hw/kvmclock.c | 66 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/hw/kvmclock.c b/hw/kvmclock.c index e90d61f..0c1c294 100644 --- a/hw/kvmclock.c +++ b/hw/kvmclock.c @@ -29,40 +29,6 @@ typedef struct KVMClockState { static KVMClockState kvmclock_state; -static void kvmclock_pre_save(void *opaque) -{ - KVMClockState *s = opaque; - struct kvm_clock_data data; - int ret; - - if (s->clock_valid) { - return; - } - - ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); - if (ret < 0) { - fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); - data.clock = 0; - } - s->clock = data.clock; - /* - * If the VM is stopped, declare the clock state valid to avoid re-reading - * it on next vmsave (which would return a different value). Will be reset - * when the VM is continued. - */ - s->clock_valid = !runstate_is_running(); -} - -static int kvmclock_post_load(void *opaque, int version_id) -{ - KVMClockState *s = opaque; - struct kvm_clock_data data; - - data.clock = s->clock; - data.flags = 0; - return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); -} - static void kvmclock_vm_state_change(void *opaque, int running, RunState state) { KVMClockState *s = opaque; @@ -71,8 +37,18 @@ static void kvmclock_vm_state_change(void *opaque, int running, RunState state) int ret; if (running) { + struct kvm_clock_data data; + s->clock_valid = false; + data.clock = s->clock; + data.flags = 0; + ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); + if (ret < 0) { + fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(ret)); + abort(); + } + if (!cap_clock_ctrl) { return; } @@ -85,6 +61,26 @@ static void kvmclock_vm_state_change(void *opaque, int running, RunState state) return; } } + } else { + struct kvm_clock_data data; + int ret; + + if (s->clock_valid) { + return; + } + ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); + if (ret < 0) { + fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); + abort(); + } + s->clock = data.clock; + + /* + * If the VM is stopped, declare the clock state valid to + * avoid re-reading it on next vmsave (which would return + * a different value). Will be reset when the VM is continued. + */ + s->clock_valid = true; } } @@ -93,8 +89,6 @@ static const VMStateDescription kvmclock_vmsd = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .pre_save = kvmclock_pre_save, - .post_load = kvmclock_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64(clock, KVMClockState), VMSTATE_END_OF_LIST() -- 1.7.11.7