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(a)redhat.com>
---
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 9d34206..4a5fbb1 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 5ad8112..ff48fb5 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 bdb026b..8b71ef5 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 41b674d..38f8ecb 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 14c799e..3552a31 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 1d7f6bc..8612e92 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);
--
2.10.2