3e5111
From ea1a18cc0a5722b64c37c79bee7b9ed3c220ca01 Mon Sep 17 00:00:00 2001
3e5111
Message-Id: <ea1a18cc0a5722b64c37c79bee7b9ed3c220ca01@dist-git>
3e5111
From: Jiri Denemark <jdenemar@redhat.com>
3e5111
Date: Wed, 29 Mar 2017 15:31:17 +0200
3e5111
Subject: [PATCH] qemu: Pass migratable host CPU model to virCPUUpdate
3e5111
3e5111
We already know from QEMU which CPU features will block migration. Let's
3e5111
use this information to make a migratable copy of the host CPU model and
3e5111
use it for updating guest CPU specification. This will allow us to drop
3e5111
feature filtering from virCPUUpdate where it was just a hack.
3e5111
3e5111
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
3e5111
(cherry picked from commit 56bd7edcb5dc878beffb80d4e6a9cfb812378ded)
3e5111
3e5111
https://bugzilla.redhat.com/show_bug.cgi?id=1444421
3e5111
3e5111
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
3e5111
---
3e5111
 src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++-------
3e5111
 src/qemu/qemu_capabilities.h |  2 ++
3e5111
 src/qemu/qemu_process.c      |  2 +-
3e5111
 tests/cputest.c              |  7 +++++-
3e5111
 4 files changed, 57 insertions(+), 11 deletions(-)
3e5111
3e5111
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
3e5111
index e84de9f5b..ec773971e 100644
3e5111
--- a/src/qemu/qemu_capabilities.c
3e5111
+++ b/src/qemu/qemu_capabilities.c
3e5111
@@ -385,6 +385,8 @@ struct _virQEMUCapsHostCPUData {
3e5111
     qemuMonitorCPUModelInfoPtr info;
3e5111
     /* Host CPU definition reported in domain capabilities. */
3e5111
     virCPUDefPtr reported;
3e5111
+    /* Migratable host CPU definition used for updating guest CPU. */
3e5111
+    virCPUDefPtr migratable;
3e5111
 };
3e5111
 
3e5111
 /*
3e5111
@@ -2106,6 +2108,10 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst,
3e5111
         !(dst->reported = virCPUDefCopy(src->reported)))
3e5111
         return -1;
3e5111
 
3e5111
+    if (src->migratable &&
3e5111
+        !(dst->migratable = virCPUDefCopy(src->migratable)))
3e5111
+        return -1;
3e5111
+
3e5111
     return 0;
3e5111
 }
3e5111
 
3e5111
@@ -2115,6 +2121,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData)
3e5111
 {
3e5111
     qemuMonitorCPUModelInfoFree(cpuData->info);
3e5111
     virCPUDefFree(cpuData->reported);
3e5111
+    virCPUDefFree(cpuData->migratable);
3e5111
 
3e5111
     memset(cpuData, 0, sizeof(*cpuData));
3e5111
 }
3e5111
@@ -2453,6 +2460,9 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
3e5111
     switch (cpuType) {
3e5111
     case VIR_QEMU_CAPS_HOST_CPU_REPORTED:
3e5111
         return cpuData->reported;
3e5111
+
3e5111
+    case VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE:
3e5111
+        return cpuData->migratable;
3e5111
     }
3e5111
 
3e5111
     return NULL;
3e5111
@@ -2462,11 +2472,13 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
3e5111
 static void
3e5111
 virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps,
3e5111
                         virDomainVirtType type,
3e5111
-                        virCPUDefPtr cpu)
3e5111
+                        virCPUDefPtr reported,
3e5111
+                        virCPUDefPtr migratable)
3e5111
 {
3e5111
     virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
3e5111
 
3e5111
-    cpuData->reported = cpu;
3e5111
+    cpuData->reported = reported;
3e5111
+    cpuData->migratable = migratable;
3e5111
 }
3e5111
 
3e5111
 
3e5111
@@ -3313,26 +3325,39 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
3e5111
 }
3e5111
 
3e5111
 
3e5111
+static virCPUDefPtr
3e5111
+virQEMUCapsNewHostCPUModel(void)
3e5111
+{
3e5111
+    virCPUDefPtr cpu;
3e5111
+
3e5111
+    if (VIR_ALLOC(cpu) < 0)
3e5111
+        return NULL;
3e5111
+
3e5111
+    cpu->type = VIR_CPU_TYPE_GUEST;
3e5111
+    cpu->mode = VIR_CPU_MODE_CUSTOM;
3e5111
+    cpu->match = VIR_CPU_MATCH_EXACT;
3e5111
+    cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
3e5111
+
3e5111
+    return cpu;
3e5111
+}
3e5111
+
3e5111
+
3e5111
 void
3e5111
 virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
3e5111
                             virCapsPtr caps,
3e5111
                             virDomainVirtType type)
3e5111
 {
3e5111
     virCPUDefPtr cpu = NULL;
3e5111
+    virCPUDefPtr migCPU = NULL;
3e5111
     virCPUDefPtr hostCPU = NULL;
3e5111
     int rc;
3e5111
 
3e5111
     if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
3e5111
         return;
3e5111
 
3e5111
-    if (VIR_ALLOC(cpu) < 0)
3e5111
+    if (!(cpu = virQEMUCapsNewHostCPUModel()))
3e5111
         goto error;
3e5111
 
3e5111
-    cpu->type = VIR_CPU_TYPE_GUEST;
3e5111
-    cpu->mode = VIR_CPU_MODE_CUSTOM;
3e5111
-    cpu->match = VIR_CPU_MATCH_EXACT;
3e5111
-    cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
3e5111
-
3e5111
     if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu, false)) < 0) {
3e5111
         goto error;
3e5111
     } else if (rc == 1) {
3e5111
@@ -3346,7 +3371,20 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
3e5111
             goto error;
3e5111
     }
3e5111
 
3e5111
-    virQEMUCapsSetHostModel(qemuCaps, type, cpu);
3e5111
+    if (!(migCPU = virQEMUCapsNewHostCPUModel()))
3e5111
+        goto error;
3e5111
+
3e5111
+    if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, migCPU, true)) < 0) {
3e5111
+        goto error;
3e5111
+    } else if (rc == 1) {
3e5111
+        VIR_DEBUG("CPU migratability not provided by QEMU");
3e5111
+
3e5111
+        virCPUDefFree(migCPU);
3e5111
+        if (!(migCPU = virCPUCopyMigratable(qemuCaps->arch, cpu)))
3e5111
+            goto error;
3e5111
+    }
3e5111
+
3e5111
+    virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU);
3e5111
 
3e5111
  cleanup:
3e5111
     virCPUDefFree(hostCPU);
3e5111
@@ -3354,6 +3392,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
3e5111
 
3e5111
  error:
3e5111
     virCPUDefFree(cpu);
3e5111
+    virCPUDefFree(migCPU);
3e5111
     virResetLastError();
3e5111
     goto cleanup;
3e5111
 }
3e5111
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
3e5111
index 50333fc26..16fe044cc 100644
3e5111
--- a/src/qemu/qemu_capabilities.h
3e5111
+++ b/src/qemu/qemu_capabilities.h
3e5111
@@ -454,6 +454,8 @@ int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps,
3e5111
 typedef enum {
3e5111
     /* Host CPU definition reported in domain capabilities. */
