cpu: Introduce virCPUTranslate

The API is supposed to make sure the provided CPU definition does not
use a CPU model which is not supported by the hypervisor (if at all
possible, of course).

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Jiri Denemark 2016-06-17 09:45:48 +02:00
parent 0b119e2b19
commit 6b159239cc
4 changed files with 125 additions and 0 deletions

View File

@ -809,3 +809,62 @@ cpuGetModels(virArch arch, char ***models)
return driver->getModels(models); return driver->getModels(models);
} }
/**
* virCPUTranslate:
*
* @arch: CPU architecture
* @cpu: CPU definition to be translated
* @models: NULL-terminated list of allowed CPU models (NULL if all are allowed)
* @nmodels: number of CPU models in @models
*
* Translates @cpu model (if allowed by @cpu->fallback) to a closest CPU model
* from @models list.
*
* The function does nothing (and returns 0) if @cpu does not have to be
* translated.
*
* Returns -1 on error, 0 on success.
*/
int
virCPUTranslate(virArch arch,
virCPUDefPtr cpu,
char **models,
unsigned int nmodels)
{
struct cpuArchDriver *driver;
VIR_DEBUG("arch=%s, cpu=%p, model=%s, models=%p, nmodels=%u",
virArchToString(arch), cpu, NULLSTR(cpu->model), models, nmodels);
if (!(driver = cpuGetSubDriver(arch)))
return -1;
if (cpu->mode == VIR_CPU_MODE_HOST_MODEL ||
cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
return 0;
if (cpuModelIsAllowed(cpu->model, (const char **) models, nmodels))
return 0;
if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("CPU model %s is not supported by hypervisor"),
cpu->model);
return -1;
}
if (!driver->translate) {
virReportError(VIR_ERR_NO_SUPPORT,
_("cannot translate CPU model %s to a supported model"),
cpu->model);
return -1;
}
if (driver->translate(cpu, (const char **) models, nmodels) < 0)
return -1;
VIR_DEBUG("model=%s", NULLSTR(cpu->model));
return 0;
}

View File

@ -103,6 +103,11 @@ typedef virCPUDataPtr
typedef int typedef int
(*cpuArchGetModels) (char ***models); (*cpuArchGetModels) (char ***models);
typedef int
(*virCPUArchTranslate)(virCPUDefPtr cpu,
const char **models,
unsigned int nmodels);
struct cpuArchDriver { struct cpuArchDriver {
const char *name; const char *name;
const virArch *arch; const virArch *arch;
@ -119,6 +124,7 @@ struct cpuArchDriver {
cpuArchDataFormat dataFormat; cpuArchDataFormat dataFormat;
cpuArchDataParse dataParse; cpuArchDataParse dataParse;
cpuArchGetModels getModels; cpuArchGetModels getModels;
virCPUArchTranslate translate;
}; };
@ -202,6 +208,14 @@ cpuModelIsAllowed(const char *model,
int int
cpuGetModels(virArch arch, char ***models); cpuGetModels(virArch arch, char ***models);
int
virCPUTranslate(virArch arch,
virCPUDefPtr cpu,
char **models,
unsigned int nmodels)
ATTRIBUTE_NONNULL(2);
/* cpuDataFormat and cpuDataParse are implemented for unit tests only and /* cpuDataFormat and cpuDataParse are implemented for unit tests only and
* have no real-life usage * have no real-life usage
*/ */

View File

@ -2643,6 +2643,56 @@ x86GetModels(char ***models)
} }
static int
virCPUx86Translate(virCPUDefPtr cpu,
const char **models,
unsigned int nmodels)
{
virCPUDefPtr translated = NULL;
virCPUx86MapPtr map;
virCPUx86ModelPtr model = NULL;
size_t i;
int ret = -1;
if (!(map = virCPUx86GetMap()))
goto cleanup;
if (!(model = x86ModelFromCPU(cpu, map, -1)))
goto cleanup;
if (model->vendor &&
virCPUx86DataAddCPUID(&model->data, &model->vendor->cpuid) < 0)
goto cleanup;
if (x86DataAddSignature(&model->data, model->signature) < 0)
goto cleanup;
if (!(translated = virCPUDefCopyWithoutModel(cpu)))
goto cleanup;
if (VIR_STRDUP(translated->vendor, cpu->vendor) < 0 ||
VIR_STRDUP(translated->vendor_id, cpu->vendor_id) < 0)
goto cleanup;
if (x86Decode(translated, &model->data, models, nmodels, NULL, 0) < 0)
goto cleanup;
for (i = 0; i < cpu->nfeatures; i++) {
virCPUFeatureDefPtr f = cpu->features + i;
if (virCPUDefUpdateFeature(translated, f->name, f->policy) < 0)
goto cleanup;
}
virCPUDefStealModel(cpu, translated);
ret = 0;
cleanup:
virCPUDefFree(translated);
x86ModelFree(model);
return ret;
}
struct cpuArchDriver cpuDriverX86 = { struct cpuArchDriver cpuDriverX86 = {
.name = "x86", .name = "x86",
.arch = archs, .arch = archs,
@ -2663,4 +2713,5 @@ struct cpuArchDriver cpuDriverX86 = {
.dataFormat = x86CPUDataFormat, .dataFormat = x86CPUDataFormat,
.dataParse = x86CPUDataParse, .dataParse = x86CPUDataParse,
.getModels = x86GetModels, .getModels = x86GetModels,
.translate = virCPUx86Translate,
}; };

View File

@ -981,6 +981,7 @@ cpuGetModels;
cpuGuestData; cpuGuestData;
cpuHasFeature; cpuHasFeature;
cpuNodeData; cpuNodeData;
virCPUTranslate;
virCPUUpdate; virCPUUpdate;