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;
+}
typedef int
(*virCPUArchConvertLegacy)(virCPUDefPtr cpu);
+typedef int
+(*virCPUArchExpandFeatures)(virCPUDefPtr cpu);
+
struct cpuArchDriver {
const char *name;
const virArch *arch;
virCPUArchGetModels getModels;
virCPUArchTranslate translate;
virCPUArchConvertLegacy convertLegacy;
+ virCPUArchExpandFeatures expandFeatures;
};
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
*/
}
+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)
.dataParse = virCPUx86DataParse,
.getModels = virCPUx86GetModels,
.translate = virCPUx86Translate,
+ .expandFeatures = virCPUx86ExpandFeatures,
};
virCPUDataFree;
virCPUDataNew;
virCPUDataParse;
+virCPUExpandFeatures;
virCPUGetHost;
virCPUGetModels;
virCPUProbeHost;