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