diff --git a/.gitignore b/.gitignore index 3878653..a5dd4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/libvirt-9.5.0.tar.xz +SOURCES/libvirt-10.0.0.tar.xz diff --git a/.libvirt.metadata b/.libvirt.metadata index ad362aa..3a0ea2e 100644 --- a/.libvirt.metadata +++ b/.libvirt.metadata @@ -1 +1 @@ -472f6871651d8d3b41b2a2602adfcdb18629049d SOURCES/libvirt-9.5.0.tar.xz +7a2e402bfb1ad295544de6cd527c4c04e85c5096 SOURCES/libvirt-10.0.0.tar.xz diff --git a/SOURCES/libvirt-Don-t-overwrite-error-message-from-virXPathNodeSet.patch b/SOURCES/libvirt-Don-t-overwrite-error-message-from-virXPathNodeSet.patch new file mode 100644 index 0000000..9848939 --- /dev/null +++ b/SOURCES/libvirt-Don-t-overwrite-error-message-from-virXPathNodeSet.patch @@ -0,0 +1,679 @@ +From 9a31f486329e36bbe6f6156eb89d4d455fc0a7d8 Mon Sep 17 00:00:00 2001 +Message-ID: <9a31f486329e36bbe6f6156eb89d4d455fc0a7d8.1707394627.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 29 Jan 2024 15:50:27 +0100 +Subject: [PATCH] Don't overwrite error message from 'virXPathNodeSet' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +'virXPathNodeSet' returns -1 only when 'ctxt' or 'xpath' are NULL or +when the 'xpath' string is invalid. Both are programming errors. It +doesn't make sense for the code to overwrite the error message for +anything supposedly more relevant. + +The majority of calls to 'virXPathNodeSet' already didn't do this, so +this patch fixes the rest to prevent it from spreading again. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit a9f76d6ab7278864150d9f4776750ea22d7ef508) + +https://issues.redhat.com/browse/RHEL-22314 [9.4.0] +--- + src/conf/domain_conf.c | 78 +++++++------------------------ + src/conf/network_conf.c | 80 ++++++++------------------------ + src/conf/node_device_conf.c | 17 ++----- + src/conf/numa_conf.c | 15 +++--- + src/cpu/cpu_ppc64.c | 5 +- + src/qemu/qemu_capabilities.c | 30 +++--------- + src/qemu/qemu_domain.c | 23 +++------ + src/qemu/qemu_migration_cookie.c | 5 +- + src/qemu/qemu_nbdkit.c | 5 +- + src/vz/vz_sdk.c | 5 +- + 10 files changed, 72 insertions(+), 191 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index ac06fa39f6..52a5796ad2 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -17765,11 +17765,8 @@ virDomainResctrlMonDefParse(virDomainDef *def, + + ctxt->node = node; + +- if ((n = virXPathNodeSet("./monitor", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("Cannot extract monitor nodes")); ++ if ((n = virXPathNodeSet("./monitor", ctxt, &nodes)) < 0) + goto cleanup; +- } + + for (i = 0; i < n; i++) { + domresmon = g_new0(virDomainResctrlMonDef, 1); +@@ -17897,11 +17894,8 @@ virDomainCachetuneDefParse(virDomainDef *def, + if (virBitmapIsAllClear(vcpus)) + return 0; + +- if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("Cannot extract cache nodes under cachetune")); ++ if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0) + return -1; +- } + + if (virDomainResctrlVcpuMatch(def, vcpus, &resctrl) < 0) + return -1; +@@ -18167,11 +18161,8 @@ virDomainDefParseMemory(virDomainDef *def, + + if (virXPathNode("./memoryBacking/hugepages", ctxt)) { + /* hugepages will be used */ +- if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract hugepages nodes")); ++ if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) + return -1; +- } + + if (n) { + def->mem.hugepages = g_new0(virDomainHugePage, n); +@@ -18255,11 +18246,8 @@ virDomainMemorytuneDefParse(virDomainDef *def, + if (virBitmapIsAllClear(vcpus)) + return 0; + +- if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("Cannot extract memory nodes under memorytune")); ++ if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0) + return -1; +- } + + if (virDomainResctrlVcpuMatch(def, vcpus, &resctrl) < 0) + return -1; +@@ -18326,11 +18314,9 @@ virDomainDefTunablesParse(virDomainDef *def, + &def->blkio.weight) < 0) + def->blkio.weight = 0; + +- if ((n = virXPathNodeSet("./blkiotune/device", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("cannot extract blkiotune nodes")); ++ if ((n = virXPathNodeSet("./blkiotune/device", ctxt, &nodes)) < 0) + return -1; +- } ++ + if (n) + def->blkio.devices = g_new0(virBlkioDevice, n); + +@@ -18441,11 +18427,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/emulatorpin", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract emulatorpin nodes")); ++ if ((n = virXPathNodeSet("./cputune/emulatorpin", ctxt, &nodes)) < 0) + return -1; +- } + + if (n) { + if (n > 1) { +@@ -18460,11 +18443,8 @@ virDomainDefTunablesParse(virDomainDef *def, + VIR_FREE(nodes); + + +- if ((n = virXPathNodeSet("./cputune/iothreadpin", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract iothreadpin nodes")); ++ if ((n = virXPathNodeSet("./cputune/iothreadpin", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + if (virDomainIOThreadPinDefParseXML(nodes[i], def) < 0) +@@ -18472,11 +18452,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/vcpusched", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract vcpusched nodes")); ++ if ((n = virXPathNodeSet("./cputune/vcpusched", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + if (virDomainVcpuThreadSchedParse(nodes[i], def) < 0) +@@ -18484,11 +18461,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/iothreadsched", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract iothreadsched nodes")); ++ if ((n = virXPathNodeSet("./cputune/iothreadsched", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + if (virDomainIOThreadSchedParse(nodes[i], def) < 0) +@@ -18496,11 +18470,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/emulatorsched", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract emulatorsched nodes")); ++ if ((n = virXPathNodeSet("./cputune/emulatorsched", ctxt, &nodes)) < 0) + return -1; +- } + + if (n) { + if (n > 1) { +@@ -18514,11 +18485,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/cachetune", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract cachetune nodes")); ++ if ((n = virXPathNodeSet("./cputune/cachetune", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + if (virDomainCachetuneDefParse(def, ctxt, nodes[i], flags) < 0) +@@ -18526,11 +18494,8 @@ virDomainDefTunablesParse(virDomainDef *def, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract memorytune nodes")); ++ if ((n = virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + if (virDomainMemorytuneDefParse(def, ctxt, nodes[i], flags) < 0) +@@ -18834,11 +18799,8 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, + !virDomainIOThreadIDArrayHasPin(def)) + def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO; + +- if ((n = virXPathNodeSet("./resource", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("cannot extract resource nodes")); ++ if ((n = virXPathNodeSet("./resource", ctxt, &nodes)) < 0) + return NULL; +- } + + if (n > 1) { + virReportError(VIR_ERR_XML_ERROR, "%s", +@@ -18886,11 +18848,9 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, + return NULL; + + /* analysis of the resource leases */ +- if ((n = virXPathNodeSet("./devices/lease", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("cannot extract device leases")); ++ if ((n = virXPathNodeSet("./devices/lease", ctxt, &nodes)) < 0) + return NULL; +- } ++ + if (n) + def->leases = g_new0(virDomainLeaseDef *, n); + for (i = 0; i < n; i++) { +@@ -19009,11 +18969,9 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("cannot extract console devices")); ++ if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) + return NULL; +- } ++ + if (n) + def->consoles = g_new0(virDomainChrDef *, n); + +diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c +index 6f8a0d2d0b..52c90e53f8 100644 +--- a/src/conf/network_conf.c ++++ b/src/conf/network_conf.c +@@ -892,13 +892,9 @@ virNetworkDNSDefParseXML(const char *networkName, + &def->forwardPlainNames) < 0) + return -1; + +- nfwds = virXPathNodeSet("./forwarder", ctxt, &fwdNodes); +- if (nfwds < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nfwds = virXPathNodeSet("./forwarder", ctxt, &fwdNodes)) < 0) + return -1; +- } ++ + if (nfwds > 0) { + def->forwarders = g_new0(virNetworkDNSForwarder, nfwds); + +@@ -922,13 +918,9 @@ virNetworkDNSDefParseXML(const char *networkName, + } + } + +- nhosts = virXPathNodeSet("./host", ctxt, &hostNodes); +- if (nhosts < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nhosts = virXPathNodeSet("./host", ctxt, &hostNodes)) < 0) + return -1; +- } ++ + if (nhosts > 0) { + def->hosts = g_new0(virNetworkDNSHostDef, nhosts); + +@@ -941,13 +933,9 @@ virNetworkDNSDefParseXML(const char *networkName, + } + } + +- nsrvs = virXPathNodeSet("./srv", ctxt, &srvNodes); +- if (nsrvs < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nsrvs = virXPathNodeSet("./srv", ctxt, &srvNodes)) < 0) + return -1; +- } ++ + if (nsrvs > 0) { + def->srvs = g_new0(virNetworkDNSSrvDef, nsrvs); + +@@ -960,13 +948,9 @@ virNetworkDNSDefParseXML(const char *networkName, + } + } + +- ntxts = virXPathNodeSet("./txt", ctxt, &txtNodes); +- if (ntxts < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((ntxts = virXPathNodeSet("./txt", ctxt, &txtNodes)) < 0) + return -1; +- } ++ + if (ntxts > 0) { + def->txts = g_new0(virNetworkDNSTxtDef, ntxts); + +@@ -1222,13 +1206,10 @@ virNetworkForwardNatDefParseXML(const char *networkName, + return -1; + + /* addresses for SNAT */ +- nNatAddrs = virXPathNodeSet("./address", ctxt, &natAddrNodes); +- if (nNatAddrs < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid
element found in of network %1$s"), +- networkName); ++ if ((nNatAddrs = virXPathNodeSet("./address", ctxt, &natAddrNodes)) < 0) + return -1; +- } else if (nNatAddrs > 1) { ++ ++ if (nNatAddrs > 1) { + virReportError(VIR_ERR_XML_ERROR, + _("Only one
element is allowed in in in network %1$s"), + networkName); +@@ -1284,13 +1265,10 @@ virNetworkForwardNatDefParseXML(const char *networkName, + } + + /* ports for SNAT and MASQUERADE */ +- nNatPorts = virXPathNodeSet("./port", ctxt, &natPortNodes); +- if (nNatPorts < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nNatPorts = virXPathNodeSet("./port", ctxt, &natPortNodes)) < 0) + return -1; +- } else if (nNatPorts > 1) { ++ ++ if (nNatPorts > 1) { + virReportError(VIR_ERR_XML_ERROR, + _("Only one element is allowed in in in network %1$s"), + networkName); +@@ -1358,37 +1336,19 @@ virNetworkForwardDefParseXML(const char *networkName, + } + + /* bridge and hostdev modes can use a pool of physical interfaces */ +- nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes); +- if (nForwardIfs < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes)) < 0) + return -1; +- } + +- nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes); +- if (nForwardAddrs < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid
element found in of network %1$s"), +- networkName); ++ if ((nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes)) < 0) + return -1; +- } + +- nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes); +- if (nForwardPfs < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes)) < 0) + return -1; +- } + +- nForwardNats = virXPathNodeSet("./nat", ctxt, &forwardNatNodes); +- if (nForwardNats < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("invalid element found in of network %1$s"), +- networkName); ++ if ((nForwardNats = virXPathNodeSet("./nat", ctxt, &forwardNatNodes)) < 0) + return -1; +- } else if (nForwardNats > 1) { ++ ++ if (nForwardNats > 1) { + virReportError(VIR_ERR_XML_ERROR, + _("Only one element is allowed in of network %1$s"), + networkName); +diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c +index 95de77abe9..dd174d3020 100644 +--- a/src/conf/node_device_conf.c ++++ b/src/conf/node_device_conf.c +@@ -960,11 +960,9 @@ virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt, virPCIVPDResource + g_autofree xmlNodePtr *nodes = NULL; + size_t i = 0; + +- if ((nfields = virXPathNodeSet("./vendor_field[@index]", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("failed to evaluate elements")); ++ if ((nfields = virXPathNodeSet("./vendor_field[@index]", ctxt, &nodes)) < 0) + return -1; +- } ++ + for (i = 0; i < nfields; i++) { + g_autofree char *value = NULL; + g_autofree char *index = NULL; +@@ -989,11 +987,9 @@ virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt, virPCIVPDResource + VIR_FREE(nodes); + + if (!readOnly) { +- if ((nfields = virXPathNodeSet("./system_field[@index]", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("failed to evaluate elements")); ++ if ((nfields = virXPathNodeSet("./system_field[@index]", ctxt, &nodes)) < 0) + return -1; +- } ++ + for (i = 0; i < nfields; i++) { + g_autofree char *value = NULL; + g_autofree char *index = NULL; +@@ -1074,11 +1070,8 @@ virNodeDeviceCapVPDParseXML(xmlXPathContextPtr ctxt, virPCIVPDResource **res) + return -1; + } + +- if ((nfields = virXPathNodeSet("./fields[@access]", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("no VPD elements with an access type attribute found")); ++ if ((nfields = virXPathNodeSet("./fields[@access]", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < nfields; i++) { + g_autofree char *access = NULL; +diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c +index bcd7838e00..d8120de6d2 100644 +--- a/src/conf/numa_conf.c ++++ b/src/conf/numa_conf.c +@@ -135,11 +135,8 @@ virDomainNumatuneNodeParseXML(virDomainNuma *numa, + size_t i = 0; + g_autofree xmlNodePtr *nodes = NULL; + +- if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("Cannot extract memnode nodes")); ++ if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0) + return -1; +- } + + if (!n) + return 0; +@@ -700,7 +697,10 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def, + if (!virXPathNode("./distances[1]", ctxt)) + return 0; + +- if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) <= 0) { ++ if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) < 0) ++ goto cleanup; ++ ++ if (sibling == 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("NUMA distances defined without siblings")); + goto cleanup; +@@ -852,7 +852,10 @@ virDomainNumaDefParseXML(virDomainNuma *def, + if (!virXPathNode("./cpu/numa[1]", ctxt)) + return 0; + +- if ((n = virXPathNodeSet("./cpu/numa[1]/cell", ctxt, &cell)) <= 0) { ++ if ((n = virXPathNodeSet("./cpu/numa[1]/cell", ctxt, &cell)) < 0) ++ return -1; ++ ++ if (n == 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("NUMA topology defined without NUMA cells")); + return -1; +diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c +index e13cdbdf6b..448a0a7d85 100644 +--- a/src/cpu/cpu_ppc64.c ++++ b/src/cpu/cpu_ppc64.c +@@ -334,7 +334,10 @@ ppc64ModelParse(xmlXPathContextPtr ctxt, + } + } + +- if ((n = virXPathNodeSet("./pvr", ctxt, &nodes)) <= 0) { ++ if ((n = virXPathNodeSet("./pvr", ctxt, &nodes)) < 0) ++ return -1; ++ ++ if (n == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Missing PVR information for CPU model %1$s"), + model->name); +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index e13df2b27d..10090e0986 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -4015,11 +4015,8 @@ virQEMUCapsLoadCPUModels(virArch arch, + int n; + xmlNodePtr node; + +- if ((n = virXPathNodeSet(xpath, ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu capabilities cpus")); ++ if ((n = virXPathNodeSet(xpath, ctxt, &nodes)) < 0) + return -1; +- } + + if (n == 0) + return 0; +@@ -4057,11 +4054,8 @@ virQEMUCapsLoadCPUModels(virArch arch, + nblockers = virXPathNodeSet("./blocker", ctxt, &blockerNodes); + ctxt->node = node; + +- if (nblockers < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse CPU blockers in QEMU capabilities")); ++ if (nblockers < 0) + return -1; +- } + + if (nblockers > 0) { + size_t j; +@@ -4100,11 +4094,8 @@ virQEMUCapsLoadMachines(virQEMUCapsAccel *caps, + size_t i; + int n; + +- if ((n = virXPathNodeSet(xpath, ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu capabilities machines")); ++ if ((n = virXPathNodeSet(xpath, ctxt, &nodes)) < 0) + return -1; +- } + + if (n == 0) + return 0; +@@ -4317,11 +4308,8 @@ virQEMUCapsParseSGXInfo(virQEMUCaps *qemuCaps, + ctxt->node = sgxSections; + nSgxSections = virXPathNodeSet("./section", ctxt, §ionNodes); + +- if (nSgxSections < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse SGX sections in QEMU capabilities cache")); ++ if (nSgxSections < 0) + return -1; +- } + + sgx->nSgxSections = nSgxSections; + sgx->sgxSections = g_new0(virSGXSection, nSgxSections); +@@ -4404,11 +4392,8 @@ virQEMUCapsParseFlags(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) + size_t i; + int n; + +- if ((n = virXPathNodeSet("./flag", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu capabilities flags")); ++ if ((n = virXPathNodeSet("./flag", ctxt, &nodes)) < 0) + return -1; +- } + + VIR_DEBUG("Got flags %d", n); + for (i = 0; i < n; i++) { +@@ -4442,11 +4427,8 @@ virQEMUCapsParseGIC(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt) + size_t i; + int n; + +- if ((n = virXPathNodeSet("./gic", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu capabilities gic")); ++ if ((n = virXPathNodeSet("./gic", ctxt, &nodes)) < 0) + return -1; +- } + + if (n > 0) { + unsigned int uintValue; +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index e2a1bf2c13..97520bb49c 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -3155,11 +3155,8 @@ qemuDomainObjPrivateXMLParseSlirpFeatures(xmlNodePtr featuresNode, + + ctxt->node = featuresNode; + +- if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("failed to parse slirp-helper features")); ++ if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0) + return -1; +- } + + for (i = 0; i < n; i++) { + g_autofree char *str = virXMLPropString(nodes[i], "name"); +@@ -3273,11 +3270,9 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./qemuCaps/flag", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("failed to parse qemu capabilities flags")); ++ if ((n = virXPathNodeSet("./qemuCaps/flag", ctxt, &nodes)) < 0) + return -1; +- } ++ + if (n > 0) { + qemuCaps = virQEMUCapsNew(); + +@@ -3305,11 +3300,9 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, + + priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) == 1; + +- if ((n = virXPathNodeSet("./devices/device", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu device list")); ++ if ((n = virXPathNodeSet("./devices/device", ctxt, &nodes)) < 0) + return -1; +- } ++ + if (n > 0) { + /* NULL-terminated list */ + priv->qemuDevices = g_new0(char *, n + 1); +@@ -3325,11 +3318,9 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, + } + VIR_FREE(nodes); + +- if ((n = virXPathNodeSet("./slirp/helper", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse slirp helper list")); ++ if ((n = virXPathNodeSet("./slirp/helper", ctxt, &nodes)) < 0) + return -1; +- } ++ + for (i = 0; i < n; i++) { + g_autofree char *alias = virXMLPropString(nodes[i], "alias"); + g_autofree char *pid = virXMLPropString(nodes[i], "pid"); +diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c +index 5505fdaf22..4361949cca 100644 +--- a/src/qemu/qemu_migration_cookie.c ++++ b/src/qemu/qemu_migration_cookie.c +@@ -947,11 +947,8 @@ qemuMigrationCookieNetworkXMLParse(xmlXPathContextPtr ctxt) + g_autofree xmlNodePtr *interfaces = NULL; + VIR_XPATH_NODE_AUTORESTORE(ctxt) + +- if ((n = virXPathNodeSet("./network/interface", ctxt, &interfaces)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- "%s", _("missing interface information")); ++ if ((n = virXPathNodeSet("./network/interface", ctxt, &interfaces)) < 0) + return NULL; +- } + + optr->nnets = n; + optr->net = g_new0(qemuMigrationCookieNetData, optr->nnets); +diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c +index 85e61be44c..3343241aaf 100644 +--- a/src/qemu/qemu_nbdkit.c ++++ b/src/qemu/qemu_nbdkit.c +@@ -400,11 +400,8 @@ qemuNbdkitCapsParseFlags(qemuNbdkitCaps *nbdkitCaps, + size_t i; + int n; + +- if ((n = virXPathNodeSet("./flag", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("failed to parse qemu capabilities flags")); ++ if ((n = virXPathNodeSet("./flag", ctxt, &nodes)) < 0) + return -1; +- } + + VIR_DEBUG("Got flags %d", n); + for (i = 0; i < n; i++) { +diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c +index 6a15d60577..ce4586a3f5 100644 +--- a/src/vz/vz_sdk.c ++++ b/src/vz/vz_sdk.c +@@ -4612,11 +4612,8 @@ prlsdkParseSnapshotTree(const char *treexml) + "ParallelsSavedStates", &ctxt, NULL, false))) + goto cleanup; + +- if ((n = virXPathNodeSet("//SavedStateItem", ctxt, &nodes)) < 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", +- _("cannot extract snapshot nodes")); ++ if ((n = virXPathNodeSet("//SavedStateItem", ctxt, &nodes)) < 0) + goto cleanup; +- } + + for (i = 0; i < n; i++) { + if (nodes[i]->parent == xmlDocGetRootElement(xml)) +-- +2.43.0 diff --git a/SOURCES/libvirt-Set-stubDriverName-from-hostdev-driver-model-attribute-during-pci-device-setup.patch b/SOURCES/libvirt-Set-stubDriverName-from-hostdev-driver-model-attribute-during-pci-device-setup.patch new file mode 100644 index 0000000..d3902f1 --- /dev/null +++ b/SOURCES/libvirt-Set-stubDriverName-from-hostdev-driver-model-attribute-during-pci-device-setup.patch @@ -0,0 +1,44 @@ +From 676946491ea25cacc4f6fd11f27bd9989b84767d Mon Sep 17 00:00:00 2001 +Message-ID: <676946491ea25cacc4f6fd11f27bd9989b84767d.1708614745.git.jdenemar@redhat.com> +From: Laine Stump +Date: Fri, 16 Feb 2024 12:43:59 -0500 +Subject: [PATCH] Set stubDriverName from hostdev driver model attribute during + pci device setup + +commit v9.10.0-129-g8b93d78c83 (first appearing in libvirt-10.0.0) was +supposed to allow forcing a PCI hostdev to be bound to a particular +driver by adding to the XML for the +device. Unfortunately, a single line was missed during the final +changes to the patch prior to pushing, and the result was that the +driver model could be set to *anything* and it would be accepted but +just ignored. + +This patch adds the missing line, which will set the stubDriverName +field of the virPCIDevice object from the hostdev object as the +virPCIDevice is being created. This ends up being used by +virPCIDeviceBindToStub() as the driver that it binds the device to. + +Fixes: 8b93d78c8325f1fba5db98848350f3db43f5e7d5 +Signed-off-by: Laine Stump +Reviewed-by: Reviewed-by: Michal Privoznik +(cherry picked from commit 41fe8524870facae02be067097ea494c475d77f0) + +https://issues.redhat.com/browse/RHEL-25858 [9.4.0] +--- + src/hypervisor/virhostdev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c +index 40f8a4bc2c..185ec2ca50 100644 +--- a/src/hypervisor/virhostdev.c ++++ b/src/hypervisor/virhostdev.c +@@ -242,6 +242,7 @@ virHostdevGetPCIHostDevice(const virDomainHostdevDef *hostdev, + return -1; + + virPCIDeviceSetManaged(actual, hostdev->managed); ++ virPCIDeviceSetStubDriverName(actual, pcisrc->driver.model); + + if (pcisrc->driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO) { + virPCIDeviceSetStubDriverType(actual, VIR_PCI_STUB_DRIVER_VFIO); +-- +2.43.2 diff --git a/SOURCES/libvirt-build-Make-daemons-depend-on-generated-_protocol.-ch.patch b/SOURCES/libvirt-build-Make-daemons-depend-on-generated-_protocol.-ch.patch new file mode 100644 index 0000000..5e2e48b --- /dev/null +++ b/SOURCES/libvirt-build-Make-daemons-depend-on-generated-_protocol.-ch.patch @@ -0,0 +1,144 @@ +From 5359921ef11b68dab549b6b28ba11a784e6946a5 Mon Sep 17 00:00:00 2001 +Message-ID: <5359921ef11b68dab549b6b28ba11a784e6946a5.1706524416.git.jdenemar@redhat.com> +From: Jiri Denemark +Date: Wed, 24 Jan 2024 19:23:54 +0100 +Subject: [PATCH] build: Make daemons depend on generated *_protocol.[ch] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This should fix build failures when a daemon code is compiled before the +included *_protocol.h headers are ready, such as: + + FAILED: src/virtqemud.p/remote_remote_daemon_config.c.o + ../src/remote/remote_daemon_config.c: In function ‘daemonConfigNew’: + ../src/remote/remote_daemon_config.c:111:30: error: + ‘REMOTE_AUTH_POLKIT’ undeclared (first use in this function) + 111 | data->auth_unix_rw = REMOTE_AUTH_POLKIT; + | ^~~~~~~~~~~~~~~~~~ + ../src/remote/remote_daemon_config.c:111:30: note: each undeclared + identifier is reported only once for each function it appears in + ../src/remote/remote_daemon_config.c:115:30: error: + ‘REMOTE_AUTH_NONE’ undeclared (first use in this function) + 115 | data->auth_unix_rw = REMOTE_AUTH_NONE; + | ^~~~~~~~~~~~~~~~ + ../src/remote/remote_daemon_config.c: In function + ‘daemonConfigLoadOptions’: + ../src/remote/remote_daemon_config.c:252:31: error: + ‘REMOTE_AUTH_POLKIT’ undeclared (first use in this function) + 252 | if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) { + | ^~~~~~~~~~~~~~~~~~ + +or + + FAILED: src/virtqemud.p/remote_remote_daemon_dispatch.c.o + In file included from ../src/remote/remote_daemon.h:28, + from ../src/remote/remote_daemon_dispatch.c:26: + src/remote/lxc_protocol.h:13:5: error: + unknown type name ‘remote_nonnull_domain’ + 13 | remote_nonnull_domain dom; + | ^~~~~~~~~~~~~~~~~~~~~ + In file included from ../src/remote/remote_daemon.h:29, + from ../src/remote/remote_daemon_dispatch.c:26: + src/remote/qemu_protocol.h:13:5: error: + unknown type name ‘remote_nonnull_domain’ + 13 | remote_nonnull_domain dom; + | ^~~~~~~~~~~~~~~~~~~~~ + src/remote/qemu_protocol.h:14:5: error: + unknown type name ‘remote_nonnull_string’ + 14 | remote_nonnull_string cmd; + | ^~~~~~~~~~~~~~~~~~~~~ + ... + +Signed-off-by: Jiri Denemark +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit dcfe548cb01d64e2bdeac456c428e578158232b9) + +https://issues.redhat.com/browse/RHEL-15267 + +Signed-off-by: Jiri Denemark +--- + po/meson.build | 1 + + src/meson.build | 6 +++++- + src/remote/meson.build | 15 +++++++++++---- + 3 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/po/meson.build b/po/meson.build +index a20877ad34..592b254447 100644 +--- a/po/meson.build ++++ b/po/meson.build +@@ -20,6 +20,7 @@ potfiles_dep = [ + access_gen_sources, + admin_client_generated, + admin_driver_generated, ++ remote_protocol_generated, + remote_driver_generated, + remote_daemon_generated, + ] +diff --git a/src/meson.build b/src/meson.build +index 6538c43628..f52d2d5994 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -616,7 +616,11 @@ foreach daemon : virt_daemons + bin = executable( + daemon['name'], + [ +- daemon.get('sources', [ remote_daemon_sources, remote_daemon_generated ]), ++ daemon.get('sources', [ ++ remote_protocol_generated, ++ remote_daemon_sources, ++ remote_daemon_generated ++ ]), + dtrace_gen_objects, + ], + c_args: [ +diff --git a/src/remote/meson.build b/src/remote/meson.build +index 16b903fcaf..43bf2d0083 100644 +--- a/src/remote/meson.build ++++ b/src/remote/meson.build +@@ -7,8 +7,6 @@ remote_driver_generated = [] + + foreach name : [ 'remote', 'qemu', 'lxc' ] + client_bodies_h = '@0@_client_bodies.h'.format(name) +- protocol_c = '@0@_protocol.c'.format(name) +- protocol_h = '@0@_protocol.h'.format(name) + protocol_x = '@0@_protocol.x'.format(name) + + remote_driver_generated += custom_target( +@@ -20,8 +18,16 @@ foreach name : [ 'remote', 'qemu', 'lxc' ] + ], + capture: true, + ) ++endforeach + +- remote_driver_generated += custom_target( ++remote_protocol_generated = [] ++ ++foreach name : [ 'remote', 'qemu', 'lxc' ] ++ protocol_c = '@0@_protocol.c'.format(name) ++ protocol_h = '@0@_protocol.h'.format(name) ++ protocol_x = '@0@_protocol.x'.format(name) ++ ++ remote_protocol_generated += custom_target( + protocol_h, + input: protocol_x, + output: protocol_h, +@@ -32,7 +38,7 @@ foreach name : [ 'remote', 'qemu', 'lxc' ] + ], + ) + +- remote_driver_generated += custom_target( ++ remote_protocol_generated += custom_target( + protocol_c, + input: protocol_x, + output: protocol_c, +@@ -143,6 +149,7 @@ if conf.has('WITH_REMOTE') + remote_driver_lib = static_library( + 'virt_remote_driver', + [ ++ remote_protocol_generated, + remote_driver_sources, + remote_driver_generated, + ], +-- +2.43.0 diff --git a/SOURCES/libvirt-conf-Allow-specifying-CPU-clusters.patch b/SOURCES/libvirt-conf-Allow-specifying-CPU-clusters.patch new file mode 100644 index 0000000..717c077 --- /dev/null +++ b/SOURCES/libvirt-conf-Allow-specifying-CPU-clusters.patch @@ -0,0 +1,976 @@ +From 413d6c8c6490caa5ec5479ab10aa493677cc45c0 Mon Sep 17 00:00:00 2001 +Message-ID: <413d6c8c6490caa5ec5479ab10aa493677cc45c0.1706524416.git.jdenemar@redhat.com> +From: Andrea Bolognani +Date: Fri, 5 Jan 2024 18:20:14 +0100 +Subject: [PATCH] conf: Allow specifying CPU clusters + +The default number of CPU clusters is 1, and values other than +that one are currently rejected by all hypervisor drivers. + +Signed-off-by: Andrea Bolognani +Reviewed-by: Peter Krempa +(cherry picked from commit ef5c397584b1d03a81c74c27074ec4b1a05d3339) + +https://issues.redhat.com/browse/RHEL-7043 + +Signed-off-by: Andrea Bolognani +--- + src/bhyve/bhyve_command.c | 5 +++++ + src/conf/cpu_conf.c | 16 +++++++++++++++- + src/conf/cpu_conf.h | 1 + + src/conf/domain_conf.c | 1 + + src/conf/schemas/cputypes.rng | 5 +++++ + src/cpu/cpu.c | 1 + + src/libxl/libxl_capabilities.c | 1 + + src/qemu/qemu_command.c | 5 +++++ + src/vmx/vmx.c | 7 +++++++ + .../x86_64-host+guest,model486-result.xml | 2 +- + .../x86_64-host+guest,models-result.xml | 2 +- + tests/cputestdata/x86_64-host+guest-result.xml | 2 +- + tests/cputestdata/x86_64-host+guest.xml | 2 +- + .../x86_64-host+host-model-nofallback.xml | 2 +- + ...host-Haswell-noTSX+Haswell,haswell-result.xml | 2 +- + ...aswell-noTSX+Haswell-noTSX,haswell-result.xml | 2 +- + ...4-host-Haswell-noTSX+Haswell-noTSX-result.xml | 2 +- + .../x86_64-host-worse+guest-result.xml | 2 +- + .../ppc64-modern-bulk-result-conf.xml | 2 +- + .../ppc64-modern-bulk-result-live.xml | 2 +- + .../ppc64-modern-individual-result-conf.xml | 2 +- + .../ppc64-modern-individual-result-live.xml | 2 +- + .../x86-modern-bulk-result-conf.xml | 2 +- + .../x86-modern-bulk-result-live.xml | 2 +- + .../x86-modern-individual-add-result-conf.xml | 2 +- + .../x86-modern-individual-add-result-live.xml | 2 +- + ...e-timeout+graphics-spice-timeout-password.xml | 2 +- + .../qemuhotplug-graphics-spice-timeout.xml | 2 +- + .../fd-memory-no-numa-topology.xml | 2 +- + .../qemuxml2argvdata/fd-memory-numa-topology.xml | 2 +- + .../fd-memory-numa-topology2.xml | 2 +- + .../fd-memory-numa-topology3.xml | 2 +- + tests/qemuxml2argvdata/hugepages-nvdimm.xml | 2 +- + .../memfd-memory-default-hugepage.xml | 2 +- + tests/qemuxml2argvdata/memfd-memory-numa.xml | 2 +- + .../memory-hotplug-nvdimm-access.xml | 2 +- + .../memory-hotplug-nvdimm-align.xml | 2 +- + .../memory-hotplug-nvdimm-label.xml | 2 +- + .../memory-hotplug-nvdimm-pmem.xml | 2 +- + .../memory-hotplug-nvdimm-readonly.xml | 2 +- + tests/qemuxml2argvdata/memory-hotplug-nvdimm.xml | 2 +- + .../memory-hotplug-virtio-mem.xml | 2 +- + .../memory-hotplug-virtio-pmem.xml | 2 +- + .../cpu-numa-disjoint.x86_64-latest.xml | 2 +- + .../cpu-numa-disordered.x86_64-latest.xml | 2 +- + .../cpu-numa-memshared.x86_64-latest.xml | 2 +- + .../cpu-numa-no-memory-element.x86_64-latest.xml | 2 +- + .../cpu-numa1.x86_64-latest.xml | 2 +- + .../cpu-numa2.x86_64-latest.xml | 2 +- + .../memory-hotplug-dimm-addr.x86_64-latest.xml | 2 +- + .../memory-hotplug-dimm.x86_64-latest.xml | 2 +- + .../memory-hotplug-multiple.x86_64-latest.xml | 2 +- + ...plug-nvdimm-ppc64-abi-update.ppc64-latest.xml | 2 +- + .../memory-hotplug-nvdimm-ppc64.ppc64-latest.xml | 2 +- + .../memory-hotplug.x86_64-latest.xml | 2 +- + ...mad-auto-memory-vcpu-cpuset.x86_64-latest.xml | 2 +- + ...cpu-no-cpuset-and-placement.x86_64-latest.xml | 2 +- + ...numad-auto-vcpu-no-numatune.x86_64-latest.xml | 2 +- + ...mad-static-vcpu-no-numatune.x86_64-latest.xml | 2 +- + .../pci-expander-bus.x86_64-latest.xml | 2 +- + .../pcie-expander-bus.x86_64-latest.xml | 2 +- + .../pseries-phb-numa-node.ppc64-latest.xml | 2 +- + tests/vmx2xmldata/esx-in-the-wild-10.xml | 2 +- + tests/vmx2xmldata/esx-in-the-wild-8.xml | 2 +- + tests/vmx2xmldata/esx-in-the-wild-9.xml | 2 +- + 65 files changed, 97 insertions(+), 57 deletions(-) + +diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c +index 5b388c7a8f..d05b01ae5d 100644 +--- a/src/bhyve/bhyve_command.c ++++ b/src/bhyve/bhyve_command.c +@@ -672,6 +672,11 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def, + _("Only 1 die per socket is supported")); + return NULL; + } ++ if (def->cpu->clusters != 1) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Only 1 cluster per die is supported")); ++ return NULL; ++ } + if (nvcpus != def->cpu->sockets * def->cpu->cores * def->cpu->threads) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid CPU topology: total number of vCPUs must equal the product of sockets, cores, and threads")); +diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c +index 7abe489733..6e6e1b9a89 100644 +--- a/src/conf/cpu_conf.c ++++ b/src/conf/cpu_conf.c +@@ -241,6 +241,7 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) + copy->fallback = cpu->fallback; + copy->sockets = cpu->sockets; + copy->dies = cpu->dies; ++ copy->clusters = cpu->clusters; + copy->cores = cpu->cores; + copy->threads = cpu->threads; + copy->arch = cpu->arch; +@@ -572,6 +573,12 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, + return -1; + } + ++ if (virXMLPropUIntDefault(topology, "clusters", 10, ++ VIR_XML_PROP_NONZERO, ++ &def->clusters, 1) < 0) { ++ return -1; ++ } ++ + if (virXMLPropUInt(topology, "cores", 10, + VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, + &def->cores) < 0) { +@@ -827,10 +834,11 @@ virCPUDefFormatBuf(virBuffer *buf, + virBufferAddLit(buf, "/>\n"); + } + +- if (def->sockets && def->dies && def->cores && def->threads) { ++ if (def->sockets && def->dies && def->clusters && def->cores && def->threads) { + virBufferAddLit(buf, "sockets); + virBufferAsprintf(buf, " dies='%u'", def->dies); ++ virBufferAsprintf(buf, " clusters='%u'", def->clusters); + virBufferAsprintf(buf, " cores='%u'", def->cores); + virBufferAsprintf(buf, " threads='%u'", def->threads); + virBufferAddLit(buf, "/>\n"); +@@ -1106,6 +1114,12 @@ virCPUDefIsEqual(virCPUDef *src, + return false; + } + ++ if (src->clusters != dst->clusters) { ++ MISMATCH(_("Target CPU clusters %1$d does not match source %2$d"), ++ dst->clusters, src->clusters); ++ return false; ++ } ++ + if (src->cores != dst->cores) { + MISMATCH(_("Target CPU cores %1$d does not match source %2$d"), + dst->cores, src->cores); +diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h +index 3e4c53675c..2694022fed 100644 +--- a/src/conf/cpu_conf.h ++++ b/src/conf/cpu_conf.h +@@ -148,6 +148,7 @@ struct _virCPUDef { + unsigned int microcodeVersion; + unsigned int sockets; + unsigned int dies; ++ unsigned int clusters; + unsigned int cores; + unsigned int threads; + unsigned int sigFamily; +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 5d55d2acda..6211d2a51b 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -2316,6 +2316,7 @@ virDomainDefGetVcpusTopology(const virDomainDef *def, + + /* multiplication of 32bit numbers fits into a 64bit variable */ + if ((tmp *= def->cpu->dies) > UINT_MAX || ++ (tmp *= def->cpu->clusters) > UINT_MAX || + (tmp *= def->cpu->cores) > UINT_MAX || + (tmp *= def->cpu->threads) > UINT_MAX) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, +diff --git a/src/conf/schemas/cputypes.rng b/src/conf/schemas/cputypes.rng +index db1aa57158..3a8910e09f 100644 +--- a/src/conf/schemas/cputypes.rng ++++ b/src/conf/schemas/cputypes.rng +@@ -92,6 +92,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c +index bc43aa4e93..4f048d0dad 100644 +--- a/src/cpu/cpu.c ++++ b/src/cpu/cpu.c +@@ -435,6 +435,7 @@ virCPUGetHost(virArch arch, + if (nodeInfo) { + cpu->sockets = nodeInfo->sockets; + cpu->dies = 1; ++ cpu->clusters = 1; + cpu->cores = nodeInfo->cores; + cpu->threads = nodeInfo->threads; + } +diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c +index dfb602ca2f..522256777d 100644 +--- a/src/libxl/libxl_capabilities.c ++++ b/src/libxl/libxl_capabilities.c +@@ -152,6 +152,7 @@ libxlCapsInitCPU(virCaps *caps, libxl_physinfo *phy_info) + cpu->cores = phy_info->cores_per_socket; + cpu->threads = phy_info->threads_per_core; + cpu->dies = 1; ++ cpu->clusters = 1; + cpu->sockets = phy_info->nr_cpus / (cpu->cores * cpu->threads); + + if (!(data = libxlCapsNodeData(cpu, phy_info->hw_cap)) || +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index 653817173b..71daa85e55 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -7226,6 +7226,11 @@ qemuBuildSmpCommandLine(virCommand *cmd, + _("Only 1 die per socket is supported")); + return -1; + } ++ if (def->cpu->clusters != 1) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Only 1 cluster per die is supported")); ++ return -1; ++ } + virBufferAsprintf(&buf, ",sockets=%u", def->cpu->sockets); + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SMP_DIES)) + virBufferAsprintf(&buf, ",dies=%u", def->cpu->dies); +diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c +index 26b89776e1..4ac2320251 100644 +--- a/src/vmx/vmx.c ++++ b/src/vmx/vmx.c +@@ -1583,6 +1583,7 @@ virVMXParseConfig(virVMXContext *ctx, + goto cleanup; + } + cpu->dies = 1; ++ cpu->clusters = 1; + cpu->cores = coresPerSocket; + cpu->threads = 1; + +@@ -3377,6 +3378,12 @@ virVMXFormatConfig(virVMXContext *ctx, virDomainXMLOption *xmlopt, virDomainDef + goto cleanup; + } + ++ if (def->cpu->clusters != 1) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Only 1 cluster per die is supported")); ++ goto cleanup; ++ } ++ + calculated_vcpus = def->cpu->sockets * def->cpu->cores; + if (calculated_vcpus != maxvcpus) { + virReportError(VIR_ERR_INTERNAL_ERROR, +diff --git a/tests/cputestdata/x86_64-host+guest,model486-result.xml b/tests/cputestdata/x86_64-host+guest,model486-result.xml +index ea8e2d3a48..b533f22b88 100644 +--- a/tests/cputestdata/x86_64-host+guest,model486-result.xml ++++ b/tests/cputestdata/x86_64-host+guest,model486-result.xml +@@ -1,6 +1,6 @@ + + 486 +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host+guest,models-result.xml b/tests/cputestdata/x86_64-host+guest,models-result.xml +index 42664a48b4..e975d9bc18 100644 +--- a/tests/cputestdata/x86_64-host+guest,models-result.xml ++++ b/tests/cputestdata/x86_64-host+guest,models-result.xml +@@ -1,6 +1,6 @@ + + qemu64 +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host+guest-result.xml b/tests/cputestdata/x86_64-host+guest-result.xml +index 28e3152cbf..cf41b3f872 100644 +--- a/tests/cputestdata/x86_64-host+guest-result.xml ++++ b/tests/cputestdata/x86_64-host+guest-result.xml +@@ -1,6 +1,6 @@ + + Penryn +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host+guest.xml b/tests/cputestdata/x86_64-host+guest.xml +index 28e3152cbf..cf41b3f872 100644 +--- a/tests/cputestdata/x86_64-host+guest.xml ++++ b/tests/cputestdata/x86_64-host+guest.xml +@@ -1,6 +1,6 @@ + + Penryn +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host+host-model-nofallback.xml b/tests/cputestdata/x86_64-host+host-model-nofallback.xml +index 16d6e1daf2..881eea7bd0 100644 +--- a/tests/cputestdata/x86_64-host+host-model-nofallback.xml ++++ b/tests/cputestdata/x86_64-host+host-model-nofallback.xml +@@ -1,7 +1,7 @@ + + Penryn + Intel +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell,haswell-result.xml b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell,haswell-result.xml +index 8eda6684a0..67994c62cc 100644 +--- a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell,haswell-result.xml ++++ b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell,haswell-result.xml +@@ -1,6 +1,6 @@ + + Haswell +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX,haswell-result.xml b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX,haswell-result.xml +index cb02449d60..4804c0b818 100644 +--- a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX,haswell-result.xml ++++ b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX,haswell-result.xml +@@ -1,6 +1,6 @@ + + Haswell +- ++ + + + +diff --git a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX-result.xml b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX-result.xml +index 7ee926aba8..c21b331248 100644 +--- a/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX-result.xml ++++ b/tests/cputestdata/x86_64-host-Haswell-noTSX+Haswell-noTSX-result.xml +@@ -1,4 +1,4 @@ + + Haswell-noTSX +- ++ + +diff --git a/tests/cputestdata/x86_64-host-worse+guest-result.xml b/tests/cputestdata/x86_64-host-worse+guest-result.xml +index 9d54c66a8f..712c3ad341 100644 +--- a/tests/cputestdata/x86_64-host-worse+guest-result.xml ++++ b/tests/cputestdata/x86_64-host-worse+guest-result.xml +@@ -1,6 +1,6 @@ + + Penryn +- ++ + + + +diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-conf.xml b/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-conf.xml +index ad11b2f8a6..1a0d28257e 100644 +--- a/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-conf.xml ++++ b/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-conf.xml +@@ -44,7 +44,7 @@ + + + POWER9 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-live.xml b/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-live.xml +index 2a3b4a495f..b127883b36 100644 +--- a/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-live.xml ++++ b/tests/qemuhotplugtestcpus/ppc64-modern-bulk-result-live.xml +@@ -44,7 +44,7 @@ + + + POWER9 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-conf.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-conf.xml +index 34aec9b965..29f1a5ac45 100644 +--- a/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-conf.xml ++++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-conf.xml +@@ -44,7 +44,7 @@ + + + POWER9 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-live.xml b/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-live.xml +index 5ce2cfd0b0..76a85ac9f0 100644 +--- a/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-live.xml ++++ b/tests/qemuhotplugtestcpus/ppc64-modern-individual-result-live.xml +@@ -44,7 +44,7 @@ + + + POWER9 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-result-conf.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-result-conf.xml +index 8d52ffedb4..bec46987ff 100644 +--- a/tests/qemuhotplugtestcpus/x86-modern-bulk-result-conf.xml ++++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-result-conf.xml +@@ -20,7 +20,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/x86-modern-bulk-result-live.xml b/tests/qemuhotplugtestcpus/x86-modern-bulk-result-live.xml +index f416397e33..be9769c686 100644 +--- a/tests/qemuhotplugtestcpus/x86-modern-bulk-result-live.xml ++++ b/tests/qemuhotplugtestcpus/x86-modern-bulk-result-live.xml +@@ -20,7 +20,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-conf.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-conf.xml +index 0bd2af8e43..539f607818 100644 +--- a/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-conf.xml ++++ b/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-conf.xml +@@ -20,7 +20,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-live.xml b/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-live.xml +index b31e6ebe55..acbdd3cfd5 100644 +--- a/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-live.xml ++++ b/tests/qemuhotplugtestcpus/x86-modern-individual-add-result-live.xml +@@ -20,7 +20,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout+graphics-spice-timeout-password.xml b/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout+graphics-spice-timeout-password.xml +index 03964ad01c..ee53339338 100644 +--- a/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout+graphics-spice-timeout-password.xml ++++ b/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout+graphics-spice-timeout-password.xml +@@ -18,7 +18,7 @@ + + core2duo + Intel +- ++ + + + +diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout.xml b/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout.xml +index e6b0cc833a..eb9b902fc5 100644 +--- a/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout.xml ++++ b/tests/qemuhotplugtestdomains/qemuhotplug-graphics-spice-timeout.xml +@@ -18,7 +18,7 @@ + + core2duo + Intel +- ++ + + + +diff --git a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.xml b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.xml +index 2090bb8288..92f418fb88 100644 +--- a/tests/qemuxml2argvdata/fd-memory-no-numa-topology.xml ++++ b/tests/qemuxml2argvdata/fd-memory-no-numa-topology.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuxml2argvdata/fd-memory-numa-topology.xml b/tests/qemuxml2argvdata/fd-memory-numa-topology.xml +index 2f94690656..543509d832 100644 +--- a/tests/qemuxml2argvdata/fd-memory-numa-topology.xml ++++ b/tests/qemuxml2argvdata/fd-memory-numa-topology.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/fd-memory-numa-topology2.xml b/tests/qemuxml2argvdata/fd-memory-numa-topology2.xml +index 3a4e9b478e..d3b98da3c6 100644 +--- a/tests/qemuxml2argvdata/fd-memory-numa-topology2.xml ++++ b/tests/qemuxml2argvdata/fd-memory-numa-topology2.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/fd-memory-numa-topology3.xml b/tests/qemuxml2argvdata/fd-memory-numa-topology3.xml +index 0f7f74283b..459d1b9d1d 100644 +--- a/tests/qemuxml2argvdata/fd-memory-numa-topology3.xml ++++ b/tests/qemuxml2argvdata/fd-memory-numa-topology3.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/hugepages-nvdimm.xml b/tests/qemuxml2argvdata/hugepages-nvdimm.xml +index 1a1500895b..b786b0d3dd 100644 +--- a/tests/qemuxml2argvdata/hugepages-nvdimm.xml ++++ b/tests/qemuxml2argvdata/hugepages-nvdimm.xml +@@ -17,7 +17,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memfd-memory-default-hugepage.xml b/tests/qemuxml2argvdata/memfd-memory-default-hugepage.xml +index 238d4c6b52..a70bd53134 100644 +--- a/tests/qemuxml2argvdata/memfd-memory-default-hugepage.xml ++++ b/tests/qemuxml2argvdata/memfd-memory-default-hugepage.xml +@@ -19,7 +19,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memfd-memory-numa.xml b/tests/qemuxml2argvdata/memfd-memory-numa.xml +index 1ac87e3aef..0c5d7ba4ef 100644 +--- a/tests/qemuxml2argvdata/memfd-memory-numa.xml ++++ b/tests/qemuxml2argvdata/memfd-memory-numa.xml +@@ -22,7 +22,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-access.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-access.xml +index bee0346aca..84baf82bf5 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-access.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-access.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-align.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-align.xml +index decf87db63..664418e805 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-align.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-align.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-label.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-label.xml +index 8a0dab3908..f998f7f276 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-label.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-label.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-pmem.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-pmem.xml +index a712adfe1e..d66481fd35 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-pmem.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-pmem.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-readonly.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-readonly.xml +index 57629ccb8c..56d6b7b712 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-readonly.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-readonly.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm.xml b/tests/qemuxml2argvdata/memory-hotplug-nvdimm.xml +index 865ddcf0ea..ff6e3b7b0f 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml +index c578209d8a..52fa6b14e9 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml +@@ -11,7 +11,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-pmem.xml b/tests/qemuxml2argvdata/memory-hotplug-virtio-pmem.xml +index a8b22dd3c5..2786a739ad 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-virtio-pmem.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-pmem.xml +@@ -11,7 +11,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa-disjoint.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa-disjoint.x86_64-latest.xml +index fa2ec31463..4f33094949 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa-disjoint.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa-disjoint.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa-disordered.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa-disordered.x86_64-latest.xml +index 1b4d0bfa67..75dcb8c9e2 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa-disordered.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa-disordered.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa-memshared.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa-memshared.x86_64-latest.xml +index 47ed9efd69..c45e295921 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa-memshared.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa-memshared.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa-no-memory-element.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa-no-memory-element.x86_64-latest.xml +index 57bbacdff0..663d137ff5 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa-no-memory-element.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa-no-memory-element.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa1.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa1.x86_64-latest.xml +index 57bbacdff0..663d137ff5 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa1.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa1.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/cpu-numa2.x86_64-latest.xml b/tests/qemuxml2xmloutdata/cpu-numa2.x86_64-latest.xml +index 57bbacdff0..663d137ff5 100644 +--- a/tests/qemuxml2xmloutdata/cpu-numa2.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/cpu-numa2.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-dimm-addr.x86_64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-dimm-addr.x86_64-latest.xml +index 0a32d5491a..38b41e6719 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug-dimm-addr.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug-dimm-addr.x86_64-latest.xml +@@ -11,7 +11,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-dimm.x86_64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-dimm.x86_64-latest.xml +index 7c1b7b2c5d..7f0dc85c0e 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug-dimm.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug-dimm.x86_64-latest.xml +@@ -15,7 +15,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-multiple.x86_64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-multiple.x86_64-latest.xml +index 42b0f7b880..b3306fb569 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug-multiple.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug-multiple.x86_64-latest.xml +@@ -11,7 +11,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64-abi-update.ppc64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64-abi-update.ppc64-latest.xml +index ae157c4849..4cc0c674df 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64-abi-update.ppc64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64-abi-update.ppc64-latest.xml +@@ -11,7 +11,7 @@ + + + POWER9 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.ppc64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.ppc64-latest.xml +index 3c1cbc731d..a5c26e3c5b 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.ppc64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.ppc64-latest.xml +@@ -11,7 +11,7 @@ + + + POWER9 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/memory-hotplug.x86_64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug.x86_64-latest.xml +index 083102e8d6..697819387f 100644 +--- a/tests/qemuxml2xmloutdata/memory-hotplug.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/memory-hotplug.x86_64-latest.xml +@@ -11,7 +11,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-cpuset.x86_64-latest.xml b/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-cpuset.x86_64-latest.xml +index 2d04bc23c2..6068a76464 100644 +--- a/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-cpuset.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-cpuset.x86_64-latest.xml +@@ -13,7 +13,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-no-cpuset-and-placement.x86_64-latest.xml b/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-no-cpuset-and-placement.x86_64-latest.xml +index 80f7284126..6c558526e9 100644 +--- a/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-no-cpuset-and-placement.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/numad-auto-memory-vcpu-no-cpuset-and-placement.x86_64-latest.xml +@@ -13,7 +13,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuxml2xmloutdata/numad-auto-vcpu-no-numatune.x86_64-latest.xml b/tests/qemuxml2xmloutdata/numad-auto-vcpu-no-numatune.x86_64-latest.xml +index 724209f6e3..6e1fecb488 100644 +--- a/tests/qemuxml2xmloutdata/numad-auto-vcpu-no-numatune.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/numad-auto-vcpu-no-numatune.x86_64-latest.xml +@@ -13,7 +13,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuxml2xmloutdata/numad-static-vcpu-no-numatune.x86_64-latest.xml b/tests/qemuxml2xmloutdata/numad-static-vcpu-no-numatune.x86_64-latest.xml +index 2a4ee0d496..c42d7066f9 100644 +--- a/tests/qemuxml2xmloutdata/numad-static-vcpu-no-numatune.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/numad-static-vcpu-no-numatune.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + destroy +diff --git a/tests/qemuxml2xmloutdata/pci-expander-bus.x86_64-latest.xml b/tests/qemuxml2xmloutdata/pci-expander-bus.x86_64-latest.xml +index b63c8c145a..2a6c329a40 100644 +--- a/tests/qemuxml2xmloutdata/pci-expander-bus.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/pci-expander-bus.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/pcie-expander-bus.x86_64-latest.xml b/tests/qemuxml2xmloutdata/pcie-expander-bus.x86_64-latest.xml +index a441be8ebe..99612740b2 100644 +--- a/tests/qemuxml2xmloutdata/pcie-expander-bus.x86_64-latest.xml ++++ b/tests/qemuxml2xmloutdata/pcie-expander-bus.x86_64-latest.xml +@@ -10,7 +10,7 @@ + + + qemu64 +- ++ + + + +diff --git a/tests/qemuxml2xmloutdata/pseries-phb-numa-node.ppc64-latest.xml b/tests/qemuxml2xmloutdata/pseries-phb-numa-node.ppc64-latest.xml +index 59015846fb..0a044f50b0 100644 +--- a/tests/qemuxml2xmloutdata/pseries-phb-numa-node.ppc64-latest.xml ++++ b/tests/qemuxml2xmloutdata/pseries-phb-numa-node.ppc64-latest.xml +@@ -14,7 +14,7 @@ + + + POWER9 +- ++ + + + +diff --git a/tests/vmx2xmldata/esx-in-the-wild-10.xml b/tests/vmx2xmldata/esx-in-the-wild-10.xml +index 47ed637920..78129682bd 100644 +--- a/tests/vmx2xmldata/esx-in-the-wild-10.xml ++++ b/tests/vmx2xmldata/esx-in-the-wild-10.xml +@@ -12,7 +12,7 @@ + hvm + + +- ++ + + + destroy +diff --git a/tests/vmx2xmldata/esx-in-the-wild-8.xml b/tests/vmx2xmldata/esx-in-the-wild-8.xml +index 0eea610709..47d22ced2a 100644 +--- a/tests/vmx2xmldata/esx-in-the-wild-8.xml ++++ b/tests/vmx2xmldata/esx-in-the-wild-8.xml +@@ -11,7 +11,7 @@ + hvm + + +- ++ + + + destroy +diff --git a/tests/vmx2xmldata/esx-in-the-wild-9.xml b/tests/vmx2xmldata/esx-in-the-wild-9.xml +index 66eca400dd..ee6be2527f 100644 +--- a/tests/vmx2xmldata/esx-in-the-wild-9.xml ++++ b/tests/vmx2xmldata/esx-in-the-wild-9.xml +@@ -12,7 +12,7 @@ + hvm + + +- ++ + + + destroy +-- +2.43.0 diff --git a/SOURCES/libvirt-conf-Introduce-dynamicMemslots-attribute-for-virtio-mem.patch b/SOURCES/libvirt-conf-Introduce-dynamicMemslots-attribute-for-virtio-mem.patch new file mode 100644 index 0000000..1ae2cc8 --- /dev/null +++ b/SOURCES/libvirt-conf-Introduce-dynamicMemslots-attribute-for-virtio-mem.patch @@ -0,0 +1,152 @@ +From de94232ffb9eef84bb72631979f59bbadfc3cb9e Mon Sep 17 00:00:00 2001 +Message-ID: +From: Michal Privoznik +Date: Thu, 4 Jan 2024 10:03:36 +0100 +Subject: [PATCH] conf: Introduce dynamicMemslots attribute for virtio-mem + +Introduced in v8.2.0-rc0~74^2~2, QEMU now allows setting +.dynamic-memslots attribute for virtio-mem-pci devices. When +turned on, it allows memory exposed to guest to be split into +multiple memslots and thus smaller memory footprint (see the +original commit for detailed explanation). + +Therefore, introduce new attribute which will control +that QEMU knob. + +Signed-off-by: Michal Privoznik +Reviewed-by: Peter Krempa +(cherry picked from commit 53258205854e649bc82310542373df004a4734ab) +Resolves: https://issues.redhat.com/browse/RHEL-15316 +Signed-off-by: Michal Privoznik +--- + docs/formatdomain.rst | 13 +++++++++++++ + src/conf/domain_conf.c | 18 +++++++++++++++++- + src/conf/domain_conf.h | 1 + + src/conf/schemas/domaincommon.rng | 5 +++++ + .../memory-hotplug-virtio-mem.xml | 2 +- + 5 files changed, 37 insertions(+), 2 deletions(-) + +diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst +index 298ad46a45..34b2564909 100644 +--- a/docs/formatdomain.rst ++++ b/docs/formatdomain.rst +@@ -8437,6 +8437,19 @@ Example: usage of the memory devices + The ``node`` subelement configures the guest NUMA node to attach the memory + to. The element shall be used only if the guest has NUMA nodes configured. + ++ For ``virtio-mem`` optional attribute ``dynamicMemslots`` can be specified ++ (accepted values "yes"/"no") which allows hypervisor to spread memory into ++ multiple memory slots (allocate them dynamically based on the amount of ++ memory exposed to the guest), resulting in smaller memory footprint. But be ++ aware this may affect vhost-user devices. When enabled, older vhost-user ++ device implementations (such as virtiofs) may refuse to initialize resulting ++ in failed domain startup or device hotplug. When only modern vhost-user ++ based devices will be used or when no vhost-user devices are expected to be ++ used it's beneficial to enable this feature. The current default is ++ hypervisor dependant (for QEMU is "no"). If the default changes and you are ++ having difficulties with vhost-user devices, try toggling this to "no". ++ :since:`Since 10.1.0 and QEMU 8.2.0` ++ + The following optional elements may be used: + + ``label`` +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 6211d2a51b..ac06fa39f6 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -13543,6 +13543,10 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, + &def->target.virtio_mem.requestedsize, false, false) < 0) + return -1; + ++ if (virXMLPropTristateBool(node, "dynamicMemslots", VIR_XML_PROP_NONE, ++ &def->target.virtio_mem.dynamicMemslots) < 0) ++ return -1; ++ + addrNode = virXPathNode("./address", ctxt); + addr = &def->target.virtio_mem.address; + break; +@@ -21217,6 +21221,12 @@ virDomainMemoryDefCheckABIStability(virDomainMemoryDef *src, + src->target.virtio_mem.address); + return false; + } ++ ++ if (src->target.virtio_mem.dynamicMemslots != dst->target.virtio_mem.dynamicMemslots) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Target memory device 'dynamicMemslots' property doesn't match source memory device")); ++ return false; ++ } + break; + + case VIR_DOMAIN_MEMORY_MODEL_DIMM: +@@ -25432,6 +25442,7 @@ virDomainMemoryTargetDefFormat(virBuffer *buf, + unsigned int flags) + { + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); ++ g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&childBuf, "%llu\n", def->size); + if (def->targetNode >= 0) +@@ -25471,6 +25482,11 @@ virDomainMemoryTargetDefFormat(virBuffer *buf, + if (def->target.virtio_mem.address) + virBufferAsprintf(&childBuf, "
\n", + def->target.virtio_mem.address); ++ ++ if (def->target.virtio_mem.dynamicMemslots) { ++ virBufferAsprintf(&attrBuf, " dynamicMemslots='%s'", ++ virTristateBoolTypeToString(def->target.virtio_mem.dynamicMemslots)); ++ } + break; + + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: +@@ -25480,7 +25496,7 @@ virDomainMemoryTargetDefFormat(virBuffer *buf, + break; + } + +- virXMLFormatElement(buf, "target", NULL, &childBuf); ++ virXMLFormatElement(buf, "target", &attrBuf, &childBuf); + } + + static int +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index d176bda5f8..bd283d42df 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2676,6 +2676,7 @@ struct _virDomainMemoryDef { + unsigned long long currentsize; /* kibibytes, valid for an active + domain only and parsed */ + unsigned long long address; /* address where memory is mapped */ ++ virTristateBool dynamicMemslots; + } virtio_mem; + struct { + } sgx_epc; +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index a34427c330..df44cd9857 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -7268,6 +7268,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml +index 52fa6b14e9..20282a131b 100644 +--- a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml ++++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml +@@ -60,7 +60,7 @@ + 1-3 + 2048 + +- ++ + 2097152 + 0 + 2048 +-- +2.43.0 diff --git a/SOURCES/libvirt-conf-Report-CPU-clusters-in-capabilities-XML.patch b/SOURCES/libvirt-conf-Report-CPU-clusters-in-capabilities-XML.patch new file mode 100644 index 0000000..ee181de --- /dev/null +++ b/SOURCES/libvirt-conf-Report-CPU-clusters-in-capabilities-XML.patch @@ -0,0 +1,684 @@ +From 130768f856aef1a4fa09a4654fd5ddcaad985795 Mon Sep 17 00:00:00 2001 +Message-ID: <130768f856aef1a4fa09a4654fd5ddcaad985795.1706524416.git.jdenemar@redhat.com> +From: Andrea Bolognani +Date: Fri, 5 Jan 2024 16:03:54 +0100 +Subject: [PATCH] conf: Report CPU clusters in capabilities XML + +For machines that don't expose useful information through sysfs, +the dummy ID 0 is used. + +https://issues.redhat.com/browse/RHEL-7043 + +Signed-off-by: Andrea Bolognani +Reviewed-by: Peter Krempa +(cherry picked from commit 5fc56aefb67a085a2f0fd3d2a157c7c029d2ef60) + +https://issues.redhat.com/browse/RHEL-7043 + +Signed-off-by: Andrea Bolognani +--- + src/conf/capabilities.c | 5 +- + src/conf/capabilities.h | 1 + + src/conf/schemas/capability.rng | 3 ++ + src/libvirt_linux.syms | 1 + + src/util/virhostcpu.c | 22 +++++++++ + src/util/virhostcpu.h | 1 + + tests/capabilityschemadata/caps-qemu-kvm.xml | 32 ++++++------- + .../vircaps-aarch64-basic-clusters.xml | 16 +++---- + .../vircaps2xmldata/vircaps-aarch64-basic.xml | 32 ++++++------- + .../vircaps-x86_64-basic-dies.xml | 24 +++++----- + .../vircaps2xmldata/vircaps-x86_64-basic.xml | 32 ++++++------- + .../vircaps2xmldata/vircaps-x86_64-caches.xml | 16 +++---- + tests/vircaps2xmldata/vircaps-x86_64-hmat.xml | 48 +++++++++---------- + .../vircaps-x86_64-resctrl-cdp.xml | 24 +++++----- + .../vircaps-x86_64-resctrl-cmt.xml | 24 +++++----- + .../vircaps-x86_64-resctrl-fake-feature.xml | 24 +++++----- + .../vircaps-x86_64-resctrl-skx-twocaches.xml | 2 +- + .../vircaps-x86_64-resctrl-skx.xml | 2 +- + .../vircaps-x86_64-resctrl.xml | 24 +++++----- + 19 files changed, 182 insertions(+), 151 deletions(-) + +diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c +index 32badee7b3..02298e40a3 100644 +--- a/src/conf/capabilities.c ++++ b/src/conf/capabilities.c +@@ -811,9 +811,10 @@ virCapsHostNUMACellCPUFormat(virBuffer *buf, + return -1; + + virBufferAsprintf(&childBuf, +- " socket_id='%d' die_id='%d' core_id='%d' siblings='%s'", ++ " socket_id='%d' die_id='%d' cluster_id='%d' core_id='%d' siblings='%s'", + cpus[j].socket_id, + cpus[j].die_id, ++ cpus[j].cluster_id, + cpus[j].core_id, + siblings); + } +@@ -1453,6 +1454,7 @@ virCapabilitiesFillCPUInfo(int cpu_id G_GNUC_UNUSED, + + if (virHostCPUGetSocket(cpu_id, &cpu->socket_id) < 0 || + virHostCPUGetDie(cpu_id, &cpu->die_id) < 0 || ++ virHostCPUGetCluster(cpu_id, &cpu->cluster_id) < 0 || + virHostCPUGetCore(cpu_id, &cpu->core_id) < 0) + return -1; + +@@ -1712,6 +1714,7 @@ virCapabilitiesHostNUMAInitFake(virCapsHostNUMA *caps) + if (tmp) { + cpus[cid].id = id; + cpus[cid].die_id = 0; ++ cpus[cid].cluster_id = 0; + cpus[cid].socket_id = s; + cpus[cid].core_id = c; + cpus[cid].siblings = virBitmapNewCopy(siblings); +diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h +index 9eaf6e2807..52e395de14 100644 +--- a/src/conf/capabilities.h ++++ b/src/conf/capabilities.h +@@ -89,6 +89,7 @@ struct _virCapsHostNUMACellCPU { + unsigned int id; + unsigned int socket_id; + unsigned int die_id; ++ unsigned int cluster_id; + unsigned int core_id; + virBitmap *siblings; + }; +diff --git a/src/conf/schemas/capability.rng b/src/conf/schemas/capability.rng +index b1968df258..a1606941e7 100644 +--- a/src/conf/schemas/capability.rng ++++ b/src/conf/schemas/capability.rng +@@ -201,6 +201,9 @@ + + + ++ ++ ++ + + + +diff --git a/src/libvirt_linux.syms b/src/libvirt_linux.syms +index 55649ae39c..004cbfee97 100644 +--- a/src/libvirt_linux.syms ++++ b/src/libvirt_linux.syms +@@ -3,6 +3,7 @@ + # + + # util/virhostcpu.h ++virHostCPUGetCluster; + virHostCPUGetCore; + virHostCPUGetDie; + virHostCPUGetInfoPopulateLinux; +diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c +index 4027547e1e..a3781ca870 100644 +--- a/src/util/virhostcpu.c ++++ b/src/util/virhostcpu.c +@@ -232,6 +232,28 @@ virHostCPUGetDie(unsigned int cpu, unsigned int *die) + return 0; + } + ++int ++virHostCPUGetCluster(unsigned int cpu, unsigned int *cluster) ++{ ++ int cluster_id; ++ int ret = virFileReadValueInt(&cluster_id, ++ "%s/cpu/cpu%u/topology/cluster_id", ++ SYSFS_SYSTEM_PATH, cpu); ++ ++ if (ret == -1) ++ return -1; ++ ++ /* If the file doesn't exists (old kernel) or the value contained ++ * in it is -1 (architecture without CPU clusters), report 0 to ++ * indicate the lack of information */ ++ if (ret == -2 || cluster_id < 0) ++ cluster_id = 0; ++ ++ *cluster = cluster_id; ++ ++ return 0; ++} ++ + int + virHostCPUGetCore(unsigned int cpu, unsigned int *core) + { +diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h +index 5f0d43e069..d7e09bff22 100644 +--- a/src/util/virhostcpu.h ++++ b/src/util/virhostcpu.h +@@ -68,6 +68,7 @@ int virHostCPUStatsAssign(virNodeCPUStatsPtr param, + #ifdef __linux__ + int virHostCPUGetSocket(unsigned int cpu, unsigned int *socket); + int virHostCPUGetDie(unsigned int cpu, unsigned int *die); ++int virHostCPUGetCluster(unsigned int cpu, unsigned int *cluster); + int virHostCPUGetCore(unsigned int cpu, unsigned int *core); + + virBitmap *virHostCPUGetSiblingsList(unsigned int cpu); +diff --git a/tests/capabilityschemadata/caps-qemu-kvm.xml b/tests/capabilityschemadata/caps-qemu-kvm.xml +index acdbb362cc..317fa0885f 100644 +--- a/tests/capabilityschemadata/caps-qemu-kvm.xml ++++ b/tests/capabilityschemadata/caps-qemu-kvm.xml +@@ -64,14 +64,14 @@ + + + +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ + + + +@@ -84,14 +84,14 @@ + + + +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-aarch64-basic-clusters.xml b/tests/vircaps2xmldata/vircaps-aarch64-basic-clusters.xml +index fe61fc42cc..b37c8e7a20 100644 +--- a/tests/vircaps2xmldata/vircaps-aarch64-basic-clusters.xml ++++ b/tests/vircaps2xmldata/vircaps-aarch64-basic-clusters.xml +@@ -14,10 +14,10 @@ + 4096 + 6144 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -26,10 +26,10 @@ + 6144 + 8192 + +- +- +- +- ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-aarch64-basic.xml b/tests/vircaps2xmldata/vircaps-aarch64-basic.xml +index 0a04052c40..5533ae0586 100644 +--- a/tests/vircaps2xmldata/vircaps-aarch64-basic.xml ++++ b/tests/vircaps2xmldata/vircaps-aarch64-basic.xml +@@ -16,10 +16,10 @@ + 4096 + 6144 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -28,10 +28,10 @@ + 6144 + 8192 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -40,10 +40,10 @@ + 8192 + 10240 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -52,10 +52,10 @@ + 10240 + 12288 + +- +- +- +- ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-basic-dies.xml b/tests/vircaps2xmldata/vircaps-x86_64-basic-dies.xml +index 8a3ca2d13c..c86dc4defc 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-basic-dies.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-basic-dies.xml +@@ -14,18 +14,18 @@ + 4096 + 6144 + +- +- +- +- +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-basic.xml b/tests/vircaps2xmldata/vircaps-x86_64-basic.xml +index 4da09f889c..9ae155d571 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-basic.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-basic.xml +@@ -14,10 +14,10 @@ + 4096 + 6144 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -26,10 +26,10 @@ + 6144 + 8192 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -38,10 +38,10 @@ + 8192 + 10240 + +- +- +- +- ++ ++ ++ ++ + + + +@@ -50,10 +50,10 @@ + 10240 + 12288 + +- +- +- +- ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-caches.xml b/tests/vircaps2xmldata/vircaps-x86_64-caches.xml +index 28f00c0a90..05b33147b7 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-caches.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-caches.xml +@@ -17,14 +17,14 @@ + 4096 + 6144 + +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-hmat.xml b/tests/vircaps2xmldata/vircaps-x86_64-hmat.xml +index 6fe5751666..2b97354bf3 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-hmat.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-hmat.xml +@@ -25,30 +25,30 @@ + + + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml +index ee26fe9464..167b217d8e 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cdp.xml +@@ -17,12 +17,12 @@ + 4096 + 6144 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +@@ -31,12 +31,12 @@ + 6144 + 8192 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml +index acdd97ec58..311bb58e6a 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml +@@ -17,12 +17,12 @@ + 4096 + 6144 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +@@ -31,12 +31,12 @@ + 6144 + 8192 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-fake-feature.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-fake-feature.xml +index 1327d85c98..d85407f0b1 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-fake-feature.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-fake-feature.xml +@@ -17,12 +17,12 @@ + 4096 + 6144 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +@@ -31,12 +31,12 @@ + 6144 + 8192 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx-twocaches.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx-twocaches.xml +index 6769bd0591..eb53eb2142 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx-twocaches.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx-twocaches.xml +@@ -17,7 +17,7 @@ + 4096 + 6144 + +- ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx.xml +index bc52480905..38ea0bdc27 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl-skx.xml +@@ -17,7 +17,7 @@ + 4096 + 6144 + +- ++ + + + +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml +index b638bbd1c9..fd854ee91e 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml +@@ -17,12 +17,12 @@ + 4096 + 6144 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +@@ -31,12 +31,12 @@ + 6144 + 8192 + +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ + + + +-- +2.43.0 diff --git a/SOURCES/libvirt-conf-node_device-Refactor-virNodeDeviceCapVPDParseCustomFields-to-fix-error-reporting.patch b/SOURCES/libvirt-conf-node_device-Refactor-virNodeDeviceCapVPDParseCustomFields-to-fix-error-reporting.patch new file mode 100644 index 0000000..eb91e09 --- /dev/null +++ b/SOURCES/libvirt-conf-node_device-Refactor-virNodeDeviceCapVPDParseCustomFields-to-fix-error-reporting.patch @@ -0,0 +1,138 @@ +From 8d84e4af4cbb93d73f4d9967f517552257f025f5 Mon Sep 17 00:00:00 2001 +Message-ID: <8d84e4af4cbb93d73f4d9967f517552257f025f5.1707394627.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 29 Jan 2024 18:26:29 +0100 +Subject: [PATCH] conf: node_device: Refactor + 'virNodeDeviceCapVPDParseCustomFields' to fix error reporting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The errors raised in virNodeDeviceCapVPDParseCustomFields were actually +ignored by continuing the parse rather than raised. + +Rather than just replace 'continue' by 'return -1' this patch refactors +the whole parser to simplify it as well as report reasonable errors. + +Parsing of individual fields is done without XPath and is extracted into +a common helper. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit ea8d864d9ecf3ee72910ccc1497244f1ef74e948) + +https://issues.redhat.com/browse/RHEL-22314 [9.4.0] +--- + src/conf/node_device_conf.c | 81 ++++++++++++++++++------------------- + 1 file changed, 40 insertions(+), 41 deletions(-) + +diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c +index d7e1a23034..0f2c341967 100644 +--- a/src/conf/node_device_conf.c ++++ b/src/conf/node_device_conf.c +@@ -953,63 +953,62 @@ virNodeDevCapMdevTypesParseXML(xmlXPathContextPtr ctxt, + return ret; + } + ++ + static int +-virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt, virPCIVPDResource *res, bool readOnly) ++virNodeDeviceCapVPDParseCustomFieldOne(xmlNodePtr node, ++ virPCIVPDResource *res, ++ bool read_only, ++ const char keyword_prefix) ++{ ++ g_autofree char *value = NULL; ++ g_autofree char *index = NULL; ++ g_autofree char *keyword = NULL; ++ ++ if (!(index = virXMLPropStringRequired(node, "index"))) ++ return -1; ++ ++ if (strlen(index) != 1) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("'%1$s' 'index' value '%2$s' malformed"), ++ node->name, index); ++ return -1; ++ } ++ ++ keyword = g_strdup_printf("%c%c", keyword_prefix, index[0]); ++ ++ if (!(value = virXMLNodeContentString(node))) ++ return -1; ++ ++ virPCIVPDResourceUpdateKeyword(res, read_only, keyword, value); ++ return 0; ++} ++ ++ ++static int ++virNodeDeviceCapVPDParseCustomFields(xmlXPathContextPtr ctxt, ++ virPCIVPDResource *res, ++ bool readOnly) + { + int nfields = -1; + g_autofree xmlNodePtr *nodes = NULL; + size_t i = 0; + +- if ((nfields = virXPathNodeSet("./vendor_field[@index]", ctxt, &nodes)) < 0) ++ if ((nfields = virXPathNodeSet("./vendor_field", ctxt, &nodes)) < 0) + return -1; + + for (i = 0; i < nfields; i++) { +- g_autofree char *value = NULL; +- g_autofree char *index = NULL; +- VIR_XPATH_NODE_AUTORESTORE(ctxt) +- g_autofree char *keyword = NULL; +- +- ctxt->node = nodes[i]; +- if (!(index = virXPathString("string(./@index[1])", ctxt)) || +- strlen(index) > 1) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _(" evaluation has failed")); +- continue; +- } +- if (!(value = virXPathString("string(./text())", ctxt))) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _(" value evaluation has failed")); +- continue; +- } +- keyword = g_strdup_printf("V%c", index[0]); +- virPCIVPDResourceUpdateKeyword(res, readOnly, keyword, value); ++ if (virNodeDeviceCapVPDParseCustomFieldOne(nodes[i], res, readOnly, 'V') < 0) ++ return -1; + } + VIR_FREE(nodes); + + if (!readOnly) { +- if ((nfields = virXPathNodeSet("./system_field[@index]", ctxt, &nodes)) < 0) ++ if ((nfields = virXPathNodeSet("./system_field", ctxt, &nodes)) < 0) + return -1; + + for (i = 0; i < nfields; i++) { +- g_autofree char *value = NULL; +- g_autofree char *index = NULL; +- g_autofree char *keyword = NULL; +- VIR_XPATH_NODE_AUTORESTORE(ctxt); +- +- ctxt->node = nodes[i]; +- if (!(index = virXPathString("string(./@index[1])", ctxt)) || +- strlen(index) > 1) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _(" evaluation has failed")); +- continue; +- } +- if (!(value = virXPathString("string(./text())", ctxt))) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _(" value evaluation has failed")); +- continue; +- } +- keyword = g_strdup_printf("Y%c", index[0]); +- virPCIVPDResourceUpdateKeyword(res, readOnly, keyword, value); ++ if (virNodeDeviceCapVPDParseCustomFieldOne(nodes[i], res, readOnly, 'Y') < 0) ++ return -1; + } + } + +-- +2.43.0 diff --git a/SOURCES/libvirt-conf-virNodeDeviceCapVPDParse-Remove-pointless-NULL-checks.patch b/SOURCES/libvirt-conf-virNodeDeviceCapVPDParse-Remove-pointless-NULL-checks.patch new file mode 100644 index 0000000..58c94cb --- /dev/null +++ b/SOURCES/libvirt-conf-virNodeDeviceCapVPDParse-Remove-pointless-NULL-checks.patch @@ -0,0 +1,47 @@ +From 15145b5ecb2e9186e42bbb295e1d44f93ff25cfb Mon Sep 17 00:00:00 2001 +Message-ID: <15145b5ecb2e9186e42bbb295e1d44f93ff25cfb.1707394627.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Wed, 24 Jan 2024 16:27:35 +0100 +Subject: [PATCH] conf: virNodeDeviceCapVPDParse*: Remove pointless NULL checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function are never called with NULL argument so the checks can be +removed. + +Signed-off-by: Peter Krempa +Reviewed-by: Ján Tomko +(cherry picked from commit fb69acf5c255f6baedefe2a2535325af8088ced5) + +https://issues.redhat.com/browse/RHEL-22314 [9.4.0] +--- + src/conf/node_device_conf.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c +index dd174d3020..d7e1a23034 100644 +--- a/src/conf/node_device_conf.c ++++ b/src/conf/node_device_conf.c +@@ -1023,9 +1023,6 @@ virNodeDeviceCapVPDParseReadOnlyFields(xmlXPathContextPtr ctxt, virPCIVPDResourc + "serial_number", "part_number", NULL}; + size_t i = 0; + +- if (res == NULL) +- return -1; +- + res->ro = virPCIVPDResourceRONew(); + + while (keywords[i]) { +@@ -1061,9 +1058,6 @@ virNodeDeviceCapVPDParseXML(xmlXPathContextPtr ctxt, virPCIVPDResource **res) + size_t i = 0; + g_autoptr(virPCIVPDResource) newres = g_new0(virPCIVPDResource, 1); + +- if (res == NULL) +- return -1; +- + if (!(newres->name = virXPathString("string(./name)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Could not read a device name from the element")); +-- +2.43.0 diff --git a/SOURCES/libvirt-domain_validate-Account-for-NVDIMM-label-size-properly-when-checking-for-memory-conflicts.patch b/SOURCES/libvirt-domain_validate-Account-for-NVDIMM-label-size-properly-when-checking-for-memory-conflicts.patch new file mode 100644 index 0000000..0cf71d0 --- /dev/null +++ b/SOURCES/libvirt-domain_validate-Account-for-NVDIMM-label-size-properly-when-checking-for-memory-conflicts.patch @@ -0,0 +1,123 @@ +From 8d48d5fe02c0afcf5bbe68e0a182ee11f9a108dc Mon Sep 17 00:00:00 2001 +Message-ID: <8d48d5fe02c0afcf5bbe68e0a182ee11f9a108dc.1708614745.git.jdenemar@redhat.com> +From: Michal Privoznik +Date: Mon, 19 Feb 2024 15:37:16 +0100 +Subject: [PATCH] domain_validate: Account for NVDIMM label size properly when + checking for memory conflicts + +As of v9.8.0-rc1~7 we check whether two devices don't +overlap (since we allow setting where a device should +be mapped to). We do this pretty straightforward, by comparing +start and end address of each device combination. +But since only the start address is given (an exposed in the +XML), the end address is computed trivially as: + + start + mem->size * 1024 + +And for majority of memory device types this works. Except for +NVDIMMs. For them the device consists of two separate +regions: 1) actual memory device, and 2) label. + +Label is where NVDIMM stores some additional information like +namespaces partition and so on. But it's not mapped into the +guest the same way as actual memory device. In fact, mem->size is +a sum of both actual memory device and label sizes. And to make +things a bit worse, both sizes are subject to alignment (either +the alignsize value specified in XML, or system page size if not +specified in XML). + +Therefore, to get the size of actual memory device we need to +take mem->size and substract label size rounded up to alignment. + +If we don't do this we report there's an overlap between two +NVDIMMs even when in reality there's none. + +Fixes: 3fd64fb0e236fc80ffa2cc977c0d471f11fc39bf +Fixes: 91f9a9fb4fc0d34ed8d7a869de3d9f87687c3618 +Resolves: https://issues.redhat.com/browse/RHEL-4452?focusedId=23805174#comment-23805174 +Signed-off-by: Michal Privoznik +Reviewed-by: Martin Kletzander +(cherry picked from commit 4545f313c23e7000451d1cec793ebc8da1a2c25f) +Signed-off-by: Michal Privoznik +--- + src/conf/domain_validate.c | 51 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 49 insertions(+), 2 deletions(-) + +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index 46479f10f2..faa7659f07 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -2225,6 +2225,53 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev) + } + + ++/** ++ * virDomainMemoryGetMappedSize: ++ * @mem: memory device definition ++ * ++ * For given memory device definition (@mem) calculate size mapped into ++ * the guest. This is usually mem->size, except for NVDIMM where its ++ * label is mapped elsewhere. ++ * ++ * Returns: Number of bytes a memory device takes when mapped into a ++ * guest. ++ */ ++static unsigned long long ++virDomainMemoryGetMappedSize(const virDomainMemoryDef *mem) ++{ ++ unsigned long long ret = mem->size; ++ ++ if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) { ++ unsigned long long alignsize = mem->source.nvdimm.alignsize; ++ unsigned long long labelsize = 0; ++ ++ /* For NVDIMM the situation is a bit more complicated. Firstly, ++ * its