From 47275214789017a509aba641803efe7faf9643b6 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Tue, 8 Feb 2011 16:08:58 -0200 Subject: [PATCH 01/10] kvm: make tsc stable over migration and machine start RH-Author: Glauber Costa Message-id: <1297181338-15127-1-git-send-email-glommer@redhat.com> Patchwork-id: 17863 O-Subject: [RHEL6.1 PATCH v2] kvm: make tsc stable over migration and machine start Bugzilla: 662386 RH-Acked-by: Xiao Wang RH-Acked-by: Marcelo Tosatti RH-Acked-by: Alex Williamson RH-Author: Glauber Costa Upstream: 6fa29c9f3f694cc673bc24f85519aecb4515f692 RH-Bugzilla: 662386 If the machine is stopped, we should not record two different tsc values upon a save operation. The same problem happens with kvmclock. But kvmclock is taking a different diretion, being now seen as a separate device. Since this is unlikely to happen with the tsc, I am taking the approach here of simply registering a handler for state change, and using a per-CPUState variable that prevents double updates for the TSC. Signed-off-by: Glauber Costa --- Differences from upstream: * trivial code replacements * inclusion of qemu-common.h in cpu.h, for the bool type v2: marcelo correctly pointed out we're still using those from qemu-kvm-x86.c My bad --- qemu-kvm-x86.c | 19 ++++++++++++++++++- target-i386/cpu.h | 4 +++- 2 files changed, 21 insertions(+), 2 deletions(-) Signed-off-by: Luiz Capitulino --- qemu-kvm-x86.c | 19 ++++++++++++++++++- target-i386/cpu.h | 4 +++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index d4fdb88..2d581cc 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -1218,7 +1218,12 @@ void kvm_arch_save_regs(CPUState *env) msrs[n++].index = MSR_IA32_SYSENTER_EIP; if (kvm_has_msr_star) msrs[n++].index = MSR_STAR; - msrs[n++].index = MSR_IA32_TSC; + + if (!env->tsc_valid) { + msrs[n++].index = MSR_IA32_TSC; + env->tsc_valid = !vm_running; + } + if (kvm_has_vm_hsave_pa) msrs[n++].index = MSR_VM_HSAVE_PA; #ifdef TARGET_X86_64 @@ -1314,6 +1319,15 @@ static void kvm_trim_features(uint32_t *features, uint32_t supported) } } +static void cpu_update_state(void *opaque, int running, int reason) +{ + CPUState *env = opaque; + + if (running) { + env->tsc_valid = false; + } +} + int kvm_arch_init_vcpu(CPUState *cenv) { struct kvm_cpuid_entry2 cpuid_ent[100]; @@ -1421,6 +1435,9 @@ int kvm_arch_init_vcpu(CPUState *cenv) #ifdef KVM_EXIT_TPR_ACCESS kvm_tpr_vcpu_start(cenv); #endif + + qemu_add_vm_change_state_handler(cpu_update_state, cenv); + return 0; } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index b64bd02..47de043 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -20,6 +20,7 @@ #define CPU_I386_H #include "config.h" +#include "qemu-common.h" #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64 @@ -718,7 +719,8 @@ typedef struct CPUX86State { uint8_t has_error_code; uint32_t sipi_vector; uint32_t cpuid_kvm_features; - + bool tsc_valid; + /* in order to simplify APIC support, we leave this pointer to the user */ struct APICState *apic_state; -- 1.7.4.rc1.16.gd2f15e