From: Jiri Denemark <[email protected]>

When probing host model CPU we already expand it to get a list of all
CPU features. Let's store the expanded CPU definition in virQEMUCaps and
copy it to domain capabilities when requested by the
VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES flag instead of
expanding the CPU over and over on each request.

Signed-off-by: Jiri Denemark <[email protected]>
---
 src/qemu/qemu_capabilities.c | 36 +++++++++++++++++++++++++-----------
 src/qemu/qemu_capabilities.h |  4 ++++
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 166d6ed540..8295a9ae9d 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1978,6 +1978,9 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUData *dst,
     if (src->reported)
         dst->reported = virCPUDefCopy(src->reported);
 
+    if (src->supported)
+        dst->supported = virCPUDefCopy(src->supported);
+
     if (src->migratable)
         dst->migratable = virCPUDefCopy(src->migratable);
 
@@ -1991,6 +1994,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUData 
*cpuData)
 {
     qemuMonitorCPUModelInfoFree(cpuData->info);
     virCPUDefFree(cpuData->reported);
+    virCPUDefFree(cpuData->supported);
     virCPUDefFree(cpuData->migratable);
     virCPUDefFree(cpuData->full);
 
@@ -2317,6 +2321,9 @@ virQEMUCapsGetHostModel(virQEMUCaps *qemuCaps,
         /* 'full' is non-NULL only if we have data from both QEMU and
          * virCPUGetHost */
         return cpuData->full ? cpuData->full : cpuData->reported;
+
+    case VIR_QEMU_CAPS_HOST_CPU_SUPPORTED:
+        return cpuData->supported;
     }
 
     return NULL;
@@ -2328,6 +2335,7 @@ virQEMUCapsSetHostModel(virQEMUCaps *qemuCaps,
                         virDomainVirtType type,
                         unsigned int physAddrSize,
                         virCPUDef *reported,
+                        virCPUDef *supported,
                         virCPUDef *migratable,
                         virCPUDef *full)
 {
@@ -2336,6 +2344,7 @@ virQEMUCapsSetHostModel(virQEMUCaps *qemuCaps,
     cpuData = &virQEMUCapsGetAccel(qemuCaps, type)->hostCPU;
     cpuData->physAddrSize = physAddrSize;
     cpuData->reported = reported;
+    cpuData->supported = supported;
     cpuData->migratable = migratable;
     cpuData->full = full;
 }
@@ -4139,16 +4148,18 @@ virQEMUCapsInitHostCPUModel(virQEMUCaps *qemuCaps,
 
         virCPUDefCopyModelFilter(cpu, hostCPU, true, 
virQEMUCapsCPUFilterFeatures,
                                  &qemuCaps->arch);
-    } else if (virQEMUCapsTypeIsAccelerated(type) &&
-               virCPUGetHostIsSupported(qemuCaps->arch)) {
+    }
+
+    cpuExpanded = virCPUDefCopy(cpu);
+    if (virCPUExpandFeatures(qemuCaps->arch, cpuExpanded) < 0)
+        goto error;
+
+    if (rc == 0 &&
+        virQEMUCapsTypeIsAccelerated(type) &&
+        virCPUGetHostIsSupported(qemuCaps->arch)) {
         if (!(fullCPU = virQEMUCapsProbeHostCPU(qemuCaps->arch, NULL)))
             goto error;
 
-        cpuExpanded = virCPUDefCopy(cpu);
-
-        if (virCPUExpandFeatures(qemuCaps->arch, cpuExpanded) < 0)
-            goto error;
-
         for (i = 0; i < cpuExpanded->nfeatures; i++) {
             if (cpuExpanded->features[i].policy == VIR_CPU_FEATURE_REQUIRE)
                 virCPUDefUpdateFeature(fullCPU, cpuExpanded->features[i].name,
@@ -4187,6 +4198,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCaps *qemuCaps,
 
     virQEMUCapsSetHostModel(qemuCaps, type, physAddrSize,
                             g_steal_pointer(&cpu),
+                            g_steal_pointer(&cpuExpanded),
                             g_steal_pointer(&migCPU),
                             g_steal_pointer(&fullCPU));
 
@@ -6643,9 +6655,14 @@ virQEMUCapsFillDomainCPUHostModel(virQEMUCaps *qemuCaps,
                                   virDomainCaps *domCaps,
                                   unsigned int flags)
 {
-    virQEMUCapsHostCPUType cpuType = VIR_QEMU_CAPS_HOST_CPU_REPORTED;
+    virQEMUCapsHostCPUType cpuType;
     virCPUDef *cpu;
 
+    if (flags & VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES)
+        cpuType = VIR_QEMU_CAPS_HOST_CPU_SUPPORTED;
+    else
+        cpuType = VIR_QEMU_CAPS_HOST_CPU_REPORTED;
+
     cpu = virCPUDefCopy(virQEMUCapsGetHostModel(qemuCaps, domCaps->virttype,
                                                 cpuType));
     domCaps->cpu.hostModel = cpu;
@@ -6656,9 +6673,6 @@ virQEMUCapsFillDomainCPUHostModel(virQEMUCaps *qemuCaps,
         virQEMUCapsUpdateCPUDeprecatedFeatures(qemuCaps, domCaps->virttype,
                                                cpu, VIR_CPU_FEATURE_DISABLE);
     }
-
-    if (flags & VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES)
-        virCPUExpandFeatures(domCaps->arch, cpu);
 }
 
 
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index b26b5d3145..53db699ae7 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -795,6 +795,10 @@ typedef enum {
      * combined with features reported by QEMU. This is used for backward
      * compatible comparison between a guest CPU and a host CPU. */
     VIR_QEMU_CAPS_HOST_CPU_FULL,
+    /* Host CPU definition containing all supported features, including those
+     * that should not be automatically included in a host-model CPU and
+     * features that are implicitly enabled by the selected CPU model. */
+    VIR_QEMU_CAPS_HOST_CPU_SUPPORTED,
 } virQEMUCapsHostCPUType;
 
 virCPUDef *virQEMUCapsGetHostModel(virQEMUCaps *qemuCaps,
-- 
2.54.0

Reply via email to