]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
cpu: Fix VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
authorJiri Denemark <jdenemar@redhat.com>
Mon, 27 Jan 2014 16:03:55 +0000 (17:03 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Tue, 28 Jan 2014 21:12:47 +0000 (22:12 +0100)
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.

(cherry picked from commit 802f157e8c7afaf4971b82705f67519939d2da0c)

Conflicts:
src/cpu/cpu_x86.c - some structs and functions were renamed
    since 1.1.3

src/cpu/cpu_x86.c

index 3d5e16f66175e7a4a078b193cbdb703d3b0521dd..18e39becb70ebf1b333ea4291c405b33e0af1ca4 100644 (file)
@@ -748,6 +748,36 @@ ignore:
 }
 
 
+static struct cpuX86Data *
+x86DataFromCPUFeatures(virCPUDefPtr cpu,
+                       const struct x86_map *map)
+{
+    struct cpuX86Data *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:
+    x86DataFree(data);
+    return NULL;
+}
+
+
 static struct x86_model *
 x86ModelNew(void)
 {
@@ -1319,35 +1349,6 @@ x86GuestData(virCPUDefPtr host,
     return x86Compute(host, guest, data, message);
 }
 
-static int
-x86AddFeatures(virCPUDefPtr cpu,
-               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 struct cpuX86Data *data,
@@ -1361,6 +1362,9 @@ x86Decode(virCPUDefPtr cpu,
     const struct x86_model *candidate;
     virCPUDefPtr cpuCandidate;
     virCPUDefPtr cpuModel = NULL;
+    struct cpuX86Data *copy = NULL;
+    struct cpuX86Data *features = NULL;
+    const struct cpuX86Data *cpuData = NULL;
     size_t i;
 
     virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
@@ -1417,6 +1421,7 @@ x86Decode(virCPUDefPtr cpu,
         if (preferred && STREQ(cpuCandidate->model, preferred)) {
             virCPUDefFree(cpuModel);
             cpuModel = cpuCandidate;
+            cpuData = candidate->data;
             break;
         }
 
@@ -1424,8 +1429,10 @@ x86Decode(virCPUDefPtr cpu,
             || cpuModel->nfeatures > cpuCandidate->nfeatures) {
             virCPUDefFree(cpuModel);
             cpuModel = cpuCandidate;
-        } else
+            cpuData = candidate->data;
+        } else {
             virCPUDefFree(cpuCandidate);
+        }
 
     next:
         candidate = candidate->next;
@@ -1437,9 +1444,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;
@@ -1451,7 +1466,8 @@ x86Decode(virCPUDefPtr cpu,
 out:
     x86MapFree(map);
     virCPUDefFree(cpuModel);
-
+    x86DataFree(copy);
+    x86DataFree(features);
     return ret;
 }