mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 22:25:25 +00:00
cpu: Fix VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
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.
This commit is contained in:
parent
0e9373a5c0
commit
802f157e8c
@ -730,6 +730,36 @@ ignore:
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1447,35 +1477,6 @@ x86GuestData(virCPUDefPtr host,
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
@ -1489,6 +1490,9 @@ x86Decode(virCPUDefPtr cpu,
|
||||
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);
|
||||
@ -1545,6 +1549,7 @@ x86Decode(virCPUDefPtr cpu,
|
||||
if (preferred && STREQ(cpuCandidate->model, preferred)) {
|
||||
virCPUDefFree(cpuModel);
|
||||
cpuModel = cpuCandidate;
|
||||
cpuData = candidate->data;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1552,8 +1557,10 @@ x86Decode(virCPUDefPtr cpu,
|
||||
|| cpuModel->nfeatures > cpuCandidate->nfeatures) {
|
||||
virCPUDefFree(cpuModel);
|
||||
cpuModel = cpuCandidate;
|
||||
} else
|
||||
cpuData = candidate->data;
|
||||
} else {
|
||||
virCPUDefFree(cpuCandidate);
|
||||
}
|
||||
|
||||
next:
|
||||
candidate = candidate->next;
|
||||
@ -1565,9 +1572,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;
|
||||
@ -1578,7 +1593,8 @@ x86Decode(virCPUDefPtr cpu,
|
||||
|
||||
out:
|
||||
virCPUDefFree(cpuModel);
|
||||
|
||||
virCPUx86DataFree(copy);
|
||||
virCPUx86DataFree(features);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user