]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
cpu: Introduce virCPUTranslate
authorJiri Denemark <jdenemar@redhat.com>
Fri, 17 Jun 2016 07:45:48 +0000 (09:45 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 22 Sep 2016 13:40:09 +0000 (15:40 +0200)
The API is supposed to make sure the provided CPU definition does not
use a CPU model which is not supported by the hypervisor (if at all
possible, of course).

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 e6f6335ff5ab6b0fc54f9c75515b8723d68a21e3..748b6f92a56cd865139e766b006015859474d4a0 100644 (file)
@@ -809,3 +809,62 @@ cpuGetModels(virArch arch, char ***models)
 
     return driver->getModels(models);
 }
+
+
+/**
+ * virCPUTranslate:
+ *
+ * @arch: CPU architecture
+ * @cpu: CPU definition to be translated
+ * @models: NULL-terminated list of allowed CPU models (NULL if all are allowed)
+ * @nmodels: number of CPU models in @models
+ *
+ * Translates @cpu model (if allowed by @cpu->fallback) to a closest CPU model
+ * from @models list.
+ *
+ * The function does nothing (and returns 0) if @cpu does not have to be
+ * translated.
+ *
+ * Returns -1 on error, 0 on success.
+ */
+int
+virCPUTranslate(virArch arch,
+                virCPUDefPtr cpu,
+                char **models,
+                unsigned int nmodels)
+{
+    struct cpuArchDriver *driver;
+
+    VIR_DEBUG("arch=%s, cpu=%p, model=%s, models=%p, nmodels=%u",
+              virArchToString(arch), cpu, NULLSTR(cpu->model), models, nmodels);
+
+    if (!(driver = cpuGetSubDriver(arch)))
+        return -1;
+
+    if (cpu->mode == VIR_CPU_MODE_HOST_MODEL ||
+        cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
+        return 0;
+
+    if (cpuModelIsAllowed(cpu->model, (const char **) models, nmodels))
+        return 0;
+
+    if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("CPU model %s is not supported by hypervisor"),
+                       cpu->model);
+        return -1;
+    }
+
+    if (!driver->translate) {
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("cannot translate CPU model %s to a supported model"),
+                       cpu->model);
+        return -1;
+    }
+
+    if (driver->translate(cpu, (const char **) models, nmodels) < 0)
+        return -1;
+
+    VIR_DEBUG("model=%s", NULLSTR(cpu->model));
+    return 0;
+}
index dac76881267000b3abed9d7647bca631676f8d18..6a21bfa53fd985a322e2e1b79a8caf9e2277dec5 100644 (file)
@@ -103,6 +103,11 @@ typedef virCPUDataPtr
 typedef int
 (*cpuArchGetModels) (char ***models);
 
+typedef int
+(*virCPUArchTranslate)(virCPUDefPtr cpu,
+                       const char **models,
+                       unsigned int nmodels);
+
 struct cpuArchDriver {
     const char *name;
     const virArch *arch;
@@ -119,6 +124,7 @@ struct cpuArchDriver {
     cpuArchDataFormat   dataFormat;
     cpuArchDataParse    dataParse;
     cpuArchGetModels    getModels;
+    virCPUArchTranslate translate;
 };
 
 
@@ -202,6 +208,14 @@ cpuModelIsAllowed(const char *model,
 int
 cpuGetModels(virArch arch, char ***models);
 
+int
+virCPUTranslate(virArch arch,
+                virCPUDefPtr cpu,
+                char **models,
+                unsigned int nmodels)
+    ATTRIBUTE_NONNULL(2);
+
+
 /* cpuDataFormat and cpuDataParse are implemented for unit tests only and
  * have no real-life usage
  */
index f424f7205f68e17730d9e6e702b0babae37b3e2f..a45427ad80347cfa3ea3f7db8e6f4beacc42925f 100644 (file)
@@ -2643,6 +2643,56 @@ x86GetModels(char ***models)
 }
 
 
+static int
+virCPUx86Translate(virCPUDefPtr cpu,
+                   const char **models,
+                   unsigned int nmodels)
+{
+    virCPUDefPtr translated = NULL;
+    virCPUx86MapPtr map;
+    virCPUx86ModelPtr model = NULL;
+    size_t i;
+    int ret = -1;
+
+    if (!(map = virCPUx86GetMap()))
+        goto cleanup;
+
+    if (!(model = x86ModelFromCPU(cpu, map, -1)))
+        goto cleanup;
+
+    if (model->vendor &&
+        virCPUx86DataAddCPUID(&model->data, &model->vendor->cpuid) < 0)
+        goto cleanup;
+
+    if (x86DataAddSignature(&model->data, model->signature) < 0)
+        goto cleanup;
+
+    if (!(translated = virCPUDefCopyWithoutModel(cpu)))
+        goto cleanup;
+
+    if (VIR_STRDUP(translated->vendor, cpu->vendor) < 0 ||
+        VIR_STRDUP(translated->vendor_id, cpu->vendor_id) < 0)
+        goto cleanup;
+
+    if (x86Decode(translated, &model->data, models, nmodels, NULL, 0) < 0)
+        goto cleanup;
+
+    for (i = 0; i < cpu->nfeatures; i++) {
+        virCPUFeatureDefPtr f = cpu->features + i;
+        if (virCPUDefUpdateFeature(translated, f->name, f->policy) < 0)
+            goto cleanup;
+    }
+
+    virCPUDefStealModel(cpu, translated);
+    ret = 0;
+
+ cleanup:
+    virCPUDefFree(translated);
+    x86ModelFree(model);
+    return ret;
+}
+
+
 struct cpuArchDriver cpuDriverX86 = {
     .name = "x86",
     .arch = archs,
@@ -2663,4 +2713,5 @@ struct cpuArchDriver cpuDriverX86 = {
     .dataFormat = x86CPUDataFormat,
     .dataParse  = x86CPUDataParse,
     .getModels  = x86GetModels,
+    .translate  = virCPUx86Translate,
 };
index 6dfab8284a2faa63da583cc322f7bb70ad70a8df..09fd024c222dc8ad17a6029f098111395de696c9 100644 (file)
@@ -981,6 +981,7 @@ cpuGetModels;
 cpuGuestData;
 cpuHasFeature;
 cpuNodeData;
+virCPUTranslate;
 virCPUUpdate;