render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
0a7476
From 539a83390fb4b4b0dd7b029b7dd4ba2a345611cd Mon Sep 17 00:00:00 2001
0a7476
Message-Id: <539a83390fb4b4b0dd7b029b7dd4ba2a345611cd@dist-git>
0a7476
From: Jiri Denemark <jdenemar@redhat.com>
0a7476
Date: Tue, 4 Jun 2019 13:04:33 +0200
0a7476
Subject: [PATCH] qemu: Check TSC frequency before starting QEMU
0a7476
MIME-Version: 1.0
0a7476
Content-Type: text/plain; charset=UTF-8
0a7476
Content-Transfer-Encoding: 8bit
0a7476
0a7476
When migrating a domain with invtsc CPU feature enabled, the TSC
0a7476
frequency of the destination host must match the frequency used when the
0a7476
domain was started on the source host or the destination host has to
0a7476
support TSC scaling.
0a7476
0a7476
If the frequencies do not match and the destination host does not
0a7476
support TSC scaling, QEMU will fail to set the right TSC frequency when
0a7476
starting vCPUs on the destination and thus migration will fail. However,
0a7476
this is quite late since both host might have spent significant time
0a7476
transferring memory and perhaps even storage data.
0a7476
0a7476
By adding the check to libvirt we can let migration fail before any data
0a7476
starts to be sent over. If for some reason libvirt is unable to detect
0a7476
the host's TSC frequency or scaling support, we'll just let QEMU try and
0a7476
the migration will either succeed or fail later.
0a7476
0a7476
Luckily, we mandate TSC frequency to be explicitly set in the domain XML
0a7476
to even allow migration of domains with invtsc. We can just check
0a7476
whether the requested frequency is compatible with the current host
0a7476
before starting QEMU.
0a7476
0a7476
https://bugzilla.redhat.com/show_bug.cgi?id=1641702
0a7476
0a7476
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
0a7476
(cherry picked from commit 7da62c91f043209e3d40c2dc7655c5e35a4309bf)
0a7476
0a7476
Conflicts:
0a7476
	src/qemu/qemu_process.c
0a7476
            - qemuProcessStartValidateXML function was removed upstream
0a7476
              by commit v4.9.0-89-g91afd53cb8
0a7476
0a7476
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
0a7476
Message-Id: <f5fcbf9d5afc4e156d1d2c888dc360d06bb29a1a.1559646067.git.jdenemar@redhat.com>
0a7476
Reviewed-by: Ján Tomko <jtomko@redhat.com>
0a7476
---
0a7476
 src/qemu/qemu_process.c | 53 +++++++++++++++++++++++++++++++++++++++++
0a7476
 1 file changed, 53 insertions(+)
0a7476
0a7476
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
0a7476
index 2795796166..7f70d79566 100644
0a7476
--- a/src/qemu/qemu_process.c
0a7476
+++ b/src/qemu/qemu_process.c
0a7476
@@ -5181,6 +5181,56 @@ qemuProcessStartValidateXML(virQEMUDriverPtr driver,
0a7476
 }
0a7476
 
0a7476
 
0a7476
+static int
0a7476
+qemuProcessStartValidateTSC(virDomainObjPtr vm,
0a7476
+                            virCapsPtr caps)
0a7476
+{
0a7476
+    size_t i;
0a7476
+    unsigned long long freq = 0;
0a7476
+    virHostCPUTscInfoPtr tsc;
0a7476
+
0a7476
+    for (i = 0; i < vm->def->clock.ntimers; i++) {
0a7476
+        virDomainTimerDefPtr timer = vm->def->clock.timers[i];
0a7476
+
0a7476
+        if (timer->name == VIR_DOMAIN_TIMER_NAME_TSC &&
0a7476
+            timer->frequency > 0) {
0a7476
+            freq = timer->frequency;
0a7476
+            break;
0a7476
+        }
0a7476
+    }
0a7476
+
0a7476
+    if (freq == 0)
0a7476
+        return 0;
0a7476
+
0a7476
+    VIR_DEBUG("Requested TSC frequency %llu Hz", freq);
0a7476
+
0a7476
+    if (!caps->host.cpu || !caps->host.cpu->tsc) {
0a7476
+        VIR_DEBUG("Host TSC frequency could not be probed");
0a7476
+        return 0;
0a7476
+    }
0a7476
+
0a7476
+    tsc = caps->host.cpu->tsc;
0a7476
+    VIR_DEBUG("Host TSC frequency %llu Hz, scaling %s",
0a7476
+              tsc->frequency, virTristateBoolTypeToString(tsc->scaling));
0a7476
+
0a7476
+    if (freq == tsc->frequency || tsc->scaling == VIR_TRISTATE_BOOL_YES)
0a7476
+        return 0;
0a7476
+
0a7476
+    if (tsc->scaling == VIR_TRISTATE_BOOL_ABSENT) {
0a7476
+        VIR_DEBUG("TSC frequencies do not match and scaling support is "
0a7476
+                  "unknown, QEMU will try and possibly fail later");
0a7476
+        return 0;
0a7476
+    }
0a7476
+
0a7476
+    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
0a7476
+                   _("Requested TSC frequency %llu Hz does not match "
0a7476
+                     "host (%llu Hz) and TSC scaling is not supported "
0a7476
+                     "by the host CPU"),
0a7476
+                   freq, tsc->frequency);
0a7476
+    return -1;
0a7476
+}
0a7476
+
0a7476
+
0a7476
 /**
0a7476
  * qemuProcessStartValidate:
0a7476
  * @vm: domain object
0a7476
@@ -5241,6 +5291,9 @@ qemuProcessStartValidate(virQEMUDriverPtr driver,
0a7476
     if (qemuProcessStartValidateDisks(vm, qemuCaps) < 0)
0a7476
         return -1;
0a7476
 
0a7476
+    if (qemuProcessStartValidateTSC(vm, caps) < 0)
0a7476
+        return -1;
0a7476
+
0a7476
     VIR_DEBUG("Checking for any possible (non-fatal) issues");
0a7476
 
0a7476
     qemuProcessStartWarnShmem(vm);
0a7476
-- 
0a7476
2.21.0
0a7476