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);