X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fi386%2Fkvm%2Fclock.c;h=f25977d3f68075d54981633a02e2759cda7393f2;hb=b77af26e973705e8fd96cff102fc978ee44043da;hp=d98cf9d5d109e4bfe0e863a64bfb0f9abd418dda;hpb=d6454270575da1f16a8923c7cb240e46ef243f72;p=mirror_qemu.git diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index d98cf9d5d1..f25977d3f6 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -14,25 +14,26 @@ */ #include "qemu/osdep.h" -#include "cpu.h" #include "qemu/host-utils.h" #include "qemu/module.h" -#include "sysemu/sysemu.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/i386/kvm/clock.h" +#include "hw/qdev-properties.h" #include "qapi/error.h" #include #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 >*/ @@ -40,13 +41,16 @@ typedef struct KVMClockState { 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; @@ -62,7 +66,7 @@ struct pvclock_vcpu_time_info { static uint64_t kvmclock_current_nsec(KVMClockState *s) { CPUState *cpu = first_cpu; - CPUX86State *env = cpu->env_ptr; + CPUX86State *env = cpu_env(cpu); hwaddr kvmclock_struct_pa; uint64_t migration_tsc = env->tsc; struct pvclock_vcpu_time_info time; @@ -101,7 +105,7 @@ static void kvm_update_clock(KVMClockState *s) ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); if (ret < 0) { - fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); + fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(-ret)); abort(); } s->clock = data.clock; @@ -157,7 +161,7 @@ static void do_kvmclock_ctrl(CPUState *cpu, run_on_cpu_data data) } } -static void kvmclock_vm_state_change(void *opaque, int running, +static void kvmclock_vm_state_change(void *opaque, bool running, RunState state) { KVMClockState *s = opaque; @@ -185,7 +189,7 @@ static void kvmclock_vm_state_change(void *opaque, int running, data.clock = s->clock; ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); if (ret < 0) { - fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(ret)); + fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(-ret)); abort(); } @@ -201,6 +205,8 @@ static void kvmclock_vm_state_change(void *opaque, int running, return; } + s->runstate_paused = runstate_check(RUN_STATE_PAUSED); + kvm_synchronize_all_tsc(); kvm_update_clock(s); @@ -259,9 +265,9 @@ static int kvmclock_pre_load(void *opaque) } /* - * 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() * * @@ -276,7 +282,9 @@ static int kvmclock_pre_save(void *opaque) { KVMClockState *s = opaque; - kvm_update_clock(s); + if (!s->runstate_paused) { + kvm_update_clock(s); + } return 0; } @@ -309,7 +317,7 @@ static void kvmclock_class_init(ObjectClass *klass, void *data) dc->realize = kvmclock_realize; dc->vmsd = &kvmclock_vmsd; - dc->props = kvmclock_properties; + device_class_set_props(dc, kvmclock_properties); } static const TypeInfo kvmclock_info = { @@ -320,11 +328,16 @@ 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() && + assert(kvm_enabled()); + if (!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);