diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index bf94811960..44094bd0df 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -538,12 +538,11 @@ virCPUBaseline(virArch arch, * @guest: guest CPU definition to be updated * @host: host CPU definition * - * Updates @guest CPU definition according to @host CPU. This is required 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. - * When the guest CPU was not specified relatively, the function does nothing - * and returns success. + * 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. * * Returns 0 on success, -1 on error. */ @@ -553,6 +552,7 @@ virCPUUpdate(virArch arch, const virCPUDef *host) { struct cpuArchDriver *driver; + bool relative; VIR_DEBUG("arch=%s, guest=%p mode=%s model=%s, host=%p model=%s", virArchToString(arch), guest, virCPUModeTypeToString(guest->mode), @@ -561,30 +561,36 @@ virCPUUpdate(virArch arch, if (!(driver = cpuGetSubDriver(arch))) return -1; - if (guest->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) + switch ((virCPUMode) guest->mode) { + case VIR_CPU_MODE_HOST_PASSTHROUGH: return 0; - if (guest->mode == VIR_CPU_MODE_CUSTOM && - guest->match != VIR_CPU_MATCH_MINIMUM) { - size_t i; - bool optional = false; + case VIR_CPU_MODE_HOST_MODEL: + relative = true; + break; - for (i = 0; i < guest->nfeatures; i++) { - if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) { - optional = true; - break; + case VIR_CPU_MODE_CUSTOM: + if (guest->match == VIR_CPU_MATCH_MINIMUM) { + relative = true; + } else { + size_t i; + + relative = false; + for (i = 0; i < guest->nfeatures; i++) { + if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) { + relative = true; + break; + } } } + break; - if (!optional) - return 0; + case VIR_CPU_MODE_LAST: + default: + virReportEnumRangeError(virCPUMode, guest->mode); + return -1; } - /* We get here if guest CPU is either - * - host-model - * - custom with minimum match - * - custom with optional features - */ if (!driver->update) { virReportError(VIR_ERR_NO_SUPPORT, _("cannot update guest CPU for %s architecture"), @@ -592,7 +598,7 @@ virCPUUpdate(virArch arch, return -1; } - if (driver->update(guest, host) < 0) + if (driver->update(guest, host, relative) < 0) return -1; VIR_DEBUG("model=%s", NULLSTR(guest->model)); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index cc2d132275..ff4fb7e103 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -79,7 +79,8 @@ typedef virCPUDefPtr typedef int (*virCPUArchUpdate)(virCPUDefPtr guest, - const virCPUDef *host); + const virCPUDef *host, + bool relative); typedef int (*virCPUArchUpdateLive)(virCPUDefPtr cpu, diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 31997b59cd..8a408a324a 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -415,11 +415,12 @@ virCPUarmGetMap(void) static int virCPUarmUpdate(virCPUDefPtr guest, - const virCPUDef *host) + const virCPUDef *host, + bool relative) { g_autoptr(virCPUDef) updated = NULL; - if (guest->mode != VIR_CPU_MODE_HOST_MODEL) + if (!relative || guest->mode != VIR_CPU_MODE_HOST_MODEL) return 0; if (!host) { diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index 555eeecbe7..d71d147207 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -614,7 +614,8 @@ virCPUppc64GetHost(virCPUDefPtr cpu, static int virCPUppc64Update(virCPUDefPtr guest, - const virCPUDef *host G_GNUC_UNUSED) + const virCPUDef *host G_GNUC_UNUSED, + bool relative G_GNUC_UNUSED) { /* * - host-passthrough doesn't even get here diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c index c1c5686244..17321dc04a 100644 --- a/src/cpu/cpu_s390.c +++ b/src/cpu/cpu_s390.c @@ -43,11 +43,15 @@ virCPUs390Compare(virCPUDefPtr host G_GNUC_UNUSED, static int virCPUs390Update(virCPUDefPtr guest, - const virCPUDef *host) + const virCPUDef *host, + bool relative) { g_autoptr(virCPUDef) updated = NULL; size_t i; + if (!relative) + return 0; + if (guest->mode == VIR_CPU_MODE_CUSTOM) { if (guest->match == VIR_CPU_MATCH_MINIMUM) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 0e533c62e1..72f17070e1 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -2936,12 +2936,16 @@ x86UpdateHostModel(virCPUDefPtr guest, static int virCPUx86Update(virCPUDefPtr guest, - const virCPUDef *host) + const virCPUDef *host, + bool relative) { g_autoptr(virCPUx86Model) model = NULL; virCPUx86MapPtr map; size_t i; + if (!relative) + return 0; + if (!host) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unknown host CPU model"));