From d73422c1867b938b9fd9411ad68b840e7264b5a1 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 9 Nov 2016 17:09:48 +0100 Subject: [PATCH] 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 --- src/cpu/cpu.c | 35 +++++++++++++++++++++++++++++++++++ src/cpu/cpu.h | 8 ++++++++ src/cpu/cpu_ppc64.c | 30 ++++++++++++------------------ src/libvirt_private.syms | 1 + src/qemu/qemu_process.c | 3 +++ tests/cputest.c | 5 ++++- 6 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 9d34206bf5..4a5fbb1fde 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -934,3 +934,38 @@ virCPUTranslate(virArch arch, VIR_DEBUG("model=%s", NULLSTR(cpu->model)); 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; +} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 5ad811270e..ff48fb5ca2 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -112,6 +112,9 @@ typedef int const char **models, unsigned int nmodels); +typedef int +(*virCPUArchConvertLegacy)(virCPUDefPtr cpu); + struct cpuArchDriver { const char *name; const virArch *arch; @@ -130,6 +133,7 @@ struct cpuArchDriver { virCPUArchDataParse dataParse; virCPUArchGetModels getModels; virCPUArchTranslate translate; + virCPUArchConvertLegacy convertLegacy; }; @@ -229,6 +233,10 @@ virCPUTranslate(virArch arch, unsigned int nmodels) ATTRIBUTE_NONNULL(2); +int +virCPUConvertLegacy(virArch arch, + virCPUDefPtr cpu) + ATTRIBUTE_NONNULL(2); /* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and * have no real-life usage diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index bdb026b2c2..8b71ef55f2 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -63,26 +63,18 @@ struct ppc64_map { * POWER7_v2.3 => POWER7 * POWER7+_v2.1 => POWER7 * POWER8_v1.0 => POWER8 */ -static virCPUDefPtr -ppc64ConvertLegacyCPUDef(const virCPUDef *legacy) +static int +virCPUppc64ConvertLegacy(virCPUDefPtr cpu) { - virCPUDefPtr cpu; - - 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.1") || - STREQ(cpu->model, "POWER8_v1.0"))) { - goto out; + if (cpu->model && + (STREQ(cpu->model, "POWER7_v2.1") || + STREQ(cpu->model, "POWER7_v2.3") || + STREQ(cpu->model, "POWER7+_v2.1") || + STREQ(cpu->model, "POWER8_v1.0"))) { + cpu->model[strlen("POWERx")] = 0; } - cpu->model[strlen("POWERx")] = 0; - - out: - return cpu; + return 0; } /* Some hosts can run guests in compatibility mode, but not all @@ -519,7 +511,8 @@ ppc64Compute(virCPUDefPtr host, size_t i; /* Ensure existing configurations are handled correctly */ - if (!(cpu = ppc64ConvertLegacyCPUDef(other))) + if (!(cpu = virCPUDefCopy(other)) || + virCPUppc64ConvertLegacy(cpu) < 0) goto cleanup; if (cpu->arch != VIR_ARCH_NONE) { @@ -922,4 +915,5 @@ struct cpuArchDriver cpuDriverPPC64 = { .baseline = ppc64DriverBaseline, .update = virCPUppc64Update, .getModels = virCPUppc64DriverGetModels, + .convertLegacy = virCPUppc64ConvertLegacy, }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 41b674d6e5..38f8ecb631 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -983,6 +983,7 @@ cpuNodeData; virCPUCheckFeature; virCPUCompare; virCPUCompareXML; +virCPUConvertLegacy; virCPUDataCheckFeature; virCPUDataFormat; virCPUDataParse; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 14c799e46f..3552a3130e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5066,6 +5066,9 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, return -1; } + if (virCPUConvertLegacy(caps->host.arch, def->cpu) < 0) + return -1; + /* nothing to update for host-passthrough */ if (def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0; diff --git a/tests/cputest.c b/tests/cputest.c index 1d7f6bc562..8612e920ee 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -251,6 +251,9 @@ cpuTestGuestCPU(const void *arg) !(cpu = cpuTestLoadXML(data->arch, data->name))) goto cleanup; + if (virCPUConvertLegacy(host->arch, cpu) < 0) + goto cleanup; + cmpResult = virCPUCompare(host->arch, host, cpu, false); if (cmpResult == VIR_CPU_COMPARE_ERROR || 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-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-invalid", ppc_models, -1);