}
+static virCPUDefPtr
+x86DataToCPU(const union cpuData *data,
+ const struct x86_model *model,
+ const struct x86_map *map)
+{
+ virCPUDefPtr cpu;
+ union cpuData *tmp = NULL;
+ struct cpuX86cpuid *cpuid;
+ const struct x86_feature *feature;
+ int i;
+
+ if (VIR_ALLOC(cpu) < 0 ||
+ (cpu->model = strdup(model->name)) == NULL ||
+ (tmp = x86DataCopy(data)) == NULL)
+ goto no_memory;
+
+ for (i = 0; i < model->ncpuid; i++) {
+ x86cpuidClearBits(x86DataCpuid(tmp, model->cpuid[i].function),
+ model->cpuid + i);
+ }
+
+ feature = map->features;
+ while (feature != NULL) {
+ for (i = 0; i < feature->ncpuid; i++) {
+ if ((cpuid = x86DataCpuid(tmp, feature->cpuid[i].function))
+ && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
+ x86cpuidClearBits(cpuid, feature->cpuid + i);
+ if (virCPUDefAddFeature(NULL, cpu, feature->name,
+ VIR_CPU_FEATURE_REQUIRE) < 0)
+ goto error;
+ }
+ }
+
+ feature = feature->next;
+ }
+
+cleanup:
+ x86DataFree(tmp);
+ return cpu;
+
+no_memory:
+ virReportOOMError(NULL);
+error:
+ virCPUDefFree(cpu);
+ cpu = NULL;
+ goto cleanup;
+}
+
+
static void
x86FeatureFree(struct x86_feature *feature)
{
{
int ret = -1;
struct x86_map *map;
- const struct x86_feature *feature;
- const struct x86_model *model = NULL;
const struct x86_model *candidate;
- union cpuData *tmp = NULL;
+ virCPUDefPtr cpuCandidate;
+ virCPUDefPtr cpuModel = NULL;
struct cpuX86cpuid *cpuid;
int i;
candidate = map->models;
while (candidate != NULL) {
+ bool allowed = (models == NULL);
+
for (i = 0; i < candidate->ncpuid; i++) {
cpuid = x86DataCpuid(data, candidate->cpuid[i].function);
if (cpuid == NULL
goto next;
}
- if (model == NULL
- || x86ModelCompare(model, candidate) == SUBSET) {
- bool found = false;
- for (i = 0; i < nmodels; i++) {
- if (STREQ(models[i], candidate->name)) {
- found = true;
- break;
- }
+ for (i = 0; i < nmodels; i++) {
+ if (STREQ(models[i], candidate->name)) {
+ allowed = true;
+ break;
}
+ }
- if (nmodels > 0 && !found) {
- VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring",
- candidate->name);
- }
- else
- model = candidate;
+ if (!allowed) {
+ VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring",
+ candidate->name);
+ goto next;
}
+ if (!(cpuCandidate = x86DataToCPU(data, candidate, map)))
+ goto out;
+
+ if (cpuModel == NULL
+ || cpuModel->nfeatures > cpuCandidate->nfeatures) {
+ virCPUDefFree(cpuModel);
+ cpuModel = cpuCandidate;
+ } else
+ virCPUDefFree(cpuCandidate);
+
next:
candidate = candidate->next;
}
- if (model == NULL) {
+ if (cpuModel == NULL) {
virCPUReportError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Cannot find suitable CPU model for given data"));
goto out;
}
- if ((cpu->model = strdup(model->name)) == NULL
- || (tmp = x86DataCopy(data)) == NULL) {
- virReportOOMError(NULL);
- goto out;
- }
-
- for (i = 0; i < model->ncpuid; i++) {
- x86cpuidClearBits(x86DataCpuid(tmp, model->cpuid[i].function),
- model->cpuid + i);
- }
-
- feature = map->features;
- while (feature != NULL) {
- for (i = 0; i < feature->ncpuid; i++) {
- if ((cpuid = x86DataCpuid(tmp, feature->cpuid[i].function))
- && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
- x86cpuidClearBits(cpuid, feature->cpuid + i);
- if (virCPUDefAddFeature(NULL, cpu, feature->name,
- VIR_CPU_FEATURE_REQUIRE) < 0)
- goto out;
- }
- }
-
- feature = feature->next;
- }
+ cpu->model = cpuModel->model;
+ cpu->nfeatures = cpuModel->nfeatures;
+ cpu->features = cpuModel->features;
+ VIR_FREE(cpuModel);
ret = 0;
out:
- x86DataFree(tmp);
x86MapFree(map);
+ virCPUDefFree(cpuModel);
return ret;
}