[PATCH 0/6] qemu: Fix incoming migration to QEMU >= 10.0.0
Incoming migration of domains with multiple CPU threads to QEMU 10.0.0 or newer is broken unless "ht" feature is explicitly enabled in the domain XML. See 6/6 for details. Jiri Denemark (6): cpu_conf: Make virCPUDefFilterFeatures return void qemu_domain: Simplify qemuDomainFixupCPUs qemu_domain: Fix qemuDomainFixupCPUs qemu_process: Always fix CPUs on reconnect qemu_monitor: Filter CPU features reported by QEMU qemu: Ignore "ht" CPU feature src/conf/cpu_conf.c | 9 ++-- src/conf/cpu_conf.h | 2 +- src/qemu/qemu_capabilities.c | 16 ++++---- src/qemu/qemu_domain.c | 41 +++++++------------ src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_monitor.c | 6 ++- src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 16 ++++++-- src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_process.c | 17 +++----- tests/qemumonitorjsontest.c | 1 + .../cpu-cache-disable3.x86_64-latest.args | 2 +- ...u-check-default-partial.x86_64-latest.args | 2 +- .../cpu-exact2-nofallback.x86_64-latest.args | 2 +- .../cpu-exact2-nofallback.x86_64-latest.xml | 1 - .../qemuxmlconfdata/cpu-exact2-nofallback.xml | 1 - .../cpu-exact2.x86_64-latest.args | 2 +- .../cpu-exact2.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-exact2.xml | 1 - .../cpu-host-model-cmt.x86_64-latest.args | 2 +- .../cpu-host-model-vendor.x86_64-latest.args | 2 +- .../cpu-minimum1.x86_64-latest.args | 2 +- .../cpu-minimum2.x86_64-latest.args | 2 +- .../cpu-phys-bits-emulate2.x86_64-latest.args | 2 +- .../cpu-strict1.x86_64-latest.args | 2 +- .../cpu-strict1.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-strict1.xml | 1 - .../cpu-tsc-frequency.x86_64-latest.args | 2 +- 28 files changed, 63 insertions(+), 77 deletions(-) -- 2.51.0
From: Jiri Denemark <jdenemar@redhat.com> The only thing that can fail inside virCPUDefFilterFeatures is VIR_DELETE_ELEMENT_INPLACE macro. The macro just calls virDeleteElementsN, which reports a warning when all elements to be removed are not within the array bounds and returns -1. The function succeeds otherwise. But since VIR_DELETE_ELEMENT_INPLACE sets the number of elements to be removed to 1 and we call it with i < cpu->nfeatures, the safety check in virDeleteElementsN will never fail. And even if we theoretically called it with wrong arguments, it just wouldn't do anything. Thus we can safely assume VIR_DELETE_ELEMENT_INPLACE always succeeds in virCPUDefFilterFeatures and avoid reporting any errors to simplify callers. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/cpu_conf.c | 9 ++++----- src/conf/cpu_conf.h | 2 +- src/qemu/qemu_capabilities.c | 15 ++++++--------- src/qemu/qemu_domain.c | 3 +-- src/qemu/qemu_process.c | 5 ++--- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 31425783ba..7aeedf64f5 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -1017,7 +1017,7 @@ virCPUDefListExplicitFeatures(const virCPUDef *def) } -int +void virCPUDefFilterFeatures(virCPUDef *cpu, virCPUDefFeatureFilter filter, void *opaque) @@ -1031,11 +1031,10 @@ virCPUDefFilterFeatures(virCPUDef *cpu, } VIR_FREE(cpu->features[i].name); - if (VIR_DELETE_ELEMENT_INPLACE(cpu->features, i, cpu->nfeatures) < 0) - return -1; - } - return 0; + /* Safe to ignore as an error is returned only for invalid arguments */ + ignore_value(VIR_DELETE_ELEMENT_INPLACE(cpu->features, i, cpu->nfeatures)); + } } diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 28e26303ef..cfb8f1a461 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -260,7 +260,7 @@ virCPUFeatureDef * virCPUDefFindFeature(const virCPUDef *def, const char *name); -int +void virCPUDefFilterFeatures(virCPUDef *cpu, virCPUDefFeatureFilter filter, void *opaque); diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 83946123be..2c966e7ef0 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4023,17 +4023,14 @@ virQEMUCapsInitHostCPUModel(virQEMUCaps *qemuCaps, if (ARCH_IS_X86(qemuCaps->arch) && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_UNAVAILABLE_FEATURES)) { - if (cpu && - virCPUDefFilterFeatures(cpu, virCPUx86FeatureFilterDropMSR, NULL) < 0) - goto error; + if (cpu) + virCPUDefFilterFeatures(cpu, virCPUx86FeatureFilterDropMSR, NULL); - if (migCPU && - virCPUDefFilterFeatures(migCPU, virCPUx86FeatureFilterDropMSR, NULL) < 0) - goto error; + if (migCPU) + virCPUDefFilterFeatures(migCPU, virCPUx86FeatureFilterDropMSR, NULL); - if (fullCPU && - virCPUDefFilterFeatures(fullCPU, virCPUx86FeatureFilterDropMSR, NULL) < 0) - goto error; + if (fullCPU) + virCPUDefFilterFeatures(fullCPU, virCPUx86FeatureFilterDropMSR, NULL); } if (virQEMUCapsTypeIsAccelerated(type)) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 375e0e441a..227eee3646 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5319,8 +5319,7 @@ qemuDomainMakeCPUMigratable(virArch arch, g_auto(GStrv) keep = virCPUDefListExplicitFeatures(origCPU); data.keep = keep; - if (virCPUDefFilterFeatures(cpu, qemuDomainDropAddedCPUFeatures, &data) < 0) - return -1; + virCPUDefFilterFeatures(cpu, qemuDomainDropAddedCPUFeatures, &data); } } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 9926998f85..17eac5772b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6552,9 +6552,8 @@ qemuProcessUpdateGuestCPU(virDomainDef *def, def->cpu->fallback = VIR_CPU_FALLBACK_FORBID; } - if (virCPUDefFilterFeatures(def->cpu, virQEMUCapsCPUFilterFeatures, - &def->os.arch) < 0) - return -1; + virCPUDefFilterFeatures(def->cpu, virQEMUCapsCPUFilterFeatures, + &def->os.arch); if (def->cpu->deprecated_feats) { virCPUFeaturePolicy policy = VIR_CPU_FEATURE_REQUIRE; -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
The only thing that can fail inside virCPUDefFilterFeatures is VIR_DELETE_ELEMENT_INPLACE macro. The macro just calls virDeleteElementsN, which reports a warning when all elements to be removed are not within the array bounds and returns -1. The function succeeds otherwise. But since VIR_DELETE_ELEMENT_INPLACE sets the number of elements to be removed to 1 and we call it with i < cpu->nfeatures, the safety check in virDeleteElementsN will never fail. And even if we theoretically called it with wrong arguments, it just wouldn't do anything.
Thus we can safely assume VIR_DELETE_ELEMENT_INPLACE always succeeds in virCPUDefFilterFeatures and avoid reporting any errors to simplify callers.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/cpu_conf.c | 9 ++++----- src/conf/cpu_conf.h | 2 +- src/qemu/qemu_capabilities.c | 15 ++++++--------- src/qemu/qemu_domain.c | 3 +-- src/qemu/qemu_process.c | 5 ++--- 5 files changed, 14 insertions(+), 20 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Jiri Denemark <jdenemar@redhat.com> Since virCPUDefFilterFeatures never fails, we can use it for in-place modifications instead of modifying a temporary virCPUDef copy. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_domain.c | 26 ++++++-------------------- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_process.c | 4 ++-- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 227eee3646..0c0ac4d82d 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9633,7 +9633,7 @@ qemuDomainUpdateCPU(virDomainObj *vm, */ void qemuDomainFixupCPUs(virDomainObj *vm, - virCPUDef **origCPU) + virCPUDef *origCPU) { virArch arch = vm->def->os.arch; @@ -9649,28 +9649,14 @@ qemuDomainFixupCPUs(virDomainObj *vm, * we asked for or libvirt was too old to mess up the translation from * host-model. */ - if (!*origCPU) + if (!origCPU) return; - if (virCPUDefFindFeature(vm->def->cpu, "cmt")) { - g_autoptr(virCPUDef) fixedCPU = virCPUDefCopyWithoutModel(vm->def->cpu); + if (virCPUDefFindFeature(vm->def->cpu, "cmt")) + virCPUDefFilterFeatures(vm->def->cpu, virQEMUCapsCPUFilterFeatures, &arch); - virCPUDefCopyModelFilter(fixedCPU, vm->def->cpu, false, - virQEMUCapsCPUFilterFeatures, &arch); - - virCPUDefFree(vm->def->cpu); - vm->def->cpu = g_steal_pointer(&fixedCPU); - } - - if (virCPUDefFindFeature(*origCPU, "cmt")) { - g_autoptr(virCPUDef) fixedOrig = virCPUDefCopyWithoutModel(*origCPU); - - virCPUDefCopyModelFilter(fixedOrig, *origCPU, false, - virQEMUCapsCPUFilterFeatures, &arch); - - virCPUDefFree(*origCPU); - *origCPU = g_steal_pointer(&fixedOrig); - } + if (virCPUDefFindFeature(origCPU, "cmt")) + virCPUDefFilterFeatures(origCPU, virQEMUCapsCPUFilterFeatures, &arch); } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index fe4ba4fa15..3396f929fd 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -997,7 +997,7 @@ qemuDomainUpdateCPU(virDomainObj *vm, void qemuDomainFixupCPUs(virDomainObj *vm, - virCPUDef **origCPU); + virCPUDef *origCPU); char * qemuDomainGetMachineName(virDomainObj *vm); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 17eac5772b..330519fd2e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8695,7 +8695,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn, * the CPU definitions. */ if (cookie) - qemuDomainFixupCPUs(vm, &cookie->cpu); + qemuDomainFixupCPUs(vm, cookie->cpu); if (cookie && !cookie->slirpHelper) priv->disableSlirp = true; @@ -9517,7 +9517,7 @@ qemuProcessRefreshCPU(virQEMUDriver *driver, * case the host-model is known to not contain features which QEMU * doesn't know about. */ - qemuDomainFixupCPUs(vm, &priv->origCPU); + qemuDomainFixupCPUs(vm, priv->origCPU); } return 0; -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
Since virCPUDefFilterFeatures never fails, we can use it for in-place modifications instead of modifying a temporary virCPUDef copy.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_domain.c | 26 ++++++-------------------- src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_process.c | 4 ++-- 3 files changed, 9 insertions(+), 23 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Jiri Denemark <jdenemar@redhat.com> The function was apparently created when the list of ignored CPU features contained just cmt and related features. The list grew quite a bit since then and this function stopped making sense as it would remove all ignored features from CPU definitions but only if cmt was present. The issue with cmt is long gone and this function was not really doing anything. Surprisingly this didn't cause any real issues as we don't update CPU definitions with features unknown to QEMU. But we may still want to remove ignored features even though QEMU knows about them for compatibility reasons. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_domain.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 0c0ac4d82d..a42721efad 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9614,15 +9614,20 @@ qemuDomainUpdateCPU(virDomainObj *vm, /** - * qemuDomainFixupCPUS: + * qemuDomainFixupCPUs: * @vm: domain object * @origCPU: original CPU used when the domain was started * * Libvirt older than 3.9.0 could have messed up the expansion of host-model * CPU when reconnecting to a running domain by adding features QEMU does not - * support (such as cmt). This API fixes both the actual CPU provided by QEMU - * (stored in the domain object) and the @origCPU used when starting the - * domain. + * support (such as cmt). + * + * Newer libvirt would not include feature unknown to QEMU, but the CPU + * definitions could contain features that were removed from QEMU and added to + * our list of ignored features as they were not actually doing anything. + * + * This API fixes both the actual CPU provided by QEMU (stored in the domain + * object) and the @origCPU used when starting the domain. * * This is safe even if the original CPU definition used mode='custom' (rather * than host-model) since we know QEMU was able to start the domain and thus @@ -9652,11 +9657,8 @@ qemuDomainFixupCPUs(virDomainObj *vm, if (!origCPU) return; - if (virCPUDefFindFeature(vm->def->cpu, "cmt")) - virCPUDefFilterFeatures(vm->def->cpu, virQEMUCapsCPUFilterFeatures, &arch); - - if (virCPUDefFindFeature(origCPU, "cmt")) - virCPUDefFilterFeatures(origCPU, virQEMUCapsCPUFilterFeatures, &arch); + virCPUDefFilterFeatures(vm->def->cpu, virQEMUCapsCPUFilterFeatures, &arch); + virCPUDefFilterFeatures(origCPU, virQEMUCapsCPUFilterFeatures, &arch); } -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
The function was apparently created when the list of ignored CPU features contained just cmt and related features. The list grew quite a bit since then and this function stopped making sense as it would remove all ignored features from CPU definitions but only if cmt was present. The issue with cmt is long gone and this function was not really doing anything. Surprisingly this didn't cause any real issues as we don't update CPU definitions with features unknown to QEMU. But we may still want to remove ignored features even though QEMU knows about them for compatibility reasons.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_domain.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Jiri Denemark <jdenemar@redhat.com> We fix CPUs (i.e., remove ignored CPU features) only when libvirt/QEMU combo used to start the domain is very old and doesn't support query-cpu-model-expansion, in which case the CPU definition may contain features that are unknown to QEMU. But even if both libvirt and QEMU are new enough, we still want to remove features that do nothing to minimize confusion or to avoid false migration issues. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_process.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 330519fd2e..d93ea4058d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9511,12 +9511,7 @@ qemuProcessRefreshCPU(virQEMUDriver *driver, if (qemuProcessUpdateCPU(vm, VIR_ASYNC_JOB_NONE) < 0) return -1; - } else if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) { - /* We only try to fix CPUs when the libvirt/QEMU combo used to start - * the domain did not know about query-cpu-model-expansion in which - * case the host-model is known to not contain features which QEMU - * doesn't know about. - */ + } else { qemuDomainFixupCPUs(vm, priv->origCPU); } -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
We fix CPUs (i.e., remove ignored CPU features) only when libvirt/QEMU combo used to start the domain is very old and doesn't support query-cpu-model-expansion, in which case the CPU definition may contain features that are unknown to QEMU. But even if both libvirt and QEMU are new enough, we still want to remove features that do nothing to minimize confusion or to avoid false migration issues.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_process.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Jiri Denemark <jdenemar@redhat.com> Some features may be on our ignore list because they do nothing even though QEMU still supports them and reports their state. But as the features do nothing, the state reported by QEMU may not correspond to what the guest sees. To avoid possible confusion we may just pretend QEMU did not report any of the features on our ignore list. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor.c | 6 ++++-- src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 16 ++++++++++++---- src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_process.c | 1 + tests/qemumonitorjsontest.c | 1 + 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index f9b320f765..3dbaaf9c59 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3686,7 +3686,8 @@ qemuMonitorSetDomainLog(qemuMonitor *mon, * a single qom-list-get QMP command * @cpuQOMPath: QOM path of a CPU to probe * @translate: callback for translating CPU feature names from QEMU to libvirt - * @opaque: data for @translate callback + * @filter: callback for filtering ignored features, a pointer to @arch is + * passed as opaque pointer to the callback * @enabled: returns the CPU data for all enabled features * @disabled: returns the CPU data for features which we asked for * (either explicitly or via a named CPU model) but QEMU disabled them @@ -3701,6 +3702,7 @@ qemuMonitorGetGuestCPU(qemuMonitor *mon, bool qomListGet, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, + virCPUDefFeatureFilter filter, virCPUData **enabled, virCPUData **disabled) { @@ -3715,7 +3717,7 @@ qemuMonitorGetGuestCPU(qemuMonitor *mon, *disabled = NULL; return qemuMonitorJSONGetGuestCPU(mon, arch, qomListGet, cpuQOMPath, - translate, enabled, disabled); + translate, filter, enabled, disabled); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f611ebfa24..d950d548b4 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1495,6 +1495,7 @@ qemuMonitorGetGuestCPU(qemuMonitor *mon, bool qomListGet, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, + virCPUDefFeatureFilter filter, virCPUData **enabled, virCPUData **disabled); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c121c05ffd..9b9a005771 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6795,7 +6795,8 @@ qemuMonitorJSONGetCPUProperties(qemuMonitor *mon, static int qemuMonitorJSONCPUDataAddFeatures(virCPUData *data, GStrv props, - qemuMonitorCPUFeatureTranslationCallback translate) + qemuMonitorCPUFeatureTranslationCallback translate, + virCPUDefFeatureFilter filter) { char **p; @@ -6805,6 +6806,9 @@ qemuMonitorJSONCPUDataAddFeatures(virCPUData *data, if (translate) name = translate(data->arch, name); + if (filter && !filter(name, VIR_CPU_FEATURE_REQUIRE, &data->arch)) + continue; + if (virCPUDataAddFeature(data, name) < 0) return -1; } @@ -6821,7 +6825,8 @@ qemuMonitorJSONCPUDataAddFeatures(virCPUData *data, * a single qom-list-get QMP command * @cpuQOMPath: QOM path of a CPU to probe * @translate: callback for translating CPU feature names from QEMU to libvirt - * @opaque: data for @translate callback + * @filter: callback for filtering ignored features, a pointer to @arch is + * passed as opaque pointer to the callback * @enabled: returns the CPU data for all enabled features * @disabled: returns the CPU data for features which we asked for * (either explicitly or via a named CPU model) but QEMU disabled them @@ -6836,6 +6841,7 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, bool qomListGet, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, + virCPUDefFeatureFilter filter, virCPUData **enabled, virCPUData **disabled) { @@ -6852,8 +6858,10 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, &propsEnabled, &propsDisabled) < 0) return -1; - if (qemuMonitorJSONCPUDataAddFeatures(cpuEnabled, propsEnabled, translate) < 0 || - qemuMonitorJSONCPUDataAddFeatures(cpuDisabled, propsDisabled, translate) < 0) + if (qemuMonitorJSONCPUDataAddFeatures(cpuEnabled, propsEnabled, + translate, filter) < 0 || + qemuMonitorJSONCPUDataAddFeatures(cpuDisabled, propsDisabled, + translate, filter) < 0) return -1; *enabled = g_steal_pointer(&cpuEnabled); diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 8b06b7599e..f20830532d 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -558,6 +558,7 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, bool qomListGet, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, + virCPUDefFeatureFilter filter, virCPUData **enabled, virCPUData **disabled); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d93ea4058d..45fc32a663 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4595,6 +4595,7 @@ qemuProcessFetchGuestCPU(virDomainObj *vm, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QOM_LIST_GET), cpuQOMPath, virQEMUCapsCPUFeatureFromQEMU, + virQEMUCapsCPUFilterFeatures, &dataEnabled, &dataDisabled); qemuDomainObjExitMonitor(vm); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 6129dde449..bfe81739a7 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2809,6 +2809,7 @@ testQemuMonitorJSONGetGuestCPU(const void *opaque) data->qomListGet, "/machine/unattached/device[0]", virQEMUCapsCPUFeatureFromQEMU, + virQEMUCapsCPUFilterFeatures, &dataEnabled, &dataDisabled) < 0) return -1; -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
Some features may be on our ignore list because they do nothing even though QEMU still supports them and reports their state. But as the features do nothing, the state reported by QEMU may not correspond to what the guest sees. To avoid possible confusion we may just pretend QEMU did not report any of the features on our ignore list.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor.c | 6 ++++-- src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 16 ++++++++++++---- src/qemu/qemu_monitor_json.h | 1 + src/qemu/qemu_process.c | 1 + tests/qemumonitorjsontest.c | 1 + 6 files changed, 20 insertions(+), 6 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Jiri Denemark <jdenemar@redhat.com> The feature does not do anything, QEMU will always set it according to the CPU topology completely ignoring what we asked for. Unfortunately, the way the state of "ht" is reported changed in QEMU 10.0.0 (commit c6bd2dd634208). QEMU older than 10.0.0 would just report whatever was specified on the command line totally ignoring the actual state of the feature visible to a guest. But after the change QEMU reports ht=on in case it enabled "ht" based on the CPU topology. In all other cases QEMU still reports the state requested on the command line. As a result of this change a domain with multiple CPU threads started on QEMU < 10.0.0 could not be migrated to QEMU >= 10.0.0 unless "ht" was explicitly enabled in the domain XML because libvirt would see "ht" enabled on the destination, but disabled on the source (the guest would see "ht" enabled in both cases anyway). Outgoing migration of domains started on QEMU >= 10.0.0 is not affected. To fix this issue we can completely ignore "ht" both in the domain XML and in the CPU properties reported by QEMU. With this fix incoming migration to QEMU >= 10.0.0 works again. https://issues.redhat.com/browse/RHEL-104216 Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 1 + tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args | 2 +- .../cpu-check-default-partial.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-exact2-nofallback.xml | 1 - tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-exact2.xml | 1 - tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-strict1.xml | 1 - tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args | 2 +- 18 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2c966e7ef0..bd1dc26363 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3663,6 +3663,7 @@ const char *ignoredFeatures[] = { "osxsave", "ospke", /* dropped from QEMU */ "vmx-ept-uc", "vmx-ept-wb", /* never supported by QEMU */ "vmx-invvpid-single-context", /* never supported by QEMU */ + "ht", /* ignored by QEMU, set according to topology */ }; bool diff --git a/tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args index 4adf20b55a..1e962589c9 100644 --- a/tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-foo/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,l3-cache=off \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,l3-cache=off \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-check-default-partial.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-check-default-partial.x86_64-latest.args index a92da44bd8..fe553fd31b 100644 --- a/tests/qemuxmlconfdata/cpu-check-default-partial.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-check-default-partial.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args index 20b0306268..7464609aba 100644 --- a/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu core2duo,ds=on,ht=on,tm=on,ds-cpl=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off \ +-cpu core2duo,ds=on,tm=on,ds-cpl=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml b/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml index d66d0a182b..05c78334ab 100644 --- a/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml @@ -11,7 +11,6 @@ <cpu mode='custom' match='exact' check='partial'> <model fallback='forbid'>core2duo</model> <feature policy='require' name='ds'/> - <feature policy='require' name='ht'/> <feature policy='optional' name='tm'/> <feature policy='require' name='ds_cpl'/> <feature policy='require' name='xtpr'/> diff --git a/tests/qemuxmlconfdata/cpu-exact2-nofallback.xml b/tests/qemuxmlconfdata/cpu-exact2-nofallback.xml index 4cd1d18216..d7c3e4f40f 100644 --- a/tests/qemuxmlconfdata/cpu-exact2-nofallback.xml +++ b/tests/qemuxmlconfdata/cpu-exact2-nofallback.xml @@ -11,7 +11,6 @@ <cpu match='exact'> <model fallback='forbid'>core2duo</model> <feature name='ds' policy='require'/> - <feature name='ht' policy='require'/> <feature name='tm' policy='optional'/> <feature name='ds_cpl' policy='require'/> <feature name='xtpr' policy='require'/> diff --git a/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args index 20b0306268..7464609aba 100644 --- a/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu core2duo,ds=on,ht=on,tm=on,ds-cpl=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off \ +-cpu core2duo,ds=on,tm=on,ds-cpl=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml b/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml index 7dccf6902c..cf9d241372 100644 --- a/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml @@ -11,7 +11,6 @@ <cpu mode='custom' match='exact' check='partial'> <model fallback='allow'>core2duo</model> <feature policy='require' name='ds'/> - <feature policy='require' name='ht'/> <feature policy='optional' name='tm'/> <feature policy='require' name='ds_cpl'/> <feature policy='require' name='xtpr'/> diff --git a/tests/qemuxmlconfdata/cpu-exact2.xml b/tests/qemuxmlconfdata/cpu-exact2.xml index 4239796f31..b4800262f6 100644 --- a/tests/qemuxmlconfdata/cpu-exact2.xml +++ b/tests/qemuxmlconfdata/cpu-exact2.xml @@ -11,7 +11,6 @@ <cpu match='exact'> <model>core2duo</model> <feature name='ds' policy='require'/> - <feature name='ht' policy='require'/> <feature name='tm' policy='optional'/> <feature name='ds_cpl' policy='require'/> <feature name='xtpr' policy='require'/> diff --git a/tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args index 510e19bba6..d6b57d40a3 100644 --- a/tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel tcg \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args index c258a1ab36..ef7d442d5b 100644 --- a/tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel tcg \ --cpu 'Haswell,vendor=Libvirt QEMU,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on' \ +-cpu 'Haswell,vendor=Libvirt QEMU,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on' \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args index a92da44bd8..fe553fd31b 100644 --- a/tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args index 62e0101568..ddd0c64080 100644 --- a/tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,syscall=off,nx=off,lm=off,svm=off \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,syscall=off,nx=off,lm=off,svm=off \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args index 92c719b553..3808af7399 100644 --- a/tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-foo/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,phys-bits=42 \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,phys-bits=42 \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args index 3f9c3516bb..7e870db393 100644 --- a/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,ds=on,acpi=on,ht=on,tm=on,ds-cpl=on,vmx=on,est=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off,vme=off,invtsc=off,abm=off,pdpe1gb=off,rdrand=off,f16c=off,pdcm=off,smx=off,monitor=off,dtes64=off \ +-cpu Haswell,ds=on,acpi=on,tm=on,ds-cpl=on,vmx=on,est=on,xtpr=on,3dnowext=on,lahf-lm=on,nx=off,cx16=off,tm2=off,pbe=off,ss=off,sse4a=off,wdt=off,vme=off,invtsc=off,abm=off,pdpe1gb=off,rdrand=off,f16c=off,pdcm=off,smx=off,monitor=off,dtes64=off \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ diff --git a/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml b/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml index beeaf5c682..9c5e083aee 100644 --- a/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml @@ -12,7 +12,6 @@ <model fallback='allow'>Haswell</model> <feature policy='require' name='ds'/> <feature policy='optional' name='acpi'/> - <feature policy='require' name='ht'/> <feature policy='optional' name='tm'/> <feature policy='require' name='ds_cpl'/> <feature policy='optional' name='vmx'/> diff --git a/tests/qemuxmlconfdata/cpu-strict1.xml b/tests/qemuxmlconfdata/cpu-strict1.xml index 63db54ecad..c0548b3dca 100644 --- a/tests/qemuxmlconfdata/cpu-strict1.xml +++ b/tests/qemuxmlconfdata/cpu-strict1.xml @@ -12,7 +12,6 @@ <model>Haswell</model> <feature name='ds' policy='require'/> <feature name='acpi' policy='optional'/> - <feature name='ht' policy='require'/> <feature name='tm' policy='optional'/> <feature name='ds_cpl' policy='require'/> <feature name='vmx' policy='optional'/> diff --git a/tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args b/tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args index 4353d65ac2..e926d309f5 100644 --- a/tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args +++ b/tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args @@ -12,7 +12,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ -machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ -accel kvm \ --cpu Haswell,vme=on,ds=on,acpi=on,ss=on,ht=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,invtsc=on,tsc-frequency=4567890000 \ +-cpu Haswell,vme=on,ds=on,acpi=on,ss=on,tm=on,pbe=on,dtes64=on,monitor=on,ds-cpl=on,vmx=on,smx=on,est=on,tm2=on,xtpr=on,pdcm=on,f16c=on,rdrand=on,pdpe1gb=on,abm=on,lahf-lm=on,invtsc=on,tsc-frequency=4567890000 \ -m size=219136k \ -object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ -overcommit mem-lock=off \ -- 2.51.0
On a Thursday in 2025, Jiri Denemark via Devel wrote:
From: Jiri Denemark <jdenemar@redhat.com>
The feature does not do anything, QEMU will always set it according to the CPU topology completely ignoring what we asked for. Unfortunately, the way the state of "ht" is reported changed in QEMU 10.0.0 (commit c6bd2dd634208).
QEMU older than 10.0.0 would just report whatever was specified on the command line totally ignoring the actual state of the feature visible to a guest. But after the change QEMU reports ht=on in case it enabled "ht" based on the CPU topology. In all other cases QEMU still reports the state requested on the command line.
As a result of this change a domain with multiple CPU threads started on QEMU < 10.0.0 could not be migrated to QEMU >= 10.0.0 unless "ht" was explicitly enabled in the domain XML because libvirt would see "ht" enabled on the destination, but disabled on the source (the guest would see "ht" enabled in both cases anyway). Outgoing migration of domains started on QEMU >= 10.0.0 is not affected.
To fix this issue we can completely ignore "ht" both in the domain XML and in the CPU properties reported by QEMU. With this fix incoming migration to QEMU >= 10.0.0 works again.
https://issues.redhat.com/browse/RHEL-104216
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 1 + tests/qemuxmlconfdata/cpu-cache-disable3.x86_64-latest.args | 2 +- .../cpu-check-default-partial.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2-nofallback.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-exact2-nofallback.xml | 1 - tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-exact2.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-exact2.xml | 1 - tests/qemuxmlconfdata/cpu-host-model-cmt.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-host-model-vendor.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-minimum1.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-minimum2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-phys-bits-emulate2.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/cpu-strict1.x86_64-latest.xml | 1 - tests/qemuxmlconfdata/cpu-strict1.xml | 1 - tests/qemuxmlconfdata/cpu-tsc-frequency.x86_64-latest.args | 2 +- 18 files changed, 12 insertions(+), 17 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (2)
-
Jiri Denemark -
Ján Tomko