}
+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)
{
}
-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 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);
if (preferred && STREQ(cpuCandidate->model, preferred)) {
virCPUDefFree(cpuModel);
cpuModel = cpuCandidate;
+ cpuData = candidate->data;
break;
}
|| cpuModel->nfeatures > cpuCandidate->nfeatures) {
virCPUDefFree(cpuModel);
cpuModel = cpuCandidate;
- } else
+ cpuData = candidate->data;
+ } else {
virCPUDefFree(cpuCandidate);
+ }
next:
candidate = candidate->next;
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;
out:
virCPUDefFree(cpuModel);
-
+ virCPUx86DataFree(copy);
+ virCPUx86DataFree(features);
return ret;
}