*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "cpu.h"
#include "qemu/host-utils.h"
-#include "sysemu/sysemu.h"
+#include "qemu/module.h"
#include "sysemu/kvm.h"
+#include "sysemu/runstate.h"
#include "sysemu/hw_accel.h"
-#include "kvm_i386.h"
+#include "kvm/kvm_i386.h"
+#include "migration/vmstate.h"
#include "hw/sysbus.h"
#include "hw/kvm/clock.h"
+#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include <linux/kvm.h>
#include "standard-headers/asm-x86/kvm_para.h"
+#include "qom/object.h"
#define TYPE_KVM_CLOCK "kvmclock"
-#define KVM_CLOCK(obj) OBJECT_CHECK(KVMClockState, (obj), TYPE_KVM_CLOCK)
+OBJECT_DECLARE_SIMPLE_TYPE(KVMClockState, KVM_CLOCK)
-typedef struct KVMClockState {
+struct KVMClockState {
/*< private >*/
SysBusDevice busdev;
/*< public >*/
uint64_t clock;
bool clock_valid;
+ /* whether the 'clock' value was obtained in the 'paused' state */
+ bool runstate_paused;
+
/* whether machine type supports reliable KVM_GET_CLOCK */
bool mach_use_reliable_get_clock;
/* whether the 'clock' value was obtained in a host with
* reliable KVM_GET_CLOCK */
bool clock_is_reliable;
-} KVMClockState;
+};
struct pvclock_vcpu_time_info {
uint32_t version;
s->clock_is_reliable = kvm_has_adjust_clock_stable();
}
+static void do_kvmclock_ctrl(CPUState *cpu, run_on_cpu_data data)
+{
+ int ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0);
+
+ if (ret && ret != -EINVAL) {
+ fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
+ }
+}
+
static void kvmclock_vm_state_change(void *opaque, int running,
RunState state)
{
return;
}
CPU_FOREACH(cpu) {
- ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0);
- if (ret) {
- if (ret != -EINVAL) {
- fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
- }
- return;
- }
+ run_on_cpu(cpu, do_kvmclock_ctrl, RUN_ON_CPU_NULL);
}
} else {
return;
}
+ s->runstate_paused = runstate_check(RUN_STATE_PAUSED);
+
kvm_synchronize_all_tsc();
kvm_update_clock(s);
}
/*
- * When migrating, read the clock just before migration,
- * so that the guest clock counts during the events
- * between:
+ * When migrating a running guest, read the clock just
+ * before migration, so that the guest clock counts
+ * during the events between:
*
* * vm_stop()
* *
{
KVMClockState *s = opaque;
- kvm_update_clock(s);
+ if (!s->runstate_paused) {
+ kvm_update_clock(s);
+ }
return 0;
}
dc->realize = kvmclock_realize;
dc->vmsd = &kvmclock_vmsd;
- dc->props = kvmclock_properties;
+ device_class_set_props(dc, kvmclock_properties);
}
static const TypeInfo kvmclock_info = {
};
/* Note: Must be called after VCPU initialization. */
-void kvmclock_create(void)
+void kvmclock_create(bool create_always)
{
X86CPU *cpu = X86_CPU(first_cpu);
- if (kvm_enabled() &&
+ if (!kvm_enabled() || !kvm_has_adjust_clock())
+ return;
+
+ if (create_always ||
cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
(1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
sysbus_create_simple(TYPE_KVM_CLOCK, -1, NULL);