virCPUUpdate check the CPU definition for features that were marked as
removed in the specified CPU model and explicitly adds those that were
not mentioned in the definition. So far such features were added with
VIR_CPU_FEATURE_DISABLE policy, but the caller may want to use a
different policy in some situations, which is now possible via the
removedPolicy parameter.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/cpu/cpu.c | 10 +++++++---
src/cpu/cpu.h | 6 ++++--
src/cpu/cpu_arm.c | 3 ++-
src/cpu/cpu_loongarch.c | 3 ++-
src/cpu/cpu_ppc64.c | 3 ++-
src/cpu/cpu_riscv64.c | 3 ++-
src/cpu/cpu_s390.c | 3 ++-
src/cpu/cpu_x86.c | 31 ++++++++++++++++++++-----------
src/qemu/qemu_domain.c | 3 ++-
src/qemu/qemu_process.c | 6 ++++--
tests/cputest.c | 4 ++--
11 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 33701811fb..a2518d7cc7 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -560,19 +560,23 @@ virCPUBaseline(virArch arch,
* @arch: CPU architecture
* @guest: guest CPU definition to be updated
* @host: host CPU definition
+ * @removedPolicy: default policy for features removed from the CPU model
*
* Updates @guest CPU definition possibly taking @host CPU into account. This
* is required for maintaining compatibility with older libvirt releases or to
* support guest CPU definitions specified relatively to host CPU, such as CPUs
* with VIR_CPU_MODE_CUSTOM and optional features or VIR_CPU_MATCH_MINIMUM, or
- * CPUs with VIR_CPU_MODE_HOST_MODEL.
+ * CPUs with VIR_CPU_MODE_HOST_MODEL. If @guest CPU uses a CPU model which
+ * specifies some features as removed, such features that were not already
+ * present in the @guest CPU definition will be added there with @removedPolicy.
*
* Returns 0 on success, -1 on error.
*/
int
virCPUUpdate(virArch arch,
virCPUDef *guest,
- const virCPUDef *host)
+ const virCPUDef *host,
+ virCPUFeaturePolicy removedPolicy)
{
struct cpuArchDriver *driver;
bool relative;
@@ -622,7 +626,7 @@ virCPUUpdate(virArch arch,
return -1;
}
- if (driver->update(guest, host, relative) < 0)
+ if (driver->update(guest, host, relative, removedPolicy) < 0)
return -1;
VIR_DEBUG("model=%s", NULLSTR(guest->model));
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index a4cdb37f03..d092b4f3f0 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -81,7 +81,8 @@ typedef virCPUDef *
typedef int
(*virCPUArchUpdate)(virCPUDef *guest,
const virCPUDef *host,
- bool relative);
+ bool relative,
+ virCPUFeaturePolicy removedPolicy);
typedef int
(*virCPUArchUpdateLive)(virCPUDef *cpu,
@@ -229,7 +230,8 @@ virCPUBaseline(virArch arch,
int
virCPUUpdate(virArch arch,
virCPUDef *guest,
- const virCPUDef *host)
+ const virCPUDef *host,
+ virCPUFeaturePolicy removedPolicy)
ATTRIBUTE_NONNULL(2);
int
diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 324c701e81..7a9c8163c8 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -448,7 +448,8 @@ virCPUarmGetMap(void)
static int
virCPUarmUpdate(virCPUDef *guest,
const virCPUDef *host,
- bool relative)
+ bool relative,
+ virCPUFeaturePolicy removedPolicy G_GNUC_UNUSED)
{
g_autoptr(virCPUDef) updated = virCPUDefCopyWithoutModel(guest);
diff --git a/src/cpu/cpu_loongarch.c b/src/cpu/cpu_loongarch.c
index 78d9941320..0e2b0b5848 100644
--- a/src/cpu/cpu_loongarch.c
+++ b/src/cpu/cpu_loongarch.c
@@ -39,7 +39,8 @@ virCPULoongArchCompare(virCPUDef *host G_GNUC_UNUSED,
static int
virCPULoongArchUpdate(virCPUDef *guest G_GNUC_UNUSED,
const virCPUDef *host G_GNUC_UNUSED,
- bool relative G_GNUC_UNUSED)
+ bool relative G_GNUC_UNUSED,
+ virCPUFeaturePolicy removedPolicy G_GNUC_UNUSED)
{
return 0;
}
diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
index 448a0a7d85..13f5fc9c2c 100644
--- a/src/cpu/cpu_ppc64.c
+++ b/src/cpu/cpu_ppc64.c
@@ -654,7 +654,8 @@ virCPUppc64GetHost(virCPUDef *cpu,
static int
virCPUppc64Update(virCPUDef *guest,
const virCPUDef *host G_GNUC_UNUSED,
- bool relative G_GNUC_UNUSED)
+ bool relative G_GNUC_UNUSED,
+ virCPUFeaturePolicy removedPolicy G_GNUC_UNUSED)
{
/*
* - host-passthrough doesn't even get here
diff --git a/src/cpu/cpu_riscv64.c b/src/cpu/cpu_riscv64.c
index 4cb795f849..276c80a401 100644
--- a/src/cpu/cpu_riscv64.c
+++ b/src/cpu/cpu_riscv64.c
@@ -49,7 +49,8 @@ virCPURiscv64ValidateFeatures(virCPUDef *cpu G_GNUC_UNUSED)
static int
virCPURiscv64Update(virCPUDef *guest,
const virCPUDef *host,
- bool relative)
+ bool relative,
+ virCPUFeaturePolicy removedPolicy G_GNUC_UNUSED)
{
g_autoptr(virCPUDef) updated = virCPUDefCopyWithoutModel(guest);
diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c
index 13695ee97a..bcfe3fc07a 100644
--- a/src/cpu/cpu_s390.c
+++ b/src/cpu/cpu_s390.c
@@ -42,7 +42,8 @@ virCPUs390Compare(virCPUDef *host G_GNUC_UNUSED,
static int
virCPUs390Update(virCPUDef *guest,
const virCPUDef *host,
- bool relative)
+ bool relative,
+ virCPUFeaturePolicy removedPolicy G_GNUC_UNUSED)
{
g_autoptr(virCPUDef) updated = virCPUDefCopyWithoutModel(guest);
size_t i;
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 8770f52d15..7a70eed9e7 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -829,6 +829,22 @@ x86DataAddSignature(virCPUx86Data *data,
}
+/*
+ * Adds features removed from the CPU @model to @cpu with a specified @policy
+ * unless the features were already explicitly mentioned in @cpu.
+ */
+static void
+virCPUx86AddRemovedFeatures(virCPUDef *cpu,
+ virCPUx86Model *model,
+ virCPUFeaturePolicy policy)
+{
+ char **feat;
+
+ for (feat = model->removedFeatures; feat && *feat; feat++)
+ virCPUDefAddFeatureIfMissing(cpu, *feat, policy);
+}
+
+
/*
* Disables features removed from the CPU @model unless they are already
* mentioned in @cpu to make sure these features will always be explicitly
@@ -838,15 +854,7 @@ static void
virCPUx86DisableRemovedFeatures(virCPUDef *cpu,
virCPUx86Model *model)
{
- char **feat = model->removedFeatures;
-
- if (!feat)
- return;
-
- while (*feat) {
- virCPUDefAddFeatureIfMissing(cpu, *feat, VIR_CPU_FEATURE_DISABLE);
- feat++;
- }
+ virCPUx86AddRemovedFeatures(cpu, model, VIR_CPU_FEATURE_DISABLE);
}
@@ -2940,7 +2948,8 @@ x86UpdateHostModel(virCPUDef *guest,
static int
virCPUx86Update(virCPUDef *guest,
const virCPUDef *host,
- bool relative)
+ bool relative,
+ virCPUFeaturePolicy removedPolicy)
{
g_autoptr(virCPUx86Model) model = NULL;
virCPUx86Model *guestModel;
@@ -2985,7 +2994,7 @@ virCPUx86Update(virCPUDef *guest,
return -1;
}
- virCPUx86DisableRemovedFeatures(guest, guestModel);
+ virCPUx86AddRemovedFeatures(guest, guestModel, removedPolicy);
return 0;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index e42b04865b..bda62f2e5c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6763,7 +6763,8 @@ qemuDomainDefFormatBufInternal(virQEMUDriver *driver,
if (virCPUUpdate(def->os.arch, def->cpu,
virQEMUCapsGetHostModel(qCaps, def->virtType,
- VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) <
0)
+ VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE),
+ VIR_CPU_FEATURE_DISABLE) < 0)
return -1;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index da2b024f92..d5c5342966 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6281,7 +6281,8 @@ qemuProcessUpdateGuestCPU(virDomainDef *def,
if (virCPUUpdate(def->os.arch, def->cpu,
virQEMUCapsGetHostModel(qemuCaps, def->virtType,
- VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) <
0)
+ VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE),
+ VIR_CPU_FEATURE_DISABLE) < 0)
return -1;
cpuModels = virQEMUCapsGetCPUModels(qemuCaps, def->virtType, NULL, NULL);
@@ -8914,7 +8915,8 @@ qemuProcessRefreshCPU(virQEMUDriver *driver,
virCPUDefCopyModelFilter(cpu, hostmig, false, virQEMUCapsCPUFilterFeatures,
&host->arch);
- if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu) < 0)
+ if (virCPUUpdate(vm->def->os.arch, vm->def->cpu, cpu,
+ VIR_CPU_FEATURE_DISABLE) < 0)
return -1;
if (qemuProcessUpdateCPU(vm, VIR_ASYNC_JOB_NONE) < 0)
diff --git a/tests/cputest.c b/tests/cputest.c
index 93cd0e12a7..32bf86997a 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -236,7 +236,7 @@ cpuTestGuestCPU(const void *arg)
goto cleanup;
}
- if (virCPUUpdate(host->arch, cpu, host) < 0 ||
+ if (virCPUUpdate(host->arch, cpu, host, VIR_CPU_FEATURE_DISABLE) < 0 ||
virCPUTranslate(host->arch, cpu, data->models) < 0) {
ret = -1;
goto cleanup;
@@ -363,7 +363,7 @@ cpuTestUpdate(const void *arg)
if (!(migHost = virCPUCopyMigratable(data->arch, host)))
return -1;
- if (virCPUUpdate(host->arch, cpu, migHost) < 0)
+ if (virCPUUpdate(host->arch, cpu, migHost, VIR_CPU_FEATURE_DISABLE) < 0)
return -1;
result = g_strdup_printf("%s+%s", data->host, data->name);
--
2.44.0