cpu: Introduce virCPUConvertLegacy API

PPC driver needs to convert POWERx_v* legacy CPU model names into POWERx
to maintain backward compatibility with existing domains. This patch
adds a new step into the guest CPU configuration work flow which CPU
drivers can use to convert legacy CPU definitions.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Jiri Denemark 2016-11-09 17:09:48 +01:00
parent 509a4a40f9
commit d73422c186
6 changed files with 63 additions and 19 deletions

View File

@ -934,3 +934,38 @@ virCPUTranslate(virArch arch,
VIR_DEBUG("model=%s", NULLSTR(cpu->model)); VIR_DEBUG("model=%s", NULLSTR(cpu->model));
return 0; return 0;
} }
/**
* virCPUConvertLegacy:
*
* @arch: CPU architecture
* @cpu: CPU definition to be converted
*
* Convert legacy CPU definition into one that the corresponding cpu driver
* will be able to work with. Currently this is only implemented by the PPC
* driver, which needs to convert legacy POWERx_v* names into POWERx.
*
* Returns -1 on error, 0 on success.
*/
int
virCPUConvertLegacy(virArch arch,
virCPUDefPtr cpu)
{
struct cpuArchDriver *driver;
VIR_DEBUG("arch=%s, cpu=%p, model=%s",
virArchToString(arch), cpu, NULLSTR(cpu->model));
if (!(driver = cpuGetSubDriver(arch)))
return -1;
if (!driver->convertLegacy)
return 0;
if (driver->convertLegacy(cpu) < 0)
return -1;
VIR_DEBUG("model=%s", NULLSTR(cpu->model));
return 0;
}

View File

@ -112,6 +112,9 @@ typedef int
const char **models, const char **models,
unsigned int nmodels); unsigned int nmodels);
typedef int
(*virCPUArchConvertLegacy)(virCPUDefPtr cpu);
struct cpuArchDriver { struct cpuArchDriver {
const char *name; const char *name;
const virArch *arch; const virArch *arch;
@ -130,6 +133,7 @@ struct cpuArchDriver {
virCPUArchDataParse dataParse; virCPUArchDataParse dataParse;
virCPUArchGetModels getModels; virCPUArchGetModels getModels;
virCPUArchTranslate translate; virCPUArchTranslate translate;
virCPUArchConvertLegacy convertLegacy;
}; };
@ -229,6 +233,10 @@ virCPUTranslate(virArch arch,
unsigned int nmodels) unsigned int nmodels)
ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(2);
int
virCPUConvertLegacy(virArch arch,
virCPUDefPtr cpu)
ATTRIBUTE_NONNULL(2);
/* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and /* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and
* have no real-life usage * have no real-life usage

View File

@ -63,26 +63,18 @@ struct ppc64_map {
* POWER7_v2.3 => POWER7 * POWER7_v2.3 => POWER7
* POWER7+_v2.1 => POWER7 * POWER7+_v2.1 => POWER7
* POWER8_v1.0 => POWER8 */ * POWER8_v1.0 => POWER8 */
static virCPUDefPtr static int
ppc64ConvertLegacyCPUDef(const virCPUDef *legacy) virCPUppc64ConvertLegacy(virCPUDefPtr cpu)
{ {
virCPUDefPtr cpu; if (cpu->model &&
(STREQ(cpu->model, "POWER7_v2.1") ||
if (!(cpu = virCPUDefCopy(legacy)))
goto out;
if (!cpu->model ||
!(STREQ(cpu->model, "POWER7_v2.1") ||
STREQ(cpu->model, "POWER7_v2.3") || STREQ(cpu->model, "POWER7_v2.3") ||
STREQ(cpu->model, "POWER7+_v2.1") || STREQ(cpu->model, "POWER7+_v2.1") ||
STREQ(cpu->model, "POWER8_v1.0"))) { STREQ(cpu->model, "POWER8_v1.0"))) {
goto out; cpu->model[strlen("POWERx")] = 0;
} }
cpu->model[strlen("POWERx")] = 0; return 0;
out:
return cpu;
} }
/* Some hosts can run guests in compatibility mode, but not all /* Some hosts can run guests in compatibility mode, but not all
@ -519,7 +511,8 @@ ppc64Compute(virCPUDefPtr host,
size_t i; size_t i;
/* Ensure existing configurations are handled correctly */ /* Ensure existing configurations are handled correctly */
if (!(cpu = ppc64ConvertLegacyCPUDef(other))) if (!(cpu = virCPUDefCopy(other)) ||
virCPUppc64ConvertLegacy(cpu) < 0)
goto cleanup; goto cleanup;
if (cpu->arch != VIR_ARCH_NONE) { if (cpu->arch != VIR_ARCH_NONE) {
@ -922,4 +915,5 @@ struct cpuArchDriver cpuDriverPPC64 = {
.baseline = ppc64DriverBaseline, .baseline = ppc64DriverBaseline,
.update = virCPUppc64Update, .update = virCPUppc64Update,
.getModels = virCPUppc64DriverGetModels, .getModels = virCPUppc64DriverGetModels,
.convertLegacy = virCPUppc64ConvertLegacy,
}; };

View File

@ -983,6 +983,7 @@ cpuNodeData;
virCPUCheckFeature; virCPUCheckFeature;
virCPUCompare; virCPUCompare;
virCPUCompareXML; virCPUCompareXML;
virCPUConvertLegacy;
virCPUDataCheckFeature; virCPUDataCheckFeature;
virCPUDataFormat; virCPUDataFormat;
virCPUDataParse; virCPUDataParse;

View File

@ -5066,6 +5066,9 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def,
return -1; return -1;
} }
if (virCPUConvertLegacy(caps->host.arch, def->cpu) < 0)
return -1;
/* nothing to update for host-passthrough */ /* nothing to update for host-passthrough */
if (def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) if (def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
return 0; return 0;

View File

@ -251,6 +251,9 @@ cpuTestGuestCPU(const void *arg)
!(cpu = cpuTestLoadXML(data->arch, data->name))) !(cpu = cpuTestLoadXML(data->arch, data->name)))
goto cleanup; goto cleanup;
if (virCPUConvertLegacy(host->arch, cpu) < 0)
goto cleanup;
cmpResult = virCPUCompare(host->arch, host, cpu, false); cmpResult = virCPUCompare(host->arch, host, cpu, false);
if (cmpResult == VIR_CPU_COMPARE_ERROR || if (cmpResult == VIR_CPU_COMPARE_ERROR ||
cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE) { cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE) {
@ -794,7 +797,7 @@ mymain(void)
DO_TEST_GUESTCPU("ppc64", "host", "guest", ppc_models, 0); DO_TEST_GUESTCPU("ppc64", "host", "guest", ppc_models, 0);
DO_TEST_GUESTCPU("ppc64", "host", "guest-nofallback", ppc_models, -1); DO_TEST_GUESTCPU("ppc64", "host", "guest-nofallback", ppc_models, -1);
DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy", ppc_models, /*0*/ -1); DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy", ppc_models, 0);
DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy-incompatible", ppc_models, -1); DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy-incompatible", ppc_models, -1);
DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy-invalid", ppc_models, -1); DO_TEST_GUESTCPU("ppc64", "host", "guest-legacy-invalid", ppc_models, -1);