[PATCH 2/4] cpu: Fix VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



https://bugzilla.redhat.com/show_bug.cgi?id=1049391

VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES flag for virConnectBaselineCPU
did not work if the resulting guest CPU would disable some features
present in its base model. This patch makes sure we won't try to add
such features twice.

Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx>
---
 src/cpu/cpu_x86.c | 84 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 34 deletions(-)

diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index ce75562..5d101a4 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -730,6 +730,36 @@ ignore:
 }
 
 
+static virCPUx86Data *
+x86DataFromCPUFeatures(virCPUDefPtr cpu,
+                       const struct x86_map *map)
+{
+    virCPUx86Data *data;
+    size_t i;
+
+    if (VIR_ALLOC(data) < 0)
+        return NULL;
+
+    for (i = 0; i < cpu->nfeatures; i++) {
+        const struct x86_feature *feature;
+        if (!(feature = x86FeatureFind(map, cpu->features[i].name))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unknown CPU feature %s"), cpu->features[i].name);
+            goto error;
+        }
+
+        if (x86DataAdd(data, feature->data) < 0)
+            goto error;
+    }
+
+    return data;
+
+error:
+    virCPUx86DataFree(data);
+    return NULL;
+}
+
+
 static struct x86_model *
 x86ModelNew(void)
 {
@@ -1448,35 +1478,6 @@ x86GuestData(virCPUDefPtr host,
 
 
 static int
-x86AddFeatures(virCPUDefPtr cpu,
-               const struct x86_map *map)
-{
-    const struct x86_model *candidate;
-    const struct x86_feature *feature = map->features;
-
-    candidate = map->models;
-    while (candidate != NULL) {
-        if (STREQ(cpu->model, candidate->name))
-            break;
-        candidate = candidate->next;
-    }
-    if (!candidate) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("%s not a known CPU model"), cpu->model);
-        return -1;
-    }
-    while (feature != NULL) {
-        if (x86DataIsSubset(candidate->data, feature->data) &&
-            virCPUDefAddFeature(cpu, feature->name,
-                                VIR_CPU_FEATURE_REQUIRE) < 0)
-            return -1;
-        feature = feature->next;
-    }
-    return 0;
-}
-
-
-static int
 x86Decode(virCPUDefPtr cpu,
           const virCPUx86Data *data,
           const char **models,
@@ -1489,6 +1490,9 @@ x86Decode(virCPUDefPtr cpu,
     const struct x86_model *candidate;
     virCPUDefPtr cpuCandidate;
     virCPUDefPtr cpuModel = NULL;
+    virCPUx86Data *copy = NULL;
+    virCPUx86Data *features = NULL;
+    const virCPUx86Data *cpuData = NULL;
     size_t i;
 
     virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
@@ -1545,6 +1549,7 @@ x86Decode(virCPUDefPtr cpu,
         if (preferred && STREQ(cpuCandidate->model, preferred)) {
             virCPUDefFree(cpuModel);
             cpuModel = cpuCandidate;
+            cpuData = candidate->data;
             break;
         }
 
@@ -1552,8 +1557,10 @@ x86Decode(virCPUDefPtr cpu,
             || cpuModel->nfeatures > cpuCandidate->nfeatures) {
             virCPUDefFree(cpuModel);
             cpuModel = cpuCandidate;
-        } else
+            cpuData = candidate->data;
+        } else {
             virCPUDefFree(cpuCandidate);
+        }
 
     next:
         candidate = candidate->next;
@@ -1565,9 +1572,17 @@ x86Decode(virCPUDefPtr cpu,
         goto out;
     }
 
-    if (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES &&
-        x86AddFeatures(cpuModel, map) < 0)
-        goto out;
+    if (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) {
+        if (!(copy = x86DataCopy(cpuData)) ||
+            !(features = x86DataFromCPUFeatures(cpuModel, map)))
+            goto out;
+
+        x86DataSubtract(copy, features);
+        if (x86DataToCPUFeatures(cpuModel, VIR_CPU_FEATURE_REQUIRE,
+                                 copy, map) < 0)
+            goto out;
+    }
+
     cpu->model = cpuModel->model;
     cpu->vendor = cpuModel->vendor;
     cpu->nfeatures = cpuModel->nfeatures;
@@ -1578,7 +1593,8 @@ x86Decode(virCPUDefPtr cpu,
 
 out:
     virCPUDefFree(cpuModel);
-
+    virCPUx86DataFree(copy);
+    virCPUx86DataFree(features);
     return ret;
 }
 
-- 
1.8.5.3

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]