Blob Blame History Raw
From f53b97e4cda28b911c11400a985bcff587b2df34 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Wed, 21 Aug 2019 14:30:06 +0200
Subject: [PATCH 2/3] target-i386: block migration and savevm if invariant tsc
 is exposed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RH-Author: Eduardo Habkost <ehabkost@redhat.com>
Message-id: <20190821143006.23516-3-ehabkost@redhat.com>
Patchwork-id: 90102
O-Subject: [RHEL-7.8 qemu-kvm PATCH 2/2] target-i386: block migration and savevm if invariant tsc is exposed
Bugzilla: 1626871
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Bandan Das <bsd@redhat.com>
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>

From: Marcelo Tosatti <mtosatti@redhat.com>

Invariant TSC documentation mentions that "invariant TSC will run at a
constant rate in all ACPI P-, C-. and T-states".

This is not the case if migration to a host with different TSC frequency
is allowed, or if savevm is performed. So block migration/savevm.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
[AF+mtosatti: Updated error message]
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit 68bfd0ad4a1dcc4c328d5db85dc746b49c1ec07e)
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 target-i386/cpu-qom.h |  2 +-
 target-i386/kvm.c     | 15 +++++++++++++++
 target-i386/machine.c |  2 +-
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 0b01e8f..89dd29a 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -94,7 +94,7 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 #define ENV_OFFSET offsetof(X86CPU, env)
 
 #ifndef CONFIG_USER_ONLY
-extern const struct VMStateDescription vmstate_x86_cpu;
+extern struct VMStateDescription vmstate_x86_cpu;
 #endif
 
 /**
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index d5f6deb..b6c76f1 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -33,6 +33,8 @@
 #include "exec/ioport.h"
 #include <asm/hyperv.h>
 #include "hw/pci/pci.h"
+#include "migration/migration.h"
+#include "qapi/qmp/qerror.h"
 
 //#define DEBUG_KVM
 
@@ -449,6 +451,8 @@ static bool hyperv_enabled(X86CPU *cpu)
             cpu->hyperv_relaxed_timing);
 }
 
+static Error *invtsc_mig_blocker;
+
 #define KVM_MAX_CPUID_ENTRIES  100
 
 int kvm_arch_init_vcpu(CPUState *cs)
@@ -698,6 +702,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
 
     qemu_add_vm_change_state_handler(cpu_update_state, env);
 
+    c = cpuid_find_entry(&cpuid_data.cpuid, 0x80000007, 0);
+    if (c && (c->edx & 1<<8) && invtsc_mig_blocker == NULL) {
+        /* for migration */
+        error_setg(&invtsc_mig_blocker,
+                   "State blocked by non-migratable CPU device"
+                   " (invtsc flag)");
+        migrate_add_blocker(invtsc_mig_blocker);
+        /* for savevm */
+        vmstate_x86_cpu.unmigratable = 1;
+    }
+
     cpuid_data.cpuid.padding = 0;
     r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
     if (r) {
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 507ab1a..cd2cf6f 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -778,7 +778,7 @@ static const VMStateDescription vmstate_msr_virt_ssbd = {
     }
 };
 
-const VMStateDescription vmstate_x86_cpu = {
+VMStateDescription vmstate_x86_cpu = {
     .name = "cpu",
     .version_id = 12,
     .minimum_version_id = 3,
-- 
1.8.3.1