mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
While the check is appropriate for eg. the x86 and generic drivers, there are some valid ppc64 guest configurations where the CPU model is supposed to be NULL. Moving this check from the generic code to the drivers makes it possible to accomodate both use cases. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1251927
227 lines
6.0 KiB
C
227 lines
6.0 KiB
C
/*
|
|
* cpu_generic.c: CPU manipulation driver for architectures which are not
|
|
* handled by their own driver
|
|
*
|
|
* Copyright (C) 2009-2011 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors:
|
|
* Jiri Denemark <jdenemar@redhat.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "viralloc.h"
|
|
#include "virhash.h"
|
|
#include "cpu.h"
|
|
#include "cpu_generic.h"
|
|
#include "virstring.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
|
|
|
static virHashTablePtr
|
|
genericHashFeatures(virCPUDefPtr cpu)
|
|
{
|
|
virHashTablePtr hash;
|
|
size_t i;
|
|
|
|
if ((hash = virHashCreate(cpu->nfeatures, NULL)) == NULL)
|
|
return NULL;
|
|
|
|
for (i = 0; i < cpu->nfeatures; i++) {
|
|
if (virHashAddEntry(hash,
|
|
cpu->features[i].name,
|
|
cpu->features + i)) {
|
|
virHashFree(hash);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
|
|
static virCPUCompareResult
|
|
genericCompare(virCPUDefPtr host,
|
|
virCPUDefPtr cpu,
|
|
bool failIncompatible)
|
|
{
|
|
virHashTablePtr hash = NULL;
|
|
virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR;
|
|
size_t i;
|
|
unsigned int reqfeatures;
|
|
|
|
if (!cpu->model) {
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
_("no guest CPU model specified"));
|
|
goto cleanup;
|
|
}
|
|
|
|
if ((cpu->arch != VIR_ARCH_NONE &&
|
|
host->arch != cpu->arch) ||
|
|
STRNEQ(host->model, cpu->model)) {
|
|
ret = VIR_CPU_COMPARE_INCOMPATIBLE;
|
|
goto cleanup;
|
|
}
|
|
|
|
if ((hash = genericHashFeatures(host)) == NULL)
|
|
goto cleanup;
|
|
|
|
reqfeatures = 0;
|
|
for (i = 0; i < cpu->nfeatures; i++) {
|
|
void *hval = virHashLookup(hash, cpu->features[i].name);
|
|
|
|
if (hval) {
|
|
if (cpu->type == VIR_CPU_TYPE_GUEST &&
|
|
cpu->features[i].policy == VIR_CPU_FEATURE_FORBID) {
|
|
ret = VIR_CPU_COMPARE_INCOMPATIBLE;
|
|
goto cleanup;
|
|
}
|
|
reqfeatures++;
|
|
} else if (cpu->type == VIR_CPU_TYPE_HOST ||
|
|
cpu->features[i].policy == VIR_CPU_FEATURE_REQUIRE) {
|
|
ret = VIR_CPU_COMPARE_INCOMPATIBLE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if (host->nfeatures > reqfeatures) {
|
|
if (cpu->type == VIR_CPU_TYPE_GUEST &&
|
|
cpu->match == VIR_CPU_MATCH_STRICT)
|
|
ret = VIR_CPU_COMPARE_INCOMPATIBLE;
|
|
else
|
|
ret = VIR_CPU_COMPARE_SUPERSET;
|
|
} else {
|
|
ret = VIR_CPU_COMPARE_IDENTICAL;
|
|
}
|
|
|
|
cleanup:
|
|
virHashFree(hash);
|
|
if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) {
|
|
ret = VIR_CPU_COMPARE_ERROR;
|
|
virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
static virCPUDefPtr
|
|
genericBaseline(virCPUDefPtr *cpus,
|
|
unsigned int ncpus,
|
|
const char **models,
|
|
unsigned int nmodels,
|
|
unsigned int flags)
|
|
{
|
|
virCPUDefPtr cpu = NULL;
|
|
virCPUFeatureDefPtr features = NULL;
|
|
unsigned int nfeatures;
|
|
unsigned int count;
|
|
size_t i, j;
|
|
|
|
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
|
|
VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
|
|
|
|
if (!cpuModelIsAllowed(cpus[0]->model, models, nmodels)) {
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
_("CPU model %s is not supported by hypervisor"),
|
|
cpus[0]->model);
|
|
goto error;
|
|
}
|
|
|
|
if (VIR_ALLOC(cpu) < 0 ||
|
|
VIR_STRDUP(cpu->model, cpus[0]->model) < 0 ||
|
|
VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0)
|
|
goto error;
|
|
|
|
cpu->arch = cpus[0]->arch;
|
|
cpu->type = VIR_CPU_TYPE_HOST;
|
|
|
|
count = nfeatures = cpus[0]->nfeatures;
|
|
for (i = 0; i < nfeatures; i++)
|
|
features[i].name = cpus[0]->features[i].name;
|
|
|
|
for (i = 1; i < ncpus; i++) {
|
|
virHashTablePtr hash;
|
|
|
|
if (cpu->arch != cpus[i]->arch) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
_("CPUs have incompatible architectures: '%s' != '%s'"),
|
|
virArchToString(cpu->arch),
|
|
virArchToString(cpus[i]->arch));
|
|
goto error;
|
|
}
|
|
|
|
if (STRNEQ(cpu->model, cpus[i]->model)) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
_("CPU models don't match: '%s' != '%s'"),
|
|
cpu->model, cpus[i]->model);
|
|
goto error;
|
|
}
|
|
|
|
if (!(hash = genericHashFeatures(cpus[i])))
|
|
goto error;
|
|
|
|
for (j = 0; j < nfeatures; j++) {
|
|
if (features[j].name &&
|
|
!virHashLookup(hash, features[j].name)) {
|
|
features[j].name = NULL;
|
|
count--;
|
|
}
|
|
}
|
|
|
|
virHashFree(hash);
|
|
}
|
|
|
|
if (VIR_ALLOC_N(cpu->features, count) < 0)
|
|
goto error;
|
|
cpu->nfeatures = count;
|
|
|
|
j = 0;
|
|
for (i = 0; i < nfeatures; i++) {
|
|
if (!features[i].name)
|
|
continue;
|
|
|
|
if (VIR_STRDUP(cpu->features[j++].name, features[i].name) < 0)
|
|
goto error;
|
|
}
|
|
|
|
cleanup:
|
|
VIR_FREE(features);
|
|
|
|
return cpu;
|
|
|
|
error:
|
|
virCPUDefFree(cpu);
|
|
cpu = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
struct cpuArchDriver cpuDriverGeneric = {
|
|
.name = "generic",
|
|
.arch = NULL,
|
|
.narch = 0,
|
|
.compare = genericCompare,
|
|
.decode = NULL,
|
|
.encode = NULL,
|
|
.free = NULL,
|
|
.nodeData = NULL,
|
|
.guestData = NULL,
|
|
.baseline = genericBaseline,
|
|
.update = NULL,
|
|
};
|