]> xenbits.xensource.com Git - libvirt.git/commitdiff
cpu: Introduce virCPUExpandFeatures
authorJiri Denemark <jdenemar@redhat.com>
Thu, 16 Mar 2017 11:23:50 +0000 (12:23 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Mon, 27 Mar 2017 14:29:27 +0000 (16:29 +0200)
Having to use cpuBaseline with VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
flag to expand CPU features is strange. Not to mention that cpuBaseline
can only expand host CPU definitions (i.e., it completely ignores
feature policies). The new virCPUExpandFeatures API is designed to work
with both host and guest CPU definitions.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
src/cpu/cpu.c
src/cpu/cpu.h
src/cpu/cpu_x86.c
src/libvirt_private.syms

index b88f9955f3580381e03ac659f7557f365c2e36e0..ed79650459339080b048eaf332836bb64dc910c0 100644 (file)
@@ -1076,3 +1076,53 @@ virCPUConvertLegacy(virArch arch,
     VIR_DEBUG("model=%s", NULLSTR(cpu->model));
     return 0;
 }
+
+
+static int
+virCPUFeatureCompare(const void *p1,
+                     const void *p2)
+{
+    const virCPUFeatureDef *f1 = p1;
+    const virCPUFeatureDef *f2 = p2;
+
+    return strcmp(f1->name, f2->name);
+}
+
+
+/**
+ * virCPUExpandFeatures:
+ *
+ * @arch: CPU architecture
+ * @cpu: CPU definition to be expanded
+ *
+ * Add all features implicitly enabled by the CPU model to the list of
+ * features. The @cpu is expected to be either a host or a guest representation
+ * of a host CPU, i.e., only VIR_CPU_FEATURE_REQUIRE and
+ * VIR_CPU_FEATURE_DISABLE policies are supported.
+ *
+ * The updated list of features in the CPU definition is sorted.
+ *
+ * Return -1 on error, 0 on success.
+ */
+int
+virCPUExpandFeatures(virArch arch,
+                     virCPUDefPtr cpu)
+{
+    struct cpuArchDriver *driver;
+
+    VIR_DEBUG("arch=%s, cpu=%p, model=%s, nfeatures=%zu",
+              virArchToString(arch), cpu, NULLSTR(cpu->model), cpu->nfeatures);
+
+    if (!(driver = cpuGetSubDriver(arch)))
+        return -1;
+
+    if (driver->expandFeatures &&
+        driver->expandFeatures(cpu) < 0)
+        return -1;
+
+    qsort(cpu->features, cpu->nfeatures, sizeof(*cpu->features),
+          virCPUFeatureCompare);
+
+    VIR_DEBUG("nfeatures=%zu", cpu->nfeatures);
+    return 0;
+}
index c4adc02f55d7945d2c3017a0cb3b06f2942490a6..905c309e6b92bb3e50ab1feaa02808ea8a917066 100644 (file)
@@ -116,6 +116,9 @@ typedef int
 typedef int
 (*virCPUArchConvertLegacy)(virCPUDefPtr cpu);
 
+typedef int
+(*virCPUArchExpandFeatures)(virCPUDefPtr cpu);
+
 struct cpuArchDriver {
     const char *name;
     const virArch *arch;
@@ -135,6 +138,7 @@ struct cpuArchDriver {
     virCPUArchGetModels getModels;
     virCPUArchTranslate translate;
     virCPUArchConvertLegacy convertLegacy;
+    virCPUArchExpandFeatures expandFeatures;
 };
 
 
@@ -247,6 +251,10 @@ virCPUConvertLegacy(virArch arch,
                     virCPUDefPtr cpu)
     ATTRIBUTE_NONNULL(2);
 
+int
+virCPUExpandFeatures(virArch arch,
+                     virCPUDefPtr cpu);
+
 /* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and
  * have no real-life usage
  */
index 9e208b0948258d82e4b24a3a23dd858048f34245..442f0ce44b121d77e1cebf4133680f4b78f01349 100644 (file)
@@ -2891,6 +2891,58 @@ virCPUx86Translate(virCPUDefPtr cpu,
 }
 
 
+static int
+virCPUx86ExpandFeatures(virCPUDefPtr cpu)
+{
+    virCPUx86MapPtr map;
+    virCPUDefPtr expanded = NULL;
+    virCPUx86ModelPtr model = NULL;
+    bool host = cpu->type == VIR_CPU_TYPE_HOST;
+    size_t i;
+    int ret = -1;
+
+    if (!(map = virCPUx86GetMap()))
+        goto cleanup;
+
+    if (!(expanded = virCPUDefCopy(cpu)))
+        goto cleanup;
+
+    virCPUDefFreeFeatures(expanded);
+
+    if (!(model = x86ModelFind(map, cpu->model))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("unknown CPU model %s"), cpu->model);
+        goto cleanup;
+    }
+
+    if (!(model = x86ModelCopy(model)) ||
+        x86DataToCPUFeatures(expanded, host ? -1 : VIR_CPU_FEATURE_REQUIRE,
+                             &model->data, map) < 0)
+        goto cleanup;
+
+    for (i = 0; i < cpu->nfeatures; i++) {
+        virCPUFeatureDefPtr f = cpu->features + i;
+
+        if (!host &&
+            f->policy != VIR_CPU_FEATURE_REQUIRE &&
+            f->policy != VIR_CPU_FEATURE_DISABLE)
+            continue;
+
+        if (virCPUDefUpdateFeature(expanded, f->name, f->policy) < 0)
+            goto cleanup;
+    }
+
+    virCPUDefFreeModel(cpu);
+
+    ret = virCPUDefCopyModel(cpu, expanded, false);
+
+ cleanup:
+    virCPUDefFree(expanded);
+    x86ModelFree(model);
+    return ret;
+}
+
+
 int
 virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
                       const virCPUx86CPUID *cpuid)
@@ -2965,4 +3017,5 @@ struct cpuArchDriver cpuDriverX86 = {
     .dataParse  = virCPUx86DataParse,
     .getModels  = virCPUx86GetModels,
     .translate  = virCPUx86Translate,
+    .expandFeatures = virCPUx86ExpandFeatures,
 };
index 1e160d80e94e114d7495a73c7124fba527c789a2..d614b38a86de46c5d45cd159bb3a9036f610ab6a 100644 (file)
@@ -1021,6 +1021,7 @@ virCPUDataFormat;
 virCPUDataFree;
 virCPUDataNew;
 virCPUDataParse;
+virCPUExpandFeatures;
 virCPUGetHost;
 virCPUGetModels;
 virCPUProbeHost;