3e5111
     VIR_QEMU_CAPS_HOST_CPU_REPORTED,
3e5111
+    /* Migratable host CPU definition used for updating guest CPU. */
3e5111
+    VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE,
3e5111
 } virQEMUCapsHostCPUType;
3e5111
 
3e5111
 virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps,
3e5111
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
3e5111
index dc073891a..c81389ef2 100644
3e5111
--- a/src/qemu/qemu_process.c
3e5111
+++ b/src/qemu/qemu_process.c
3e5111
@@ -5313,7 +5313,7 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def,
3e5111
 
3e5111
     if (virCPUUpdate(def->os.arch, def->cpu,
3e5111
                      virQEMUCapsGetHostModel(qemuCaps, def->virtType,
3e5111
-                                             VIR_QEMU_CAPS_HOST_CPU_REPORTED)) < 0)
3e5111
+                                             VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) < 0)
3e5111
         goto cleanup;
3e5111
 
3e5111
     if (virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType,
3e5111
diff --git a/tests/cputest.c b/tests/cputest.c
3e5111
index 8c07cf4f6..efa891dc1 100644
3e5111
--- a/tests/cputest.c
3e5111
+++ b/tests/cputest.c
3e5111
@@ -393,6 +393,7 @@ cpuTestUpdate(const void *arg)
3e5111
     const struct data *data = arg;
3e5111
     int ret = -1;
3e5111
     virCPUDefPtr host = NULL;
3e5111
+    virCPUDefPtr migHost = NULL;
3e5111
     virCPUDefPtr cpu = NULL;
3e5111
     char *result = NULL;
3e5111
 
3e5111
@@ -400,7 +401,10 @@ cpuTestUpdate(const void *arg)
3e5111
         !(cpu = cpuTestLoadXML(data->arch, data->name)))
3e5111
         goto cleanup;
3e5111
 
3e5111
-    if (virCPUUpdate(host->arch, cpu, host) < 0)
3e5111
+    if (!(migHost = virCPUCopyMigratable(data->arch, host)))
3e5111
+        goto cleanup;
3e5111
+
3e5111
+    if (virCPUUpdate(host->arch, cpu, migHost) < 0)
3e5111
         goto cleanup;
3e5111
 
3e5111
     if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0)
3e5111
@@ -411,6 +415,7 @@ cpuTestUpdate(const void *arg)
3e5111
  cleanup:
3e5111
     virCPUDefFree(host);
3e5111
     virCPUDefFree(cpu);
3e5111
+    virCPUDefFree(migHost);
3e5111
     VIR_FREE(result);
3e5111
     return ret;
3e5111
 }
3e5111
-- 
3e5111
2.12.2
3e5